Вместо использования синтаксического анализатора, который анализирует весь исходный файл Java, или написания чего-то самостоятельно, анализирующего только те части, которые вам интересны, вы можете использовать какой-нибудь сторонний инструмент, например ANTLR.
ANTLR имеет возможность определять только те токены, которые вам интересны (и, конечно, токены, которые могут испортить ваш поток токенов, например многострочные комментарии и литералы строк и символов). Таким образом, вам нужно только определить лексер (другое слово для токенизатора), который правильно обрабатывает эти токены.
Это называется грамматикой. В ANTLR такая грамматика может выглядеть так:
lexer grammar FuzzyJavaLexer;
options{filter=true;}
SingleLineComment
: '//' ~( '\r' | '\n' )*
;
MultiLineComment
: '/*' .* '*/'
;
StringLiteral
: '"' ( '\\' . | ~( '"' | '\\' ) )* '"'
;
CharLiteral
: '\'' ( '\\' . | ~( '\'' | '\\' ) )* '\''
;
Сохраните все вышеперечисленное в файле с именем FuzzyJavaLexer.g
. Теперь скачайте ANTLR 3.2 здесь и сохраните его в той же папке, что и файл FuzzyJavaLexer.g
.
Выполнить следующую команду:
java -cp antlr-3.2.jar org.antlr.Tool FuzzyJavaLexer.g
, который создаст FuzzyJavaLexer.java
исходный класс.
Конечно, вам нужно протестировать лексер, что вы можете сделать, создав файл с именем FuzzyJavaLexerTest.java
и скопировав в него приведенный ниже код:
import org.antlr.runtime.*;
public class FuzzyJavaLexerTest {
public static void main(String[] args) throws Exception {
String source =
"class Test { \n"+
" String s = \" ... \\\" // no comment \"; \n"+
" /* \n"+
" * also no comment: // foo \n"+
" */ \n"+
" char quote = '\"'; \n"+
" // yes, a comment, finally!!! \n"+
" int i = 0; // another comment \n"+
"} \n";
System.out.println("===== source =====");
System.out.println(source);
System.out.println("==================");
ANTLRStringStream in = new ANTLRStringStream(source);
FuzzyJavaLexer lexer = new FuzzyJavaLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
for(Object obj : tokens.getTokens()) {
Token token = (Token)obj;
if(token.getType() == FuzzyJavaLexer.SingleLineComment) {
System.out.println("Found a SingleLineComment on line "+token.getLine()+
", starting at column "+token.getCharPositionInLine()+
", text: "+token.getText());
}
}
}
}
Затем скомпилируйте FuzzyJavaLexer.java
и FuzzyJavaLexerTest.java
, выполнив:
javac -cp .:antlr-3.2.jar *.java
и, наконец, выполните файл FuzzyJavaLexerTest.class
:
// *nix/MacOS
java -cp .:antlr-3.2.jar FuzzyJavaLexerTest
или
// Windows
java -cp .;antlr-3.2.jar FuzzyJavaLexerTest
, после чего вы увидите следующее сообщение:
===== source =====
class Test {
String s = " ... \" // no comment ";
/*
* also no comment: // foo
*/
char quote = '"';
// yes, a comment, finally!!!
int i = 0; // another comment
}
==================
Found a SingleLineComment on line 7, starting at column 2, text: // yes, a comment, finally!!!
Found a SingleLineComment on line 8, starting at column 13, text: // another comment
Довольно просто, а? :)