【发布时间】:2011-05-30 23:28:31
【问题描述】:
我被一个非常简单的语法困住了。谷歌搜索和书籍阅读没有帮助。我最近开始使用 ANTLR,所以这可能是一个非常简单的问题。
我正在尝试使用 ANTLR v3 编写一个非常简单的 Lexer。
grammar TestLexer;
options {
language = Java;
}
TEST_COMMENT
: '/*' WS? TEST WS? '*/'
;
ML_COMMENT
: '/*' ( options {greedy=false;} : .)* '*/' {$channel=HIDDEN;}
;
TEST : 'TEST'
;
WS : (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel=HIDDEN;}
;
测试类:
public class TestParserInvoker {
private static void extractCommandsTokens(final String script) throws RecognitionException {
final ANTLRStringStream input = new ANTLRStringStream(script);
final Lexer lexer = new TestLexer(input);
final TokenStream tokenStream = new CommonTokenStream(lexer);
Token t;
do {
t = lexer.nextToken();
if (t != null) {
System.out.println(t);
}
} while (t == null || t.getType() != Token.EOF);
}
public static void main(final String[] args) throws RecognitionException {
final String script = "/* TEST */";
extractCommandsTokens(script);
}
}
因此,当测试字符串为“/* TEST */”时,词法分析器会按预期生成两个标记。一种是 TEST_COMMENT 类型,另一种是 EOF。一切正常。
但如果测试字符串最后包含一个额外的空格:“/* TEST */” 词法分析器会生成三个标记:ML_COMMENT、WS 和 EOF。
为什么第一个令牌得到 ML_COMMENT 类型?我认为如何检测令牌的方式仅取决于语法中词法分析器规则的优先级。当然,它不应该依赖于以下标记。
感谢您的帮助!
附:我可以使用词法分析器选项 filter=true - 令牌将获得正确的类型,但这种方法需要在令牌定义中进行额外的工作。老实说,我不想使用这种类型的词法分析器。
【问题讨论】:
-
+1 我花了一秒钟来解析,但这似乎“奇怪”。
-
你把
WS?放在另一个规则中是为了什么?在隐藏频道或被跳过时,它永远不会出现在另一个规则中。 -
@Kay 我指定了可以包含任意数量的空格 (WS) 的令牌 TEST_COMMENT。在解析阶段,我自己不需要 WS 令牌。
-
@Kay,
WS只有在它自己的令牌时才会被放入隐藏通道。当另一个规则的一部分时,它匹配的空白字符位于 那个 特定令牌的通道上。 -
和@Bart:我的错,感谢您解决这个问题。 :)