2

目前我在 Scala 2.9.2 中使用 Scala PackratParsers 产品如下所示:

  lazy val andExpression: PackratParser[Expression] = equalityExpression | expression ~ "&" ~ expression ^^ {
      case x ~"&"~y => AndExpr(x,y)
    }

  lazy val orExpression: PackratParser[Expression] = andExpression | ( expression ~ "|" ~ expression ) ^^ {
      case x ~"|"~y => OrExpr(x,y)
    }

它适用于以下输入

"a & b", "a | c", "(a & b) | c"

但是,我刚刚发现我的解析器太贪婪了。

"a && b", "a &&& b", "a ||||| b"

它解析得很好。我相信我只是错过了组合器上的显式匹配器计数。确切地说是什么e ~ "&".{1} ~ e?如何只匹配一个运算符的出现,仅此而已?

我正在编写的解析器将 Expression 类似于 XPath

lazy val absolutePath: PackratParser[NodePath] = "/" ~ relativePath ^^ {
    case "/" ~ rel => NodePath( rel.nodeExpr, true );

  }  

  lazy val relativePath: PackratParser[NodePath] = repsep( nodeExpression , "/" ) ^^ {
    case x => 
        if ( debug) printf("x=%s NodePath\n",x ); 
        NodePath( x , false )

你是对的。

   lazy val nodeExpression: PackratParser[Token] = qname | variable | step 

   lazy val expression = orExpression | nodeExpression | variable | literal | function | ...

既然你可以有空NodePath( List[QName]() ),那么“是的!” 表达式是空的,因此“x &”和“& x”被成功解析。因此我的解析器显得贪婪。

让我重新表述这个问题,我如何确保relativeExpression至少包含一个QName

本质上,字符串集( "x" , "/x", "x/y", "/x/y", ... )应该是有效的 XPath 类表达式,但不是""?;-)

4

1 回答 1

3

"&"并且"|"只匹配一个字符。我能想到的唯一解释是它expression可以是空的,也可以是,它本身&|.

于 2012-07-25T22:33:31.417 回答