scala parsing parser-combinators

Scala: cómo combinar combinadores de parser de diferentes objetos



parsing parser-combinators (1)

La respuesta rápida es usar el trait s en lugar de alojar los analizadores en el object s:

import scala.util.parsing.combinator._ trait BinaryParser extends JavaTokenParsers { def anyrep: Parser[Any] = rep(any) def any: Parser[Any] = zero | one def zero: Parser[Any] = "0" def one: Parser[Any] = "1" } trait LongChainParser extends BinaryParser { def parser1: Parser[Any] = zero~zero~one~one } trait ShortChainParser extends BinaryParser { def parser2: Parser[Any] = zero~zero } object ExampleParser extends LongChainParser with ShortChainParser { def parser: Parser[Any] = (parser1 ||| parser2) ~ anyrep def main(args: Array[String]) { println(parseAll(parser, args(0) )) } }

Debido a que los operadores combinator como ~ y | están escritas contra la clase interna, escalando las referencias del analizador a nivel de clase diciendo que BinaryParser#Parser[_] no le hace ningún bien. El uso de rasgos resuelve todos los problemas de clase interna, ya que tanto el Parser[Any] de LongChainParser como el de ShortChainParser se refieren a la clase interna del objeto ExampleParser .

Dada una familia de objetos que implementan combinadores de analizadores, ¿cómo combino los analizadores? Como Parsers.Parser es una clase interna, y en Scala las clases internas están vinculadas al objeto externo , la historia se vuelve un poco complicada.

Aquí hay un ejemplo que intenta combinar dos analizadores de diferentes objetos.

import scala.util.parsing.combinator._ class BinaryParser extends JavaTokenParsers { def anyrep: Parser[Any] = rep(any) def any: Parser[Any] = zero | one def zero: Parser[Any] = "0" def one: Parser[Any] = "1" } object LongChainParser extends BinaryParser { def parser1: Parser[Any] = zero~zero~one~one } object ShortChainParser extends BinaryParser { def parser2: Parser[Any] = zero~zero } object ExampleParser extends BinaryParser { def parser: Parser[Any] = (LongChainParser.parser1 ||| ShortChainParser.parser2) ~ anyrep def main(args: Array[String]) { println(parseAll(parser, args(0) )) } }

Esto da lugar al siguiente error:

<console>:11: error: type mismatch; found : ShortChainParser.Parser[Any] required: LongChainParser.Parser[?] def parser: Parser[Any] = (LongChainParser.parser1 ||| ShortChainParser.parser2) ~ anyrep

Ya he encontrado la solución a este problema, pero como se mencionó recientemente en scala-user ML ( Problema al inyectar un analizador en otro ), probablemente también valga la pena ponerlo aquí.