我目前正在尝试使用ANTLR4编写UCUM解析器。我目前的方法是将每个有效单位和前缀定义为令牌。
这是定义的令牌的一个非常小的子集。我可以将语法的简化版本作为一个例子,但似乎没有必要解决这个问题(或者指出我完全以错误的方式解决这个问题)。
MILLI_OR_METRE: 'm' ;
OSMOLE: 'osm' ;
MONTH: 'mo' ;
SECOND: 's' ;
其中一个标准测试用例是mosm
,词法分析器应该从中生成令牌流MILLI_OR_METRE OSMOLE
。不幸的是,因为ANTLR优先匹配更长的令牌,它会生成令牌流MONTH SECOND MILLI_OR_METRE
,然后导致解析器引发错误。
是否可以让ANTLR4词法分析器首先使用较短的令牌进行匹配?向MONTH
添加前瞻型规则并不是一个很好的解决方案,因为我需要考虑各种潜在的冲突(例如mol
被列为{{1}而不是MONTH LITRE
等等。)
编辑:
下面的StefanA当然是正确的;这是一个能够回溯的解析器的工作(例如,递归下降,packrat,PEG以及可能是其他各种... Coco / R是一个合理的包来做到这一点)。为了避免在另一个解析器生成器上添加依赖项(或者将项目的其他位从ANTLR移动到这个新生成器),我已经破解了这个问题:MOLE
但这并不是一个非常可扩展或可维护的解决方案,并且不会引入我尚未遇到的其他微妙问题。
答案 0 :(得分:1)
您的问题不需要较小的令牌(在这种情况下,MONTH永远不会匹配)。您需要依赖于匹配或不匹配的文本的回溯行为。正确?
ANTLR严格区分标记化和解析。因此,解决问题的每个解决方案都会像黑客一样。
然而,其他解析器生成器专门处理像您这样的问题。 Packrat Parsers(PEG)正在回溯并允许动态标记化。为此目的尝试parboiled。
答案 1 :(得分:0)
似乎问题没有正确构建。
我目前正在尝试使用ANTLR4编写UCUM解析器。我目前的方法是将每个有效单位和前缀定义为令牌。
但是,根据UCUM:
计量单位统一代码的表达式语法生成无限数量的代码,结果是无法编译所有有效单位的表。
词法分析器最期待的是对测量字符串的明确识别,而不考虑其语义值。类似地,单独的解析器将无法在诸如MONTH LITRE
和MOLE
之类的单元序列之间进行有效选择 - 两者都可以合理地应用于泄漏率 - 除非问题空间在解析器定义中受到静态约束。
启发式,结构性(明确地识别问题空间)或上下文(考虑问题空间中其他单位的相对性质),很可能需要选择正确的单位解释。
使用的最佳工具是使您处于实现消除单位字符串歧义所需的启发式的最佳位置。 Antlr 可以使用解析树步行器来完成它。这是否是适当的方法需要进一步分析。