Roberto Bonvallet Roberto Bonvallet - 1 month ago 14
Scala Question

Reuse parser within another parser with Scala parser combinators

I have a parser for arithmetic expressions:

object FormulaParser extends JavaTokenParsers {
def apply(input: String) = parseAll(formula, input)
// ...

val formula: Parser[Formula] =
comparison | comparable | concatenable | term | factor
}


I need to parse a different language that can contain formulas. Let's say I need to parse something like
X < formula
. Unfortunately I cannot reuse
FormulaParser.formula
in my new parser:

object ConditionParser extends JavaTokenParsers {
def apply(input: String) = parseAll(condition, input)
// ...

val condition: Parser[Condition] =
"X" ~ ("<=" | "<") ~ FormulaParser.formula ^^ { ... } // doesn't work
}


because the parser on the left-hand side of
~
is an instance of
ConditionParser.Parser
, so its
~
method expects something with that same type, not something of type
FormulaParser.Parser
.

The whole point of using parser combinators is, well, combining parsers! It seems silly to me that my first attempt didn't work, although I understand why it happens (we are reusing base parsers by extending a base trait).

Is there a simple way to combine parsers defined in different types?

Answer

In order to reuse parsers, you need to use inheritance. So if you make FormulaParsers a class or a trait, ConditionParser can inherit from it and reuse its parsers.

This is also how you're already reusing the parsers defined in JavaTokenParsers.