Lexer意外地标记了

Mar*_*ijn 4 antlr lexer antlr3

以下非常简单的示例语法不像我预期的那样(根本没有).

Declaration :   'VAR';
Letter: ('A'..'Z');

message :   Declaration Letter+;
Run Code Online (Sandbox Code Playgroud)

我所期望的结果是,任何字母序列都会作为单个字母而形成,并且序列"VAR"将被作为单个标记.

当我查看ANTLRWorks interperter时,我看到以下结果:

  • VARA解析message -> "VAR", "A"(预期)
  • VARVA不解析(MismatchedTokenException(-1!= 5).词法分析器命中第二个VA并尝试标记Declaration.预期:message -> "VAR", "V", "A"
  • VARVPP解析message -> "VAR", "V", "P", "P"(预期)
  • VARVALL解析message -> "VAR", "VALL".

我想帮助理解这种行为,并建议我如何解决这个问题.

特别:

  • 为什么词法分析器会尝试将所有字符串标记VA为"声明",如果后跟一个字母?
  • 为什么词法分析器不会尝试使用以V?开头的所有字符串来执行此操作?
  • 如果有一个额外的角色,为什么词法分子不会尝试这样做呢?
  • 我应该如何改变这种语法来解析我的预期方式?

Bar*_*ers 5

让我们来看看你的所有4个例子:

1"VARA"

在此输入图像描述

一切都好.

2"VARVA"

"VAR"(显然)被标记为VAR,但是词法分析器"看到" "VA"并期望一个"R",而不是那里.它会发出以下错误:

line 1:5 mismatched character '<EOF>' expecting 'R'
line 1:5 required (...)+ loop did not match anything at input '<EOF>'
Run Code Online (Sandbox Code Playgroud)

并且丢弃"VA"生成的单个令牌,正如您在运行ANTLRWorks的调试器时所看到的(忽略解析中的异常,它们实际上并不存在:) :):

在此输入图像描述

你必须意识到的是,词法分析者永远不会放弃它已经匹配的东西.因此,如果词法分析器看到 "VA"并且不能匹配"R"它,那么它将查看可匹配的其他词法分析器规则"VA".但是Letter不匹配(它只匹配单个字母!)如果你Letter改为匹配多个单个字符,ANTLR将能够回退到该规则.而不是在它匹配单个字母:词法分析器不会放弃"A""VA"Letter规则匹配.没办法:这就是ANTLR的词法分析器的工作原理.

这通常不是问题,因为IDENTIFIER当关键字无法匹配时,词法分析器可能会依赖某种规则.

3"VARVPP"

在此输入图像描述

好吧:"VAR"变成了一个VAR,然后词法分析器尝试匹配"A"后面"V"但不会发生这种情况,所以词法分析器会回到Letter单一规则上"V".之后"PP"都被标记为Letters.

4"VARVALL"

"VAR"再次成为一个VAR.然后"L"in "VAL"导致词法分析器产生以下错误消息:

line 1:5 mismatched character 'L' expecting 'R'
Run Code Online (Sandbox Code Playgroud)

然后最后"L"成为Letter:

在此输入图像描述


我猜(或希望)现在回答了前3个问题,这留下了你的最终答案:

我应该如何改变这种语法来解析我的预期方式?

通过强制词法分析器首先在字符流中"VAR"向前看,如果确实存在,如果没有,只需匹配一个"V"并更改匹配的令牌的类型Letter,如下所示:

Declaration
 : ('VAR')=> 'VAR'
 |           'V'   {$type=Letter;}
 ;
Run Code Online (Sandbox Code Playgroud)

正如我之前提到的那样,请参阅此相关问答:ANTLR词法分析器根本无法预测