summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/reference/ExamplesPart.tex4
-rw-r--r--sources/examples/parsers1.scala71
2 files changed, 45 insertions, 30 deletions
diff --git a/doc/reference/ExamplesPart.tex b/doc/reference/ExamplesPart.tex
index 0a9ef58d89..30ea725cfd 100644
--- a/doc/reference/ExamplesPart.tex
+++ b/doc/reference/ExamplesPart.tex
@@ -5420,7 +5420,7 @@ given predicate. They are now implemented in terms of \code{any}.
The next level is represented by parsers reading identifiers, numbers
and lists. Here is a parser for identifiers.
\begin{lstlisting}
-class ListParsers extends CharParsers {
+abstract class ListParsers extends CharParsers {
def ident: Parser[Tree] =
for (
val c: char <- chr(Character.isLetter);
@@ -5578,7 +5578,7 @@ applying it to the command line argument.
object Test {
def main(args: Array[String]): unit = {
val ps = new ListParsers with ParseString(args(0));
- ps.expr(input) match {
+ ps.expr(ps.input) match {
case Some(Pair(list, _)) => System.out.println("parsed: " + list);
case None => "nothing parsed"
}
diff --git a/sources/examples/parsers1.scala b/sources/examples/parsers1.scala
index 06e8ed0fe0..c5d877807e 100644
--- a/sources/examples/parsers1.scala
+++ b/sources/examples/parsers1.scala
@@ -2,37 +2,37 @@ package examples;
abstract class Parsers {
- type input;
+ type intype;
trait Parser[a] {
- type Result = Option[Pair[a, input]];
+ type Result = Option[Pair[a, intype]];
- def apply(in: input): Result;
+ def apply(in: intype): Result;
def filter(pred: a => boolean) = new Parser[a] {
- def apply(in: input): Result = Parser.this.apply(in) match {
+ def apply(in: intype): 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: a => b) = new Parser[b] {
- def apply(in: input): Result = Parser.this.apply(in) match {
+ def apply(in: intype): Result = Parser.this.apply(in) match {
case None => None
case Some(Pair(x, in1)) => Some(Pair(f(x), in1))
}
}
def flatMap[b](f: a => Parser[b]) = new Parser[b] {
- def apply(in: input): Result = Parser.this.apply(in) match {
+ def apply(in: intype): Result = Parser.this.apply(in) match {
case None => None
case Some(Pair(x, in1)) => f(x).apply(in1)
}
}
def ||| (def p: Parser[a]) = new Parser[a] {
- def apply(in: input): Result = Parser.this.apply(in) match {
+ def apply(in: intype): Result = Parser.this.apply(in) match {
case None => p(in)
case s => s
}
@@ -43,7 +43,7 @@ abstract class Parsers {
}
def succeed[a](x: a) = new Parser[a] {
- def apply(in: input) = Some(Pair(x, in))
+ def apply(in: intype) = Some(Pair(x, in))
}
def rep[a](p: Parser[a]): Parser[List[a]] =
@@ -52,59 +52,74 @@ abstract class Parsers {
def rep1[a](p: Parser[a]): Parser[List[a]] =
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 List(x)) ||| List();
+ def opt[a](p: Parser[a]): Parser[List[a]] =
+ (for (val x <- p) yield List(x)) ||| succeed(List());
}
-abstract class ExprParsers extends Parsers {
-
+abstract class CharParsers extends Parsers {
def any: Parser[char];
-
def chr(ch: char) =
for (val c <- any; c == ch) yield c;
-
def chr(p: char => boolean) =
for (val c <- any; p(c)) yield c;
+}
+
+abstract class Tree{}
+case class Id (s: String) extends Tree {}
+case class Num(n: int) extends Tree {}
+case class Lst(elems: List[Tree]) extends Tree {}
- def ident: Parser[String] =
+abstract class ListParsers extends CharParsers {
+
+ def ident: Parser[Tree] =
for (
val c: char <- chr(Character.isLetter);
val cs: List[char] <- rep(chr(Character.isLetterOrDigit))
- ) yield (c :: cs).mkString("", "", "");
+ ) yield Id((c :: cs).mkString("", "", ""));
- def number: Parser[int] =
+ def number: Parser[Tree] =
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');
+ ) yield Num(((d - '0') /: ds) ((x, digit) => x * 10 + digit - '0'));
- def list: Parser[List[Tree]] =
+ def list: Parser[Tree] =
for (
val _ <- chr('(');
val es <- listElems ||| succeed(List());
val _ <- chr(')')
- ) yield es;
+ ) yield Lst(es);
- def listElems: Parser[List[Any]] =
+ def listElems: Parser[List[Tree]] =
for (
val x <- expr;
val xs <- chr(',') &&& listElems ||| succeed(List())
) yield x :: xs;
- def expr: Parser[Any] =
+ def expr: Parser[Tree] =
list ||| ident ||| number;
}
+class ParseString(s: String) extends Parsers {
+ type intype = int;
+ val input = 0;
+ def any = new Parser[char] {
+ def apply(in: int): Parser[char]#Result =
+ if (in < s.length()) Some(Pair(s charAt in, in + 1)) else None;
+ }
+}
+
object Test {
- def main(args: Array[String]) =
+ def main(args: Array[String]): unit =
System.out.println(
- if (args.length == 1)
- new ExprParserFamily(args(0)).expr(0) match {
- case Some(Pair(tree, _)) => tree.toString();
- case None => "Syntax error"
+ if (args.length == 1) {
+ val ps = new ListParsers with ParseString(args(0));
+ ps.expr(ps.input) match {
+ case Some(Pair(list, _)) => System.out.println("parsed: " + list);
+ case None => "nothing parsed"
}
- else "usage: java examples.Test <expr-string>"
+ } else "usage: java examples.Test <expr-string>"
);
}