diff options
Diffstat (limited to 'sources/examples/parsers.scala')
-rw-r--r-- | sources/examples/parsers.scala | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/sources/examples/parsers.scala b/sources/examples/parsers.scala new file mode 100644 index 0000000000..43a386e8db --- /dev/null +++ b/sources/examples/parsers.scala @@ -0,0 +1,53 @@ +package examples; + +module Parse { + + type Result = Option[List[Char]]; + + trait Parser extends Function1[List[Char],Result] with { + def &&& (def p: Parser) = new Parser { + def apply(in: List[Char]) = Parser.this.apply(in) match { + case Some(in1) => p(in1) + case n => n + } + } + + def ||| (def p: Parser) = new Parser { + def apply(in: List[Char]) = Parser.this.apply(in) match { + case None() => p(in) + case s => s + } + } + } + + val empty = new Parser { def apply(in: List[Char]): Result = Some(in) } + + def fail = new Parser { def apply(in: List[Char]): Result = None() } + + def chrWith(p: Char => Boolean) = new Parser { + def apply(in: List[Char]): Result = in match { + case List() => None() + case (c :: in1) => if (p(c)) Some(in1) else None() + } + } + + def chr(c: Char): Parser = chrWith(d => d == c); + + def opt(p: Parser): Parser = p ||| empty; + def rep(p: Parser): Parser = opt(rep1(p)); + def rep1(p: Parser): Parser = p &&& rep(p); +} + +module ExprParser { + import Parse._; + + def letter = chrWith(c => c.isLetter); + def digit = chrWith(c => c.isDigit); + + def ident = letter &&& rep(letter ||| digit); + def number = digit &&& rep(digit); + + def expr:Parser = expr1 &&& rep((chr('+') &&& expr1) ||| (chr('-') &&& expr1)); + def expr1 = expr2 &&& rep((chr('*') &&& expr2) ||| (chr('/') &&& expr2)); + def expr2 = ident ||| number ||| (chr('(') &&& expr &&& chr(')')); +} |