我不熟悉Antlr和解析,所以这对我来说是一个学习练习。
我正在尝试解析一种允许在某些位置自由格式文本的语言。因此,自由格式文本可以是任何单词或单词,包括该语言中的关键字——它们在该语言句子中的位置将它们定义为关键字或自由文本。
在下面的例子中,"JOB"的第一个实例是一个关键字;第二个"JOB"是自由格式文本:
JOB=(JOB)
我尝试了下面的语法,它避免了在词法分析器规则中定义语言的关键字。
grammar Test;
test1 : 'JOB' EQ OPAREN (utext) CPAREN ;
utext : UNQUOTEDTEXT ;
COMMA : ',' ;
OPAREN : '(' ;
CPAREN : ')' ;
EQ : '=' ;
UNQUOTEDTEXT : ~[a-z,()'" rnt]*? ;
SPC : [ t]+ -> skip ;
我希望通过如上所述在解析器规则中定义关键字字符串字面量,它们将仅应用于定义它们的位置。但事实似乎并非如此。测试"test1"规则(使用IDEA中的Antlr4插件),并使用上面显示的示例短语"JOB=(JOB)"(不带引号)-作为输入,我得到以下错误消息:
line 1:5 mismatched input 'JOB' expecting UNQUOTEDTEXT
因此,在为'JOB'创建隐式令牌之后,看起来Antlr在解析器语法的其他点也使用该令牌,即每当它看到'JOB'字符串时。为了测试这一点,我添加了另一个解析器规则:
test2 : 'DATA' EQ OPAREN (utext) CPAREN ;
并使用"DATA=(JOB) "进行测试"
我得到了以下错误(类似于之前):
line 1:6 mismatched input 'JOB' expecting UNQUOTEDTEXT
是否有任何方法可以要求Antlr仅在定义/引入令牌的位置强制令牌识别?
谢谢!
你所拥有的本质上是湖语法,与岛语法相反。"湖泊语法"指的是你有很多结构化的文本,然后有很多你不关心的东西。一般来说,关键是有一些词法哨兵说"进入非结构化文本区域",然后"重新进入结构化文本区域"。你的情况似乎是(……)。ANTLR有一个词法模式的概念,你想用它来处理具有不同词法结构的区域。当你看到一个"("时,你想把模式切换到一些自由形式的区域。当您在该区域看到')'时,您希望切换回默认模式。总之"mode"是你的关键词
我有一个类似的问题,关键字有时只是标识符。我是这样做的:
OnlySometimesAKeyword : 'value' ;
identifier
: Identifier // defined as usual
| maybeKeywords
;
maybeKeywords
: OnlySometimesAKeyword
// ...
;
在你的解析器规则中,简单地使用identifier
而不是Identifier
,你也可以匹配"maybe keywords"。当然,这也将在它们将成为关键字的地方匹配它们,但如果需要,您可以在解析器中检查这一点。