2014-01-09 4 views
0

Я пытаюсь изменить пример из DSLs in Action.Parser Combinator ^^ с необязательными значениями

Первоначально этот код использовался для разбора 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 Some (" FOO ")' говорит мне, что 'match' не является исчерпывающим. –

Смежные вопросы