2014-01-09 48 views
0

我試圖從DSLs in Action修改示例。解析器組合器^^具有可選值

最初,這段代碼被用來解析items後跟account

lazy val order: Parser[Order] = 
    items ~ account_spec ^^ { 
     case i ~ a => Order(i, a) 
    } 

下面的文本可以與上述解析器解析:

(100 IBM shares to buy at max 45) for account "A1234 
------------- item ------------- ------ account ---- 

但是,我想FOO和一個可選的not值添加到解析器:

lazy val order: Parser[Order] = 
    items <~ "FOO" ~> ("not"?) ~ account_spec ^^ { 
     case i ~ n ~ a => println(n); Order(i, a) 
    } 

FOO必須遵循account,並且可選地,將遵循not

例子:

(100 IBM shares to buy at max 45) FOO not for account "A1234 
---------- item ------------------ --- --- ------ account ---- 

然而,上面的代碼給了我這個編譯時錯誤:

[WARNING] ....\OrderDsl.scala:19: error: constructor cannot be instantiated to 
expected type; 
[WARNING] found : ch8.trading.semantic.dsl.OrderDsl.~[a,b] 
[WARNING] required: ch8.trading.semantic.dsl.AST.Items 
[WARNING]  case i ~ n ~ a => println(n); Order(i, a) 
[WARNING]    ^

我如何修改case聲明支持解析可選「不」值?

回答

2

a <~ "FOO" ~> b表示「忽略解析器"FOO"b的結果並返回a的結果」。

重寫你的方法是這樣的:

lazy val order: Parser[Order] = 
    items ~ opt("FOO") ~ opt("not") ~ account_spec ^^ { 
    case i ~ _ ~ n ~ a => println(n); Order(i, a) 
    } 

通用助記符~><~:您可以忽略從開始到運營商或運營商從結束,但不能表達的中間部分。

+0

謝謝@senia。你的回答清除了我對'〜>'和'<〜'的誤用。 –

+0

@KevinMeredith:其實你可以使用'items〜(opt(「FOO」)〜> opt(「not」)〜account_spec)^^ {case i〜(n〜a)=> ...}。 – senia

+0

如果我們加上'case i〜foo〜n ...',是不是'foo'只能等於'None'和'Some(「FOO」)'?我在'foo match'的模式匹配{case None => ... case某些(「FOO」)'告訴我'match'不是窮盡的。 –

相關問題