Scala Parser Combinators: Parsing terms with optional initial character -
i'm working on parser parses few terms have optional initial character same terms. problem is, of terms first character same initial character. i'm trying avoid rewriting each term , without initial character. figured packrat parser sounded solution i've yet working way want. below minimal example of i'm trying accomplish.
import scala.util.parsing.combinator._ import scala.util.parsing.input._ object test extends app { object myparser extends regexparsers packratparsers { lazy val p1:parser[string] = "ab" lazy val p2:parser[string] = "cd" lazy val parser:packratparser[string] = ("a".?) ~> ( p2 | p1 ) } def parsing[t](s: string)(implicit p: myparser.parser[t]): t = { import myparser._ val phraseparser = phrase(p) val input = new packratreader(new charsequencereader(s)) phraseparser(input) match { case success(t, _) => t case nosuccess(msg, _) => throw new illegalargumentexception( "could not parse '"+s+"': "+msg) } } //> parsing: [t](s: string)(implicit p: test.myparser.parser[t])t implicit val parser = myparser.log(myparser.parser)("parser") println(parsing("cd")) /* works */ println(parsing("acd")) /* works */ println(parsing("aab")) /* works */ // should work doesn't. println(parsing("ab")) /* expected "ab" found "b" */ }
after looking @ @ishaaq's answer came solution believe little more elegant.
implicit class parserextension[t](val p: parser[t]) extends anyval { def ?~[u](q: => parser[u]): parser[option[t] ~ u] = { ((p ^^ some.apply) ~ q) | (success(none) ~ q) } }
this implicit class adds method parsers can have optional parser tracking. can use so:
val a:parser[string] = "a" val parser:parser[option[string] ~ string] = ?~ ( p2 | p1 )
Comments
Post a Comment