summaryrefslogtreecommitdiff
path: root/sources/examples/parsers.scala
diff options
context:
space:
mode:
Diffstat (limited to 'sources/examples/parsers.scala')
-rw-r--r--sources/examples/parsers.scala90
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>");
}