View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.cpd;
5   
6   import net.sourceforge.pmd.lang.ast.TokenMgrError;
7   import net.sourceforge.pmd.lang.swift.antlr4.SwiftLexer;
8   
9   import org.antlr.v4.runtime.ANTLRInputStream;
10  import org.antlr.v4.runtime.BaseErrorListener;
11  import org.antlr.v4.runtime.Lexer;
12  import org.antlr.v4.runtime.RecognitionException;
13  import org.antlr.v4.runtime.Recognizer;
14  import org.antlr.v4.runtime.Token;
15  
16  /**
17   * The Swift Tokenizer
18   */
19  public class SwiftTokenizer implements Tokenizer {
20  
21      @Override
22      public void tokenize(SourceCode sourceCode, Tokens tokenEntries) {
23          StringBuilder buffer = sourceCode.getCodeBuffer();
24  
25          try {
26              ANTLRInputStream ais = new ANTLRInputStream(buffer.toString());
27              SwiftLexer lexer = new SwiftLexer(ais);
28  
29              lexer.removeErrorListeners();
30              lexer.addErrorListener(new ErrorHandler());
31              Token token = lexer.nextToken();
32  
33              while (token.getType() != Token.EOF) {
34                  if (token.getChannel() != Lexer.HIDDEN) {
35                      TokenEntry tokenEntry =
36                              new TokenEntry(token.getText(), sourceCode.getFileName(), token.getLine());
37  
38                      tokenEntries.add(tokenEntry);
39                  }
40                  token = lexer.nextToken();
41              }
42          } catch (ANTLRSyntaxError err) {
43              // Wrap exceptions of the Swift tokenizer in a TokenMgrError, so they are correctly handled
44              // when CPD is executed with the '--skipLexicalErrors' command line option
45              throw new TokenMgrError(
46                      "Lexical error in file " + sourceCode.getFileName() + " at line " +
47                      err.getLine() + ", column " + err.getColumn() + ".  Encountered: " + err.getMessage(),
48                      TokenMgrError.LEXICAL_ERROR);
49          } finally {
50              tokenEntries.add(TokenEntry.getEOF());
51          }
52      }
53  
54      private static class ErrorHandler extends BaseErrorListener {
55          @Override
56          public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line,
57                  int charPositionInLine, String msg, RecognitionException ex) {
58              throw new ANTLRSyntaxError(msg, line, charPositionInLine, ex);
59          }
60      }
61  
62      private static class ANTLRSyntaxError extends RuntimeException {
63          private static final long serialVersionUID = 1L;
64          private final int line;
65          private final int column;
66  
67          public ANTLRSyntaxError (String msg, int line, int column, RecognitionException cause) {
68              super(msg, cause);
69              this.line = line;
70              this.column = column;
71          }
72  
73          public int getLine() {
74              return line;
75          }
76  
77          public int getColumn() {
78              return column;
79          }
80      }
81  }