【问题标题】:How to generate multiple parse trees for ambiguous input in ANTLR如何在 ANTLR 中为不明确的输入生成多个解析树
【发布时间】:2015-04-12 22:00:01
【问题描述】:

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

为简单起见,考虑到像“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 ;

【问题讨论】:

  • 回答您关于如何配置规则的问题这完全是您的(应用程序)决定(要求)!我们至少需要知道在您的应用程序中应该如何拆分名称? Johanson 应该分为 Johanson 吗?还有什么规则?我们需要更多地了解您为开发您的应用程序所做的尝试。
  • @user3320018 我用我拥有的语法更新了我的问题
  • 您想以不同的方式处理这些案例,还是为什么要生成多个解析树?
  • @CoronA 的答案是正确的;你不能做你想做的事,但那是因为词法分析器。您有一个更深层次的问题,即产生多个解析解释。 ANTLR 不是为此而设计的,弯腰这样做可能非常困难。您可以考虑改用 GLR 解析器;它们旨在产生所有可能的解析。 GLR 解析器不会解决您的词法分析问题;你需要先决定你想做什么。
  • @AdrianLeonhard 是的,我想收集名称结构的所有可能选项,以便稍后在我的应用程序中处理

标签: java parsing antlr antlr4


【解决方案1】:

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

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

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

令牌REL 永远不会出现,因为

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

回答您的第一个问题: ANTLR 解析器无法处理它,因为它依赖于解析前的标记。你有两个选择:

  • 使用解析器生成器允许您对解析器定向进行标记(PEG 解析器,如 parboiled,老鼠应该这样做)
  • 丢弃令牌 REL,并在访问解析树时重新解析姓氏

回答你的第二个问题:

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

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

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

【讨论】:

  • 感谢您详尽的回答。我会尝试检查 PEG 解析器。
【解决方案2】:

从一长串 cmets 切换:

只要你定义词位来拾取整个单词,并且有一个策略来确定当两个被识别时哪个词位获胜,你就会遇到这个问题。

为避免这种情况,您必须使用不竞争的词位。你可以做的是运行一个以 characters 作为词位的 GLR 解析器;对于简短的输入(例如人名),这不会是任何问题。然后您可以在语法中定义您的名称规则,而不是作为词位识别器,GLR 解析器将提供所有可能的解释。

不,我不知道有什么好的基于 Java 的 GLR 解析器。这里有一个很大的列表:http://en.wikipedia.org/wiki/Comparison_of_parser_generators

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多