我对ANTLR很新,我遇到了一个问题。
我有一个语法,我正在尝试编写一种语言,其中包括以相同注释标识符开头的单行注释和语言指令。例如:
--This is a comment. What follows is a directive with a parameter
--directive:param
指令将始终采用该格式 - 两个短划线字符后跟命令,冒号和单个参数。
我想让词法分析器忽略实际的注释(将其发送到隐藏的通道),但是将指令标记化。我有以下词法规则:
DCOMMAND : DATABASE;
fragment DATABASE : D A T A B A S E;
fragment COMMENTSTART : '--';
LINE_COMMENT : COMMENTSTART ~(DCOMMAND|('\n'|'\r')*) {$channel=HIDDEN;};
fragment A : ('a'|'A');
fragment B : ('b'|'B');
fragment C : ('c'|'C');
fragment D : ('d'|'D');
....
现在只有一个指令:'数据库'。 DCOMMAND令牌最终可能代表几个关键字。问题是我的词法分析器总是将以“ - ”开头的任何东西推入隐藏的通道。如何使LINE_COMMENT标记与指令不匹配?或者我是否必须将评论处理移到解析器中?
答案 0 :(得分:3)
AFAIK,没有一些手动代码就没有办法在你的词法分析器语法中处理这个问题(恕我直言,比向解析器推广评论更好!)。
你能做的是:
'--'
true
是指令的一部分时,让此方法返回'--'
true
false
skip()
快速演示:
grammar T;
@lexer::members {
private boolean directiveAhead() throws MismatchedTokenException {
StringBuilder b = new StringBuilder();
for(int ahead = 1; ; ahead++) {
// Grab the next character from the input.
int next = input.LA(ahead);
// Check if we're at the EOL.
if(next == -1 || next == '\r' || next == '\n') {
break;
}
b.append((char)next);
}
if(b.toString().trim().matches("\\w+:\\w+")) {
// Do NOT let the lexer consume all the characters, just return true!
return true;
}
else {
// Let the lexer consume all the characters!
this.match(b.toString());
return false;
}
}
}
parse
: directive EOF
;
directive
: DIRECTIVE_START IDENTIFIER COL IDENTIFIER
;
IDENTIFIER
: ('a'..'z' | 'A'..'Z')+
;
DIRECTIVE_START
: '--' { if(!directiveAhead()) skip(); }
;
COL
: ':'
;
SPACES
: (' ' | '\t' | '\r' | '\n')+ {skip();}
;