我正在尝试解析像he did [something called :action]
这样的表达式,其中action是一个变量,括号表示块是可选的。如果括号内的一个变量丢失,那么我需要用像nothing
这样的占位符来替换整个块。
我认为逻辑部分很简单,因为我熟悉访问者机制,但我无法解析字符串。
我尝试了下面的解析器,但它生成的是错误节点,而不是optionalParameter。我找不到问题,有人能看看这个解析脚本,告诉我我做错了什么吗?
grammar NamedParam;
query: (QUERY_CONTENT optionalParameter)*;
optionalParameter: '[' (STRING namedParameter)* ']';
namedParameter: ':' IDENTIFIER;
IDENTIFIER
: (ALPHANUMERIC)+;
fragment ALPHANUMERIC
: [A-Za-z0-9];
STRING : ~(':' | ']')* ;
QUERY_CONTENT : ~('[')* ;
您对ANTLR解析的理解似乎不完整:
ANTLR语法分析严格遵循ANTLR词法分析。在词法分析阶段,在不了解语法分析器规则的情况下,对完整的文本进行标记。如何生成令牌的规则是:
- 更喜欢最长的令牌
- 在两个匹配具有相同长度的情况下,首选第一个定义的令牌
您有三种令牌类型(我假设还有一个额外的空白规则):
he did [something called (-> STRING)
: (-> ':')
action] (-> QUERY_CONTENT)
您想要什么:解析器应该控制应该应用哪个令牌规则。
he did (->QUERY_CONTENT)
...
但是这失败了,因为存在较长的令牌匹配CCD_。
避免包含其他代币的代币
- 在和IDENTIFIER中添加一个不是
:
或]
的(非字母数字)字符(甚至是空格)会使生成的令牌成为字符串 - 将非
[
的字符添加到STRING会使生成的令牌成为QUERY_CONTENT
有时这是不可避免的,但它会导致难以理解的解析错误的永久风险。
如何解决此问题:
- 重写语法以适应ANTLR概念(如果你想保留这种语法,这可能很难实现)
- 完善你的语言语法(更多的限制符号,非包含标记)
- 使用PEG解析器(煮熟的老鼠)。这些类型的解析器非常接近您的理解