我面临一个模糊的情况,可以使用不同的规则解析输入字符串,我需要考虑这两个选项并为它们生成多个解析树。
为简单起见,考虑像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 ;
答案 0 :(得分:2)
ANTLR不允许您按照自己的方式进行操作。然而,原因不是模糊,而是标记化。
由于ANTLR lexing政策,“Johanson”一词总是被称为NAME:
令牌REL
将永远不会发生,因为
NAME
(最长匹配)NAME
(最长匹配)NAME
(REL
匹配,但未首先定义)回答您的第一个问题: 它不能由ANTLR解析器处理,因为它在解析之前依赖于标记化。您有两种选择:
回答您的第二个问题:
上述两种替代方案都难以解决打印相同char序列的可能解释的问题。
PEG-Parsers旨在通过设计选择第一种替代方案,如果找到有效的解释,则不会进一步探索。
ANTLR尚未设计用于驱动解析器指示的词法分析器。如果您决定重新分析姓氏,那么使用纯java找到解释可能比编写新的词法分析器/解析器更容易找到它们。
答案 1 :(得分:2)
从长篇评论中切换:
只要你定义lexemes来获取整个单词,并且有一个关于当两个被识别时lexeme获胜的策略,你就会遇到这个问题。
要避免它,你必须有不竞争的词汇。你可以做的是运行一个带有字符的GLR解析器作为lexemes;对于短输入(例如,人名),这不会是任何类型的问题。然后,您可以在语法中定义您的名称规则,而不是作为词法识别器,GLR解析器将提供所有可能的解释。
不,我不知道一个好的基于Java的GLR解析器。这里有一个很重要的列表:http://en.wikipedia.org/wiki/Comparison_of_parser_generators