简体   繁体   中英

Parser Combinator ^^ with Optional Values

I'm trying to modify an example from DSLs in Action .

Originally, this code was used to parse items followed by account .

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

The following text could be parsed with the above parser:

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

But, I'd like to add FOO and an optional not values to the parser:

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

FOO must follow account and, optionally, not will follow.

Example:

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

However, the above code gives me this compile-time error:

[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]                  ^

How can I modify the case statement to support parsing an optional "not" value?

a <~ "FOO" ~> b means "ignore results of parsers "FOO" and b and return the result of a ".

Rewrite your method like this:

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

General mnemonic for ~> and <~ : you can ignore from start to operator or from operator to end, but not the middle part of expression.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM