我正在编写一阶条件的解析器。我正在使用 Scala 和 scala-parser-combinators 库。效果很好,但我发现了这个问题。
这里,我报告否定子句(例如:not predicate(p1))。它使用递归,调用 fol_condition,即 fol 条件的根级别规则:
def fol_negation : Parser[Negation] = "not"~fol_condition ^^ {case _~sub => Negation(sub)}
因此,像“not predicate(p1)”这样的字符串会产生正确的结果 Negation(Predicate("predicate",...)) 但是,当我解析像“note(p2)”这样的字符串时,它应该生成一个 Predicate("note",...);相反,它返回 Negation(Predicate(a,...))。换句话说,解析器会忽略“not”和后面的 fol_condition 之间是否有空格。
这不是期望的行为。我会告诉解析器“not a”与“nota”不同,因为两者之间有一个空格。
我该如何解决这个问题?
这与空格无关。这是关于保留关键字和标识符之间的优先级。
not(P(x))
和note(y)
中都没有空格,但问题是一样的。
您不想强迫用户在每个
not
之后键入空格,因为 not (P(x) and Q(y))
会很尴尬。
您可能会尝试做什么:
A. 重新排序语法,使所有以标识符开头的规则排在第一位;那么
note(y)
被解析为 note
-标识符的分支将首先被取,问题就消失了;为此,您显然必须从有效标识符集中排除所有保留关键字。
B. 如果您只是想要快速修复,请使用像
"not(?=\W)".r
这样的前瞻正则表达式而不是固定字符序列 "not"
,并使用 not
规则(以及所有其他与关键字相关的规则)在 identifier
规则之前。