I'm trying to create a parser that combines Regex parsers and a custom parser I have. I've looked at Scala: How to combine parser combinators from different objects, but that question and answers deal with parsers that have the same type of Elem
.
Say I have a few RegexParsers, and also a parser that does a lookup for a String:
trait NumbersParsers extends RegexParsers {
def number = """\d+""".r
}
trait LookupParsers extends Parsers {
type Elem = String
def word = elem("word", (potential:String) => dictionary.exists(_.equals(x))
}
If I combine these parsers naively
object MyParser extends NumbersParsers with RegexParsers {
def quantitive = number ~ word
}
I obviously get type errors because of the different types of Elem
. How do I combine these parsers?
I feel somewhat responsible for answering this one since I asked and answered Scala: How to combine parser combinators from different objects.
The quick answer would be, you can't combine different types of
Elem
. A different and elegant way to solve this problem uses^?
to augment a regex parser with extra filtering.It might be helpful to read up on Combinator Parsing in Programming in Scala:
So
Elem
is used by the lexical analyzer, which is responsible for chopping up your input stream into the smallest possible tokens that the parser wants to deal with. Since you want to deal with regular expression, yourElem
isChar
.But don't worry. Just because your lexer gives you
Char
s that doesn't mean your parser is stuck with them too. WhatRegexParsers
gives you is an implicit converter from a regex toParser[String]
. You can further convert them using^^
operator (fully maps input) and^?
operator (partially maps input).Let's incorporate them into your parsers: