antlr4两个lexer规则匹配相同的字符串
我目前正在使用antlr4构建解析器,但我遇到了一个问题,我尽了最大努力但没有解决。你能帮我解释并解决它吗antlr4两个lexer规则匹配相同的字符串,antlr,antlr4,lexer,Antlr,Antlr4,Lexer,我目前正在使用antlr4构建解析器,但我遇到了一个问题,我尽了最大努力但没有解决。你能帮我解释并解决它吗 # grammer file : PluginDoc.g4: grammer PluginDoc pluginDef : pluginName | pluginDesc; pluginName : PluginName IDENTIFIER; pluginDesc : PluginDesc TEXT; PluginName '@pluginName' PluginDesc '@plu
# 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
如果我将标识符放在文本之前,我将得到“不匹配的输入'abc'预期文本”
如果我将文本放在标识符之前,我将得到“不匹配的输入'kafka'预期标识符”
看起来标识符和文本都匹配了,我怎么才能只匹配pluginName中的标识符而只匹配pluginDesc中的文本呢?首先,您发布的语法中有几个错误: 文件头应该指定语法,而不是语法。你的Lexer标记PluginName和PluginDesc前面没有冒号,也没有分号来终止它们。这也是一条(不成文的?)规则,将解析器规则全部写为小写,将lexer规则全部写为大写
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;
接下来,您的文本
和标识符
冲突出现问题。当字符流由Lexer标记时,kafka
和abc
可以是标识符
和文本
标记。由于Lexer-lexes是自上而下的,它们都被标记为语法中的whateve-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
解析器规则更改为
pluginDef : (pluginName | pluginDesc)* EOF;
因为我的印象是,您希望同时输入@pluginName X
和@pluginDesc Y
,并识别它们。如果情况并非如此,请随意更改回以前的状态
在您的示例输入上,由上面修改的语法生成的结果AST:
您也可以使用文本文件作为输入来运行此操作。只需对两者使用
text
,然后在后处理阶段验证标识符名称。EOF
是什么意思?@GaryGauh-EOF是内置的文件结尾标识符。如果输入是一个文件,则可以是文件的文本结尾,也可以是CTRL-Z/D in终端,具体取决于您的操作系统。举个例子,如果没有它,它可能会很好地工作,但经验告诉我要把它放在那里,以避免以后出现问题。