使用 Antlr4 解析简单模板

Parsing simple template with Antlr4

我正在尝试解析像 he did [something called :action] 这样的表达式,其中 action 是一个变量,括号表示该块是可选的。如果括号内的变量之一丢失,那么我需要用 nothing.

这样的占位符替换整个块

我认为逻辑部分很简单,因为我熟悉访问者机制,但我无法解析字符串。

我尝试了以下解析器,但它生成错误节点而不是可选参数。我找不到问题,谁能看看这个解析脚本并告诉我我做错了什么?

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 词法分析。在词法分析阶段,完整的文本在不知道解析器规则的情况下被标记化。生成token的规则是:

  • 喜欢最长的令牌
  • 如果两个匹配长度相同,则首选第一个定义的标记

你有三种标记类型(我假设还有一个额外的空白规则):

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

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

he did (->QUERY_CONTENT) 
...

但这失败了,因为存在更长的令牌匹配 he did [something called

避免包含其他标记的标记

  • 将不是 :] 的(非字母数字)字符(甚至是空格)添加到 IDENTIFIER 中,使生成的标记成为 STRING。
  • 将非 [ 的字符添加到 STRING 会使生成的标记成为 QUERY_CONTENT

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

如何解决:

  • 重写你的语法以适应 ANTLR 概念(如果你想保留这种语法,这可能很难实现)
  • 改进您的语言语法(更多限制符号、非归并标记)
  • 使用 PEG 解析器(煮熟的大鼠)。这些类型的解析器非常接近您的理解。