【问题标题】:Scala - Combinator Parsing, order of alternatives seems to matterScala - 组合器解析,替代品的顺序似乎很重要
【发布时间】:2015-03-03 10:58:17
【问题描述】:

我对 Scala 比较陌生,我正在尝试掌握组合子解析。所以我有一些代码可以解析逻辑原子(一阶逻辑中的谓词),如p(x,y,z)p(x,1,q(a,b,c),z)。我有这么一小段代码:

class Logic extends JavaTokenParsers {
    def functor: Parser[Any] = ident
    def term: Parser[Any] = predicate | ident | floatingPointNumber
    def predicate: Parser[Any] = functor~"("~repsep(term,",")~")"  
}

Functor 是谓词符号,如p(x,y,z) 中的pterm 是常量或变量,如1x,或predicatepredicate 是复合词如p(x,y,z)。此代码按原样工作正常,但如果我更改在term 解析器中声明替代项的顺序,则会出现问题。也就是说,如果我像

这样编写 term 解析器
def term: Parser[Any] = ident | floatingPointNumber | predicate

predicate 是这里的最后一个替代方案,而它之前是第一个),然后它无法解析像 p(x,1,q(a,b,c),z) 这样的“嵌套”表达式(虽然它仍然适用于像 p(x,y,z) 这样的“平面”表达式)。有人可以指出我在这里缺少什么吗?

非常感谢

【问题讨论】:

    标签: scala parsing


    【解决方案1】:

    订单事项

    原因是A | B 将首先尝试满足A,并且仅当A 失败时才尝试B

    这与正则表达式(或一般的上下文无关文法)中的| 不同。

    在这种情况下,"p(x,1,q(a,b,c),z)"p 满足 ident,因此不会匹配其他替代方案(并且没有回溯)。

    因此,在具有冲突前缀的替代方案中,您可以将接受较长字符串的替代方案放在第一位(或者您知道会导致满足更多短语的替代方案)。

    最长替代匹配

    请注意,您可以使用||| 组合器:

    def term: Parser[Any] = ident ||| floatingPointNumber ||| predicate
    

    根据Scala docs||| 是一个解析器组合器,用于匹配具有最长匹配组合的备选方案。

    【讨论】:

    • 好的,这真的很有帮助,我不知道 ||| 组合器。非常感谢
    【解决方案2】:

    我假设您尝试通过 logic.parse(logic.term, "p(x,1,q(a,b,c),z)") 进行解析。

    事实上,备选方案的顺序确实很重要,因为解析器将选择第一个备选方案来匹配给定的输入。在您的情况下,p 匹配 ident 定义。然后解析器将返回一个包含匹配项的ParseResult(在您的情况下键入Any)和输入的其余部分,在您的情况下为(x,1,q(a,b,c),z)

    【讨论】:

    • 实际上我试图通过predicate 解析器进行解析。但没关系,我现在明白了。非常感谢您的回答
    猜你喜欢
    • 2015-03-25
    • 2014-12-18
    • 1970-01-01
    • 2012-09-28
    • 2013-08-03
    相关资源
    最近更新 更多