使用Antlr4解析简单模板

时间:2015-04-11 19:46:50

标签: java parsing antlr antlr4

我尝试解析像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 : ~('[')* ;

1 个答案:

答案 0 :(得分:1)

您对ANTLR解析的理解似乎不完整:

ANTLR解析严格地在ANTLR lexing之前进行。在lexing阶段,在不知道解析器规则的情况下对完整文本进行标记化。如何生成令牌的规则是:

  • 更喜欢最长的令牌
  • 如果两个相同长度的匹配项更喜欢第一个定义的标记

您有三种令牌类型(我假设还有一个额外的空格规则):

he did [something called (-> STRING)
: (-> ':')
action] (-> QUERY_CONTENT)

你想要什么:解析器应该控制应该应用哪个令牌规则。

he did (->QUERY_CONTENT) 
...

但由于存在较长的令牌匹配he did [something called,因此失败。

避免包含其他令牌的令牌

  • 将非:]的(非字母数字)字符(甚至是空白字符)添加到IDENTIFIER,会将生成的标记添加到STRING。
  • 将不是[的字符添加到STRING会将结果令牌添加到QUERY_CONTENT

有时无法避免,但它会导致难以理解的解析错误的永久风险。

如何解决此问题:

  • 重写你的语法以适应ANTLR概念(如果你想保留这种语法,这可能很难实现)
  • 优化您的语言语法(更多限制符号,非包含令牌)
  • 使用PEG解析器(半熟的,大鼠)。这些类型的解析器非常接近您的理解。