summaryrefslogtreecommitdiff
path: root/sources/examples/parsers1.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2004-01-05 11:38:11 +0000
committerMartin Odersky <odersky@gmail.com>2004-01-05 11:38:11 +0000
commit0adfc8d42abed2b4019a866672c497eb5d67e5b9 (patch)
tree11c3b94a1d6df352d313d0496275cd0dc7db23df /sources/examples/parsers1.scala
parent3b1253891b888c191e9b96d566b3eb304213eeee (diff)
downloadscala-0adfc8d42abed2b4019a866672c497eb5d67e5b9.tar.gz
scala-0adfc8d42abed2b4019a866672c497eb5d67e5b9.tar.bz2
scala-0adfc8d42abed2b4019a866672c497eb5d67e5b9.zip
*** empty log message ***
Diffstat (limited to 'sources/examples/parsers1.scala')
-rw-r--r--sources/examples/parsers1.scala143
1 files changed, 69 insertions, 74 deletions
diff --git a/sources/examples/parsers1.scala b/sources/examples/parsers1.scala
index bbd0a0dbe0..06e8ed0fe0 100644
--- a/sources/examples/parsers1.scala
+++ b/sources/examples/parsers1.scala
@@ -1,52 +1,49 @@
package examples;
-trait Tree {}
-case class Var(n: String) : Tree extends Tree {}
-case class Num(n: Int) : Tree extends Tree {}
-case class Binop(op: Char, l: Tree, r: Tree): Tree extends Tree {}
+abstract class Parsers {
-module Parse {
+ type input;
- trait Parser[p] {
+ trait Parser[a] {
- type Result = Option[Pair[p, List[Char]]];
+ type Result = Option[Pair[a, input]];
- def apply(in: List[Char]): Result;
+ def apply(in: input): Result;
- def filter(p: p => Boolean) = new Parser[p] {
- def apply(in: List[Char]): Result = Parser.this.apply(in) match {
- case Some(Pair(x, in1)) => if (p(x)) Some(Pair(x, in1)) else None()
- case n => n
+ def filter(pred: a => boolean) = new Parser[a] {
+ def apply(in: input): Result = Parser.this.apply(in) match {
+ case None => None
+ case Some(Pair(x, in1)) => if (pred(x)) Some(Pair(x, in1)) else None
}
}
- def map[b](f: p => b) = new Parser[b] {
- def apply(in: List[Char]): Result = Parser.this.apply(in) match {
+ def map[b](f: a => b) = new Parser[b] {
+ def apply(in: input): Result = Parser.this.apply(in) match {
+ case None => None
case Some(Pair(x, in1)) => Some(Pair(f(x), in1))
- case None() => None()
}
}
- def flatMap[b](f: p => Parser[b]) = new Parser[b] {
- def apply(in: List[Char]): Result = Parser.this.apply(in) match {
- case Some(Pair(x, in1)) => f(x)(in1)
- case None() => None()
+ def flatMap[b](f: a => Parser[b]) = new Parser[b] {
+ def apply(in: input): Result = Parser.this.apply(in) match {
+ case None => None
+ case Some(Pair(x, in1)) => f(x).apply(in1)
}
}
- def ||| (def p: Parser[p]) = new Parser[p] {
- def apply(in: List[Char]): Result = Parser.this.apply(in) match {
- case None() => p(in)
+ def ||| (def p: Parser[a]) = new Parser[a] {
+ def apply(in: input): Result = Parser.this.apply(in) match {
+ case None => p(in)
case s => s
}
}
def &&& [b](def p: Parser[b]): Parser[b] =
- for (val _ <- this; val result <- p) yield result;
+ for (val _ <- this; val x <- p) yield x;
}
- def succeed[p](x: p) = new Parser[p] {
- def apply(in: List[Char]) = Some(Pair(x, in))
+ def succeed[a](x: a) = new Parser[a] {
+ def apply(in: input) = Some(Pair(x, in))
}
def rep[a](p: Parser[a]): Parser[List[a]] =
@@ -56,60 +53,58 @@ module Parse {
for (val x <- p; val xs <- rep(p)) yield x :: xs;
def opt[a](p: Parser[a]): Parser[Option[a]] =
- (for (val x <- p) yield Some(x): Option[a]) ||| succeed(None(): Option[a]);
+ (for (val x <- p) yield List(x)) ||| List();
}
+abstract class ExprParsers extends Parsers {
-module ExprParser {
- import Parse._;
+ def any: Parser[char];
- def chrWith(p: Char => Boolean) = new Parser[Char] {
- def apply(in: List[Char]): Result = in match {
- case List() => None()
- case (c :: in1) => if (p(c)) Some(Pair(c, in1)) else None()
- }
- }
+ def chr(ch: char) =
+ for (val c <- any; c == ch) yield c;
- def chr(c: Char): Parser[Char] = chrWith(d => d == c);
-
- def letter: Parser[Char] = chrWith(c => c.isLetter);
- def digit : Parser[Char] = chrWith(c => c.isDigit);
+ def chr(p: char => boolean) =
+ for (val c <- any; p(c)) yield c;
def ident: Parser[String] =
- for (val c <- letter; val cs <- rep(letter ||| digit))
- yield ((c :: cs) foldr "") {(c, s) => c+ s}
-
- def number: Parser[Int] =
- for (val d <- digit; val ds <- rep(digit))
- yield ((d - '0') foldl_: ds) {(x, y) => x * 10 + (y - '0')};
-
- def expr: Parser[Tree] =
- for {
- val e1 <- expr1;
- val es <- rep (
- for {
- val op <- chr('+') ||| chr('-');
- val e <- expr1
- } yield (x: Tree => Binop(op, x, e))
- )
- } yield (e1 foldl_: es) {(x,f) => f(x)}
-
- def expr1: Parser[Tree] =
- for {
- val e1 <- expr2;
- val es <- rep (
- for {
- val op <- chr('*') ||| chr('/');
- val e <- expr2
- } yield (x: Tree => Binop(op, x, e))
- )
- } yield (e1 foldl_: es) {(x,f) => f(x)}
-
- def expr2: Parser[Tree] =
- (for { val n <- ident } yield Var(n))
- ||| (for { val n <- number } yield Num(n))
- ||| (for { val _ <- chr('('); val e <- expr; val _ <- chr(')') } yield e);
-
- private def applyAll[a](fs: List[a => a], x: a) =
- (x foldl_: fs) { (x, f) => f(x) }
+ for (
+ val c: char <- chr(Character.isLetter);
+ val cs: List[char] <- rep(chr(Character.isLetterOrDigit))
+ ) yield (c :: cs).mkString("", "", "");
+
+ def number: Parser[int] =
+ for (
+ val d: char <- chr(Character.isDigit);
+ val ds: List[char] <- rep(chr(Character.isDigit))
+ ) yield ((d - '0') /: ds) ((x, digit) => x * 10 + digit - '0');
+
+ def list: Parser[List[Tree]] =
+ for (
+ val _ <- chr('(');
+ val es <- listElems ||| succeed(List());
+ val _ <- chr(')')
+ ) yield es;
+
+ def listElems: Parser[List[Any]] =
+ for (
+ val x <- expr;
+ val xs <- chr(',') &&& listElems ||| succeed(List())
+ ) yield x :: xs;
+
+ def expr: Parser[Any] =
+ list ||| ident ||| number;
+
}
+
+object Test {
+ def main(args: Array[String]) =
+ System.out.println(
+ if (args.length == 1)
+ new ExprParserFamily(args(0)).expr(0) match {
+ case Some(Pair(tree, _)) => tree.toString();
+ case None => "Syntax error"
+ }
+ else "usage: java examples.Test <expr-string>"
+ );
+}
+