我目前正在使用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?
答案 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;
接下来,您的TEXT
和IDENTIFIER
互相冲突时出现问题。当Lexer对字符流进行标记时,kafka
和abc
可以是IDENTIFIER
和TEXT
令牌。由于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
并识别它们。如果不是这种情况,请随时改回以前的状态。
您也可以使用文本文件作为输入来运行它。