| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      1 | // Parser Combinators: Simple Version
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      2 | //====================================
 | 
| 742 |      3 | //
 | 
|  |      4 | // Call with
 | 
|  |      5 | //
 | 
|  |      6 | //  amm comb1.sc
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      7 | 
 | 
| 742 |      8 |  
 | 
|  |      9 | //  Note, in the lectures I did not show the implicit type constraint
 | 
|  |     10 | //  I : IsSeq, which means that the input type 'I' needs to be
 | 
|  |     11 | //  a sequence. 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     12 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     13 | type IsSeq[A] = A => Seq[_]
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     14 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     15 | abstract class Parser[I : IsSeq, T]{
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     16 |   def parse(in: I): Set[(T, I)]
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     17 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     18 |   def parse_all(in: I) : Set[T] =
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     19 |     for ((hd, tl) <- parse(in); 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     20 |         if tl.isEmpty) yield hd
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     21 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     22 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     23 | // parser combinators
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     24 | 
 | 
| 799 |     25 | // alternative parser
 | 
|  |     26 | class AltParser[I : IsSeq, T](p: => Parser[I, T], 
 | 
|  |     27 |                               q: => Parser[I, T]) extends Parser[I, T] {
 | 
|  |     28 |   def parse(in: I) = p.parse(in) ++ q.parse(in)   
 | 
|  |     29 | }
 | 
|  |     30 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     31 | // sequence parser
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     32 | class SeqParser[I : IsSeq, T, S](p: => Parser[I, T], 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     33 |                                  q: => Parser[I, S]) extends Parser[I, (T, S)] {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     34 |   def parse(in: I) = 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     35 |     for ((hd1, tl1) <- p.parse(in); 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     36 |          (hd2, tl2) <- q.parse(tl1)) yield ((hd1, hd2), tl2)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     37 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     38 | 
 | 
| 742 |     39 | // map parser
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     40 | class MapParser[I : IsSeq, T, S](p: => Parser[I, T], 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     41 |                                  f: T => S) extends Parser[I, S] {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     42 |   def parse(in: I) = for ((hd, tl) <- p.parse(in)) yield (f(hd), tl)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     43 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     44 | 
 | 
| 742 |     45 | 
 | 
|  |     46 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     47 | // an example of an atomic parser for characters
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     48 | case class CharParser(c: Char) extends Parser[String, Char] {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     49 |   def parse(in: String) = 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     50 |     if (in != "" && in.head == c) Set((c, in.tail)) else Set()
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     51 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     52 | 
 | 
| 799 |     53 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     54 | // an atomic parser for parsing strings according to a regex
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     55 | import scala.util.matching.Regex
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     56 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     57 | case class RegexParser(reg: Regex) extends Parser[String, String] {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     58 |   def parse(in: String) = reg.findPrefixMatchOf(in) match {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     59 |     case None => Set()
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     60 |     case Some(m) => Set((m.matched, m.after.toString))  
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     61 |   }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     62 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     63 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     64 | // atomic parsers for numbers and "verbatim" strings 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     65 | val NumParser = RegexParser("[0-9]+".r)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     66 | def StrParser(s: String) = RegexParser(Regex.quote(s).r)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     67 | 
 | 
| 742 |     68 | 
 | 
| 799 |     69 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     70 | // NumParserInt transforms a "string integer" into a propper Int
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     71 | // (needs "new" because MapParser is not a case class)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     72 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     73 | val NumParserInt = new MapParser(NumParser, (s: String) => s.toInt)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     74 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     75 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     76 | // the following string interpolation allows us to write 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     77 | // StrParser(_some_string_) more conveniently as 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     78 | //
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     79 | // p"<_some_string_>" 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     80 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     81 | implicit def parser_interpolation(sc: StringContext) = new {
 | 
| 803 |     82 |   def p(args: Any*) = StrParser(sc.s(args:_*))
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     83 | }
 | 
| 803 |     84 |            
 | 
| 799 |     85 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     86 | // more convenient syntax for parser combinators
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     87 | implicit def ParserOps[I : IsSeq, T](p: Parser[I, T]) = new {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     88 |   def ||(q : => Parser[I, T]) = new AltParser[I, T](p, q)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     89 |   def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     90 |   def map[S](f: => T => S) = new MapParser[I, T, S](p, f)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     91 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     92 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     93 | // these implicits allow us to use an infix notation for
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     94 | // sequences and alternatives; we also can write the usual
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     95 | // map for a MapParser
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     96 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     97 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     98 | // with this NumParserInt can now be written more conveniently
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     99 | // as:
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    100 | 
 | 
| 799 |    101 | val NumParserInt2 = NumParser.map(_.toInt)
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    102 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    103 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    104 | // A parser for palindromes (just returns them as string)
 | 
| 803 |    105 | lazy val Pal : Parser[String, String] = {
 | 
| 849 |    106 |   ((p"a" ~ Pal) ~ p"a").map{ case ((x, y), z) => s"$x$y$z" } || 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    107 |   (p"b" ~ Pal ~ p"b").map{ case ((x, y), z) => s"$x$y$z" } || 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    108 |   p"a" || p"b" || p""
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    109 | }  
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    110 | 
 | 
| 849 |    111 | def foo(x: Int) = 
 | 
|  |    112 |    println(s"$x + $x = ${x + x}")
 | 
|  |    113 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    114 | // examples
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    115 | Pal.parse_all("abaaaba")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    116 | Pal.parse("abaaaba")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    117 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    118 | println("Palindrome: " + Pal.parse_all("abaaaba"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    119 | 
 | 
| 799 |    120 | // A parser for wellnested parentheses 
 | 
|  |    121 | //
 | 
|  |    122 | //   P ::= ( P ) P | epsilon
 | 
|  |    123 | //
 | 
|  |    124 | //   (transforms '(' -> '{' , ')' -> '}' )
 | 
|  |    125 | lazy val P : Parser[String, String] = {
 | 
|  |    126 |   (p"(" ~ P ~ p")" ~ P).map{ case (((_, x), _), y) => "{" + x + "}" + y } ||
 | 
|  |    127 |   p""
 | 
|  |    128 | }  
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    129 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    130 | println(P.parse_all("(((()()))())"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    131 | println(P.parse_all("(((()()))()))"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    132 | println(P.parse_all(")("))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    133 | println(P.parse_all("()"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    134 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    135 | // A parser for arithmetic expressions (Terms and Factors)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    136 | 
 | 
| 799 |    137 | lazy val E: Parser[String, Int] = {
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    138 |   (T ~ p"+" ~ E).map{ case ((x, _), z) => x + z } ||
 | 
| 799 |    139 |   (T ~ p"-" ~ E).map{ case ((x, _), z) => x - z } || T }
 | 
|  |    140 | lazy val T: Parser[String, Int] = {
 | 
|  |    141 |   (F ~ p"*" ~ T).map{ case ((x, _), z) => x * z } || F }
 | 
|  |    142 | lazy val F: Parser[String, Int] = {
 | 
|  |    143 |   (p"(" ~ E ~ p")").map{ case ((_, y), _) => y } || NumParserInt }
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    144 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    145 | println(E.parse_all("1+3+4"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    146 | println(E.parse("1+3+4"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    147 | println(E.parse_all("4*2+3"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    148 | println(E.parse_all("4*(2+3)"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    149 | println(E.parse_all("(4)*((2+3))"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    150 | println(E.parse_all("4/2+3"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    151 | println(E.parse("1 + 2 * 3"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    152 | println(E.parse_all("(1+2)+3"))
 | 
| 799 |    153 | println(E.parse_all("1+2+3"))
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    154 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    155 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    156 | // with parser combinators (and other parsing algorithms)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    157 | // no left-recursion is allowed, otherwise the will loop
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    158 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    159 | lazy val EL: Parser[String, Int] = 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    160 |   ((EL ~ p"+" ~ EL).map{ case ((x, y), z) => x + z} || 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    161 |    (EL ~ p"*" ~ EL).map{ case ((x, y), z) => x * z} ||
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    162 |    (p"(" ~ EL ~ p")").map{ case ((x, y), z) => y} ||
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    163 |    NumParserInt)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    164 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    165 | // this will run forever:
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    166 | //println(EL.parse_all("1+2+3"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    167 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    168 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    169 | // non-ambiguous vs ambiguous grammars
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    170 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    171 | // ambiguous
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    172 | lazy val S : Parser[String, String] =
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    173 |   (p"1" ~ S ~ S).map{ case ((x, y), z) => x + y + z } || p""
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    174 | 
 | 
| 850 |    175 | //println(time(S.parse("1" * 10)))
 | 
|  |    176 | //println(time(S.parse_all("1" * 10)))
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    177 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    178 | // non-ambiguous
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    179 | lazy val U : Parser[String, String] =
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    180 |   (p"1" ~ U).map{ case (x, y) => x + y } || p""
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    181 | 
 | 
| 850 |    182 | //println(time(U.parse("1" * 10)))
 | 
|  |    183 | //println(time(U.parse_all("1" * 10)))
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    184 | println(U.parse("1" * 25))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    185 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    186 | U.parse("11")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    187 | U.parse("11111")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    188 | U.parse("11011")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    189 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    190 | U.parse_all("1" * 100)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    191 | U.parse_all("1" * 100 + "0")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    192 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    193 | // you can see the difference in second example
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    194 | //S.parse_all("1" * 100)         // succeeds
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    195 | //S.parse_all("1" * 100 + "0")   // fails
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    196 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    197 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    198 | // A variant which counts how many 1s are parsed
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    199 | lazy val UCount : Parser[String, Int] =
 | 
| 799 |    200 |   (p"1" ~ UCount).map{ case (_, y) => y + 1 } || p"".map{ _ => 0 }
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    201 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    202 | println(UCount.parse("11111"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    203 | println(UCount.parse_all("11111"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    204 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    205 | // Two single character parsers
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    206 | lazy val One : Parser[String, String] = p"a"
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    207 | lazy val Two : Parser[String, String] = p"b"
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    208 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    209 | One.parse("a")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    210 | One.parse("aaa")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    211 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    212 | // note how the pairs nest to the left with sequence parsers
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    213 | (One ~ One).parse("aaa")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    214 | (One ~ One ~ One).parse("aaa")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    215 | (One ~ One ~ One ~ One).parse("aaaa")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    216 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    217 | (One || Two).parse("aaa")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    218 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    219 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    220 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    221 | // a problem with the arithmetic expression parser: it 
 | 
| 742 |    222 | // gets very slow with deeply nested parentheses
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    223 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    224 | println("Runtime problem")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    225 | println(E.parse("1"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    226 | println(E.parse("(1)"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    227 | println(E.parse("((1))"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    228 | //println(E.parse("(((1)))"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    229 | //println(E.parse("((((1))))"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    230 | //println(E.parse("((((((1))))))"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    231 | //println(E.parse("(((((((1)))))))"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    232 | //println(E.parse("((((((((1)))))))"))
 | 
| 828 |    233 | 
 | 
|  |    234 | 
 | 
|  |    235 | 
 | 
|  |    236 | 
 | 
|  |    237 | // runs with amm2 and amm3
 |