diff options
Diffstat (limited to 'sources/examples/parsers.scala')
-rw-r--r-- | sources/examples/parsers.scala | 90 |
1 files changed, 58 insertions, 32 deletions
diff --git a/sources/examples/parsers.scala b/sources/examples/parsers.scala index efe90fc306..3112e0346d 100644 --- a/sources/examples/parsers.scala +++ b/sources/examples/parsers.scala @@ -1,53 +1,79 @@ package examples; +abstract class Parsers[intype] { -module Parse { + abstract class Parser { - type Result = Option[List[Char]]; + type Result = Option[intype]; - trait Parser with Function1[List[Char],Result] { - 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 apply(in: intype): Result; + + /*** p &&& q applies first p, and if that succeeds, then q + */ + def &&& (def q: Parser) = new Parser { + def apply(in: intype): Result = Parser.this.apply(in) match { + case None => None + case Some(in1) => q(in1) } } - def ||| (def p: Parser) = new Parser { - def apply(in: List[Char]) = Parser.this.apply(in) match { - case None() => p(in) + /*** p ||| q applies first p, and, if that fails, then q. + */ + def ||| (def q: Parser) = new Parser { + def apply(in: intype): Result = Parser.this.apply(in) match { + case None => q(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() - } + val empty = new Parser { + def apply(in: intype): Result = Some(in) } - def chr(c: Char): Parser = chrWith(d => d == c); + val fail = new Parser { + def apply(in: intype): Result = None + } - def opt(p: Parser): Parser = p ||| empty; - def rep(p: Parser): Parser = opt(rep1(p)); - def rep1(p: Parser): Parser = p &&& rep(p); + def opt(p: Parser): Parser = p ||| empty; // p? = (p | <empty>) + def rep(p: Parser): Parser = opt(rep1(p)); // p* = [p+] + def rep1(p: Parser): Parser = p &&& rep(p); // p+ = p p* } -module ExprParser { - import Parse._; +abstract class ListParsers[intype] extends Parsers[intype] { + + def chr(p: char => boolean): Parser; - def letter = chrWith(c => c.isLetter); - def digit = chrWith(c => c.isDigit); + def chr(c: char): Parser = chr(d: char => d == c); - def ident = letter &&& rep(letter ||| digit); - def number = digit &&& rep(digit); + def letter : Parser = chr(Character.isLetter); + def digit : Parser = chr(Character.isDigit); - def expr:Parser = expr1 &&& rep((chr('+') &&& expr1) ||| (chr('-') &&& expr1)); - def expr1 = expr2 &&& rep((chr('*') &&& expr2) ||| (chr('/') &&& expr2)); - def expr2 = ident ||| number ||| (chr('(') &&& expr &&& chr(')')); + def ident : Parser = letter &&& rep(letter ||| digit); + def number : Parser = digit &&& rep(digit); + def list : Parser = chr('(') &&& listElems &&& chr(')'); + def listElems : Parser = expr &&& (chr(',') &&& listElems ||| empty); + def expr : Parser = ident ||| number ||| list; +} + +class ParseString(s: String) extends Parsers[int] { + val input = 0; + def chr(p: char => boolean) = new Parser { + def apply(in: int): Parser#Result = + if (in < s.length() && p(s charAt in)) Some(in + 1); + else None; + } +} + +object Test { + + def main(args: Array[String]): unit = + if (args.length == 1) { + val ps = new ListParsers[int] with ParseString(args(0)); + ps.exprs(input) match { + case Some(n) => + System.out.println("parsed: " + args(0).substring(0, n)); + case None => + System.out.println("nothing parsed"); + } + } else System.out.println("usage: java examples.Test <expr-string>"); } |