2012-07-25 37 views
2

目前我使用Scala的PackratParsers斯卡拉2.9.2 生產看起來是這樣的:斯卡拉PacktRat分析器限制操作正好一個

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?如何恰好匹配運營商的一個事件,只有一件事,而不是什麼?

,我同樣對待寫作的表達,以一個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]())那麼「是啊!」表達式是empy,因此「x &」和「& x」被成功解析。因此我的解析器顯得貪婪。

讓我換個問題,我如何確保relativeExpression包含至少一個QName

本質上,字符串集合("x" , "/x", "x/y", "/x/y", ...)應該是有效的XPath類似表達式,但不是""? ;-)

+2

'expression'的值是什麼? – drstevens 2012-07-25 15:08:46

+0

表達式可以像XPath一樣 – 2012-07-26 11:03:13

+1

好的!我想到了。 lazy val relativePath:PackratParser [NodePath] = rep1sep(nodeExpression,「/」) - 允許一個或多個「nodeExpressions」 – 2012-07-26 14:48:05

回答

3

"&""|"只匹配單個字符。我能想到的唯一解釋是expression既可以是空的,也可以是&|