antlr4两个词法分析器匹配相同的字符串

时间:2017-09-16 08:19:25

标签: antlr antlr4 lexer

我目前正在使用antlr4来构建解析器,但我遇到了一个问题,我尽我所能但却没有弄清楚。你能帮我解释一下吗?

# grammer file : PluginDoc.g4:

grammer PluginDoc

pluginDef : pluginName | pluginDesc;
pluginName : PluginName IDENTIFIER;
pluginDesc : PluginDesc TEXT;

PluginName '@pluginName'
PluginDesc '@pluginDesc'

IDENTIFIER : [a-zA-Z_]+;
TEXT : ~( ' ' | '\n' | '\t' )+;

input content is: 
@pluginName kafka
@pluginDesc abc

如果我在TEXT之前放置IDENTIFIER,我会得到"不匹配的输入' abc'期待TEXT" 如果我在IDENTIFIER之前放置TEXT,我会得到"不匹配的输入' kafka'期待IDENTIFIER"

看起来IDENTIFIER和TEXT都匹配,我怎样才能匹配pluginName中的IDENTIFIER并且只匹配pluginDesc中的TEXT?

1 个答案:

答案 0 :(得分:2)

首先,您发布的语法中有几个错误:

文件的标题应指定语法,而不是 grammer 。你的Lexer令牌PluginName和PluginDesc在它们前面没有冒号和分号来终止它们。它也是一个(不成文的?)规则,将解析器规则编写为全部小写,将词法分析器规则编写为全部大写。

grammar PluginDoc;

pluginDef : pluginName | pluginDesc;
pluginName : PLUGIN_NAME IDENTIFIER;
pluginDesc : PLUGIN_DESC TEXT;

PLUGIN_NAME : '@pluginName';
PLUGIN_DESC : '@pluginDesc';

IDENTIFIER : [a-zA-Z_]+;
TEXT : ~( ' ' | '\n' | '\t' )+;

我在测试你的语法时遇到的一些问题是由于未处理的空白。首先,您应该包含一个Lexer规则,以便在所有其他Lexer规则之后跳过文件末尾的空格。

WS: [ \n\t\r]+ -> skip;

接下来,您的TEXTIDENTIFIER互相冲突时出现问题。当Lexer对字符流进行标记时,kafkaabc可以是IDENTIFIERTEXT令牌。由于Lexer以自上而下的方式使用lexes,因此它们都被标记为whate,Lexer规则在你的语法中排在第一位。这会导致您遇到的错误 - 无论您定义什么,因为第二个规则在解析器中无法匹配,因为它不是作为令牌发送的。

正如Lucas建议的那样,您应该将这两者都匹配为TEXT,然后在监听器/访问者中检查输入的有效性。

grammar PluginDoc;

pluginDef : (pluginName | pluginDesc)* EOF;
pluginName : PLUGIN_NAME TEXT;
pluginDesc : PLUGIN_DESC TEXT;

PLUGIN_NAME: '@pluginName';
PLUGIN_DESC: '@pluginDesc';

TEXT : ~[ \r\n\t]+;

WS: [ \r\n\t]+ -> skip;

我还将pluginDef Parser规则更改为

pluginDef : (pluginName | pluginDesc)* EOF;

因为我的印象是您希望同时输入@pluginName X@pluginDesc Y并识别它们。如果不是这种情况,请随时改回以前的状态。

由您的样本输入上面的修改语法生成的结果AST: enter image description here

您也可以使用文本文件作为输入来运行它。