JavaMan писал:
Я пытаюсь проанализировать исходные файлы в стиле C ++ / Java и хотел бы выделить комментарий, строковый литерал и пробел в качестве токенов.
Разве вы не должны соответствовать буквам литерала? Рассмотрим:
char c = '"';
Двойная кавычка не должна рассматриваться как начало строкового литерала!
JavaMan писал:
Короче говоря, две пары / ** / и "" будут мешать друг другу.
Ошибка, нет. Если /*
«виден» первым, он будет потреблять весь путь до первого */
. Для ввода, как:
/* comment...."comment that looks like a string literal"...more comment */
это будет означать, что двойные кавычки также потребляются. То же самое для строковых литералов: когда двойная кавычка видна первой, /*
и / или */
будут использоваться до следующего (не экранированного) "
.
Или я не так понял?
Обратите внимание, что вы можете удалить options {greedy=false;}:
из вашей грамматики до .*
или .+
, которые по умолчанию являются несмешными.
Вот способ:
grammar T;
parse
: (t=.
{
if($t.type != OTHER) {
System.out.printf("\%-10s >\%s<\n", tokenNames[$t.type], $t.text);
}
}
)+
EOF
;
ML_COMMENT
: '/*' .* '*/'
;
SL_COMMENT
: '//' ~('\r' | '\n')*
;
STRING
: '"' (STR_ESC | ~('\\' | '"' | '\r' | '\n'))* '"'
;
CHAR
: '\'' (CH_ESC | ~('\\' | '\'' | '\r' | '\n')) '\''
;
SPACE
: (' ' | '\t' | '\r' | '\n')+
;
OTHER
: . // fall-through rule: matches any char if none of the above matched
;
fragment STR_ESC
: '\\' ('\\' | '"' | 't' | 'n' | 'r') // add more: Unicode esapes, ...
;
fragment CH_ESC
: '\\' ('\\' | '\'' | 't' | 'n' | 'r') // add more: Unicode esapes, Octal, ...
;
, который можно проверить с помощью:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
String source =
"String s = \" foo \\t /* bar */ baz\";\n" +
"char c = '\"'; // comment /* here\n" +
"/* multi \"no string\"\n" +
" line */";
System.out.println(source + "\n-------------------------");
TLexer lexer = new TLexer(new ANTLRStringStream(source));
TParser parser = new TParser(new CommonTokenStream(lexer));
parser.parse();
}
}
Если вы запустите класс выше, на консоль выводится следующее:
String s = " foo \t /* bar */ baz";
char c = '"'; // comment /* here
/* multi "no string"
line */
-------------------------
SPACE > <
SPACE > <
SPACE > <
STRING >" foo \t /* bar */ baz"<
SPACE >
<
SPACE > <
SPACE > <
SPACE > <
CHAR >'"'<
SPACE > <
SL_COMMENT >// comment /* here<
SPACE >
<
ML_COMMENT >/* multi "no string"
line */<