summaryrefslogtreecommitdiff
path: root/test/benchmark/sources/parsers/parsers.scala
blob: 57b79588bc440f93b3f40f8f7b39c8808a31ba1a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*                     __                                               *\
**     ________ ___   / /  ___     Scala benchmark suite                **
**    / __/ __// _ | / /  / _ |    (c) 2003-2004, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |                                         **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
** $Id$
\*                                                                      */

package benchmarks;

/** The parsers example from the scala distribution. */
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 &&& (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 ||| (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) =>
	  System.out.println("parsed: " + args(0).substring(0, n));
	case None =>
	  System.out.println("nothing parsed");
      }
    } else System.out.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) =>
	  System.out.println("parsed: " + args(0).substring(0, n));
	case None =>
	  System.out.println("nothing parsed");
      }
    } else System.out.println("usage: java examples.TestExpr <expr-string>");
}

object parsers with scala.testing.Benchmark {
  def run: Unit = {
    TestList.main(Array("(a,b,(1,2))"));
    TestExpr.main(Array("2+3+(4+1)"))
  }
}