diff options
author | michelou <michelou@epfl.ch> | 2004-05-04 13:29:11 +0000 |
---|---|---|
committer | michelou <michelou@epfl.ch> | 2004-05-04 13:29:11 +0000 |
commit | 4b1ad364d54a923d194823ce5d9a5d94a7746dc2 (patch) | |
tree | efdcd23c46eae7645e9257039173bd34cfcb8515 /sources/examples/Parsers.scala | |
parent | 7cb6cbfa0a45170d238b43868b78e72411e47f7b (diff) | |
download | scala-4b1ad364d54a923d194823ce5d9a5d94a7746dc2.tar.gz scala-4b1ad364d54a923d194823ce5d9a5d94a7746dc2.tar.bz2 scala-4b1ad364d54a923d194823ce5d9a5d94a7746dc2.zip |
- class 'Parsers' is used by parsers1.scala and...
- class 'Parsers' is used by parsers1.scala and typeinf.scala.
Diffstat (limited to 'sources/examples/Parsers.scala')
-rw-r--r-- | sources/examples/Parsers.scala | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/sources/examples/Parsers.scala b/sources/examples/Parsers.scala new file mode 100644 index 0000000000..582ad5b1f9 --- /dev/null +++ b/sources/examples/Parsers.scala @@ -0,0 +1,118 @@ +package examples; + +object parsers { + +abstract class Parsers { + + type intype; + + abstract class Parser { + + type Result = Option[intype]; + + 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) + } + } + + /*** 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: intype): Result = Some(in) + } + + val fail = new Parser { + def apply(in: intype): Result = None + } + + 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* +} + + abstract class ListParsers extends Parsers { + def chr(p: char => boolean): Parser; + def chr(c: char): Parser = chr(d: char => d == c); + + def letter : Parser = chr(Character.isLetter); + def digit : Parser = chr(Character.isDigit); + + 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; + } + + abstract class ExprParsers extends Parsers { + def chr(p: char => boolean): Parser; + def chr(c: char): Parser = chr(d: char => d == c); + + def digit : Parser = chr(Character.isDigit); + def number : Parser = digit &&& rep(digit); + def summand : Parser = number ||| chr('(') &&& expr &&& chr(')'); + def expr : Parser = summand &&& rep(chr('+') &&& summand) + } + + class ParseString(s: String) extends Parsers { + type intype = 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 TestList { + + def main(args: Array[String]): unit = + if (args.length == 1) { + val ps = new ListParsers with ParseString(args(0)); + ps.expr(ps.input) match { + case Some(n) => + Console.println("parsed: " + args(0).substring(0, n)); + case None => + Console.println("nothing parsed"); + } + } + else + Console.println("usage: java examples.TestList <expr-string>"); + } + + object TestExpr { + + def main(args: Array[String]): unit = + if (args.length == 1) { + val ps = new ExprParsers with ParseString(args(0)); + ps.expr(ps.input) match { + case Some(n) => + Console.println("parsed: " + args(0).substring(0, n)); + case None => + Console.println("nothing parsed"); + } + } + else + Console.println("usage: java examples.TestExpr <expr-string>"); + } + + def main(args: Array[String]): Unit = { + TestList.main(Array("(a,b,(1,2))")); + TestExpr.main(Array("2+3+(4+1)")) + } + +} |