java - 如何为 ANTLR 中的模糊输入生成多个解析树

标签 java parsing antlr antlr4

我面临一个模棱两可的情况,输入字符串可以使用不同的规则进行解析,我需要考虑这两个选项并为它们生成多个解析树。

为简单起见,考虑像“Alber Johanson”这样的人名,这个名字可以解析为

(fullName (firstName Alber) (lastName Johanson)) 

或解析为

(fullName (firstName Alber) (lastName Johan) (relation son)) 

首先,如何配置规则来处理第二种情况?因为它是第二个字符串的一部分,而不是单独的标记。

其次,如何为输入字符串的所有可能选项生成解析树?

更新

这是我的语法示例,它只能用于解析第一种情况而不能用于第二种情况

fullName: firstName lastName | firstName lastName relation;
firstName: NAME;
lastName: NAME;
relation: REL;

NAME: ('a'..'z'|'A'..'Z')+;
REL: 'son';

WHITESPACE : ('\t' | ' ' | '\r' | '\n'| '\u0020' | '\u000C' )+ -> skip ;

最佳答案

ANTLR 不允许您按照自己的方式进行操作。然而,原因不是歧义,而是分词器。

由于 ANTLR 的词法分析策略,“Johanson”这个词总是被词法分析为 NAME:

  • 返回匹配最长的Token
  • 如果两个标记匹配的长度相同,则首选第一个定义的

token REL 永远不会出现,因为

  • 任何带有后缀“son”的单词都是NAME(最长匹配)
  • 任何前缀为“son”的词都是NAME(最长匹配)
  • 然而,一个孤立的单词 'son' 是一个 NAME(REL 匹配但未首先定义)

第一个问题的答案: 它不能由 ANTLR 解析器处理,因为它依赖于解析前的标记化。您有两个选择:

  • 使用解析器生成器允许您对解析器进行标记化(PEG 解析器就像半熟的,老鼠应该这样做)
  • 丢弃标记 REL,并在访问解析树时重新解析姓氏

第二个问题的答案:

上述两种选择都很难解决打印同一字符序列的可能解释的问题。

PEG-Parsers 被设计为优先选择第一个替代方案,如果找到有效的解释,它不会进一步探索。

ANTLR 还没有被设计用来驱动由解析器引导的词法分析器。如果您决定重新解析姓氏,使用纯 Java 查找解释可能比编写新的词法分析器/解析器来查找它们更容易。

关于java - 如何为 ANTLR 中的模糊输入生成多个解析树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29595137/

相关文章:

javascript - Jison:为 AND 和 OR 生成具有多个子节点的 AST 节点

java - ANTLR4 验证用户定义类型匹配

java - 为什么首选 Java 类的接口(interface)?

java - Lucene 搜索查询中的嵌套禁止/要求运算符

java - 用java为nutch编写代码

regex - 贪心 block ()* 包含通配符

gradle - IntelliJ 找不到 ANTLR 生成的源

java - 在多维数组中 move 对象

java - 如何理解这段代码片段的错误消息?

java - 是否可以在 libgdx Android 项目中使用 RxJava?