Antlr Lexer标记化

Antlr Lexer标记化,antlr,antlr3,lexer,Antlr,Antlr3,Lexer,以下极为简单的示例语法并不像我所期望的那样(完全) 因此,我所期望的是,任何字母序列都将作为单个字母进行lex,而序列“VAR”将作为单个标记进行lex 当我查看ANTLRWorks interperter时,我看到以下结果: VARA解析为消息->“VAR”,“A”(预期) VARVA不解析(不匹配的TokenException(-1!=5)。lexer点击第二个VA,并尝试标记声明。预期:消息->“VAR”、“V”、“A” VARVPP解析为消息->“VAR”、“V”、“P”、“P”(预期

以下极为简单的示例语法并不像我所期望的那样(完全)

因此,我所期望的是,任何字母序列都将作为单个字母进行lex,而序列“VAR”将作为单个标记进行lex

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

  • VARA
    解析为
    消息->“VAR”,“A”
    (预期)
  • VARVA
    不解析(不匹配的TokenException(-1!=5)。lexer点击第二个
    VA
    ,并尝试标记
    声明
    。预期:
    消息->“VAR”、“V”、“A”
  • VARVPP
    解析为
    消息->“VAR”、“V”、“P”、“P”
    (预期)
  • VARVALL
    解析为
    消息->“VAR”,“VALL”
我想要一些帮助来理解这种行为,并提出一个建议如何解决这个问题

具体而言:

  • 如果后面跟一个字母,为什么lexer会尝试将所有以
    VA
    开头的字符串标记到声明中
  • 为什么lexer不尝试对所有以
    V
    开头的字符串执行此操作
  • 如果还有一个额外的字符,lexer为什么不尝试这样做呢
  • 我应该如何更改此语法以按预期的方式进行分析

lexer并没有真正执行前瞻,只有解析器执行前瞻;您可以在中阅读更多关于它的内容。因此,这里的问题是,一旦lexer无法匹配
VAR
,它就会尝试匹配到目前为止得到的-
VA
,并且没有匹配标记,因为字母不能匹配两个字符,只有一个

对于解决方案,一个简单的方法是将其更改为单个令牌:

Message :   'VAR' ('A'..'Z')+;
message :   Message;

不过,它不会为每个字母提供不同的标记。

让我们看一下您的4个示例:

1“瓦拉”

好的

2“瓦瓦”
“VAR”
被(显然)标记为
VAR
,但随后lexer“看到”
“VA”
,并期望出现一个
“R”
,但不在那里。它发出以下错误:

line 1:5 mismatched character '<EOF>' expecting 'R'
line 1:5 required (...)+ loop did not match anything at input '<EOF>'
然后最后一个
“L”
变成一个
字母


我想(或希望)前3个问题现在已经回答了,剩下最后的答案:

我应该如何更改此语法以按预期的方式进行分析

如果前面确实有
“VAR”
,则强制lexer首先在字符流中向前看,如果前面没有,则只需匹配单个
“V”
,并将匹配标记的类型更改为
字母,如下所示:

Declaration
 : ('VAR')=> 'VAR'
 |           'V'   {$type=Letter;}
 ;

正如我在回答之前所提到的,请看这个相关的问答:

啊,我现在明白你的意思了。是的,你是对的:你的建议确实适用于OP发布的4个例子。但我想OP真正的问题是如何使输入像
“VA”
,然后是
“R”以外的内容
标记为
字母
s,而不是(失败的)
VAR
标记。再次为所有混淆表示抱歉。
line 1:5 mismatched character 'L' expecting 'R'
Declaration
 : ('VAR')=> 'VAR'
 |           'V'   {$type=Letter;}
 ;