我面临一个模棱两可的情况,其中可以使用不同的规则来解析输入字符串,我需要考虑这两个选项并为其生成多个解析树.
为了简单起见,考虑一个人的名字,例如“ 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:
>返回匹配时间最长的令牌
>如果两个令牌匹配的长度相同,则首选第一个定义的令牌
令牌REL将永远不会发生,因为
>任何后缀为“ son”的单词均为NAME(最长匹配)
>任何以“ son”为前缀的单词都是NAME(最长匹配)
>但一个孤立的单词“儿子”是一个名字(REL匹配但未首先定义)
回答第一个问题:
它不能由ANTLR解析器处理,因为它依赖于解析之前的标记化.您有两种选择:
>使用解析器生成器,使您可以对定向的解析器进行标记化(PEG解析器如煮熟的,老鼠应该这样做)
>丢弃令牌REL,并在访问解析树时解析姓氏
回答第二个问题:
上面的两个选择都很难解决打印相同字符序列的可能解释的问题.
PEG解析器旨在通过设计偏爱第一个替代方案,因此,如果找到有效的解释,它将不会进一步进行探讨.
ANTLR尚未设计成驱动解析器指示的词法分析器.如果您决定重新解析姓氏,那么使用纯Java来查找解释可能比编写新的词法分析器/解析器来查找它们更容易.