# HG changeset patch # User Christian Urban # Date 1564514380 -3600 # Node ID 8067d0a8ba04d22e474b133500dc2bfee415e989 # Parent f5214da1976e201a046f41908626e9eb10bef141 updated diff -r f5214da1976e -r 8067d0a8ba04 progs/comb1.scala --- a/progs/comb1.scala Sun Jul 28 21:10:39 2019 +0100 +++ b/progs/comb1.scala Tue Jul 30 20:19:40 2019 +0100 @@ -2,8 +2,8 @@ import scala.language.reflectiveCalls /* Note, in the lectures I did not show the implicit type consraint - * I => Seq[_] , which means that the input type I needs to be - * a sequence, subtype of Seq. */ + * I => Seq[_], which means that the input type 'I' needs to be + * a sequence. */ abstract class Parser[I, T](implicit ev: I => Seq[_]) { def parse(ts: I): Set[(T, I)] @@ -31,7 +31,7 @@ for ((head, tail) <- p.parse(sb)) yield (f(head), tail) } -// atomic parsers +// atomic parsers for characters, numbers and strings case class CharParser(c: Char) extends Parser[String, Char] { def parse(sb: String) = if (sb != "" && sb.head == c) Set((c, sb.tail)) else Set() @@ -48,9 +48,9 @@ val NumParser = RegexParser("[0-9]+".r) def StringParser(s: String) = RegexParser(Regex.quote(s).r) -// NumParserInt transforms a "string integer" into an Int; +// NumParserInt2 transforms a "string integer" into an Int; // needs new, because FunParser is not a case class -val NumParserInt = new FunParser(NumParser, (s: String) => s.toInt) +val NumParserInt2 = new FunParser(NumParser, (s: String) => s.toInt) // convenience @@ -58,14 +58,14 @@ implicit def char2parser(c: Char) = CharParser(c) implicit def ParserOps[I, T](p: Parser[I, T])(implicit ev: I => Seq[_]) = new { - def | (q : => Parser[I, T]) = new AltParser[I, T](p, q) + def || (q : => Parser[I, T]) = new AltParser[I, T](p, q) def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f) def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q) } implicit def StringOps(s: String) = new { - def | (q : => Parser[String, String]) = new AltParser[String, String](s, q) - def | (r: String) = new AltParser[String, String](s, r) + def || (q : => Parser[String, String]) = new AltParser[String, String](s, q) + def || (r: String) = new AltParser[String, String](s, r) def ==>[S] (f: => String => S) = new FunParser[String, String, S](s, f) def ~[S] (q : => Parser[String, S]) = new SeqParser[String, String, S](s, q) @@ -78,8 +78,8 @@ lazy val Pal : Parser[String, String] = - (("a" ~ Pal ~ "a") ==> { case ((x, y), z) => x + y + z } | - ("b" ~ Pal ~ "b") ==> { case ((x, y), z) => x + y + z } | "a" | "b" | "") + (("a" ~ Pal ~ "a") ==> { case ((x, y), z) => x + y + z } || + ("b" ~ Pal ~ "b") ==> { case ((x, y), z) => x + y + z } || "a" || "b" || "") Pal.parse_all("abaaaba") Pal.parse("abaaaba") @@ -88,29 +88,31 @@ // well-nested parentheses parser (transforms '(' -> '{' , ')' -> '}' ) lazy val P : Parser[String, String] = - "(" ~ P ~ ")" ~ P ==> { case (((_, x), _), y) => "{" + x + "}" + y } | "" + "(" ~ P ~ ")" ~ P ==> { case (((_, x), _), y) => "{" + x + "}" + y } || "" P.parse_all("(((()()))())") P.parse_all("(((()()))()))") P.parse_all(")(") P.parse_all("()") -// Arithmetic Expressions +// Arithmetic Expressions (Terms and Factors) lazy val E: Parser[String, Int] = - (T ~ "+" ~ E) ==> { case ((x, y), z) => x + z } | - (T ~ "-" ~ E) ==> { case ((x, y), z) => x - z } | T + (T ~ "+" ~ E) ==> { case ((x, y), z) => x + z } || + (T ~ "-" ~ E) ==> { case ((x, y), z) => x - z } || T lazy val T: Parser[String, Int] = - (F ~ "*" ~ T) ==> { case ((x, y), z) => x * z } | F + (F ~ "*" ~ T) ==> { case ((x, y), z) => x * z } || F lazy val F: Parser[String, Int] = - ("(" ~ E ~ ")") ==> { case ((x, y), z) => y } | NumParserInt + ("(" ~ E ~ ")") ==> { case ((x, y), z) => y } || NumParserInt +/* same parser but producing a string lazy val E: Parser[String, String] = - (T ~ "+" ~ E) ==> { case ((x, y), z) => "(" + x + ")+(" + z + ")"} | T + (T ~ "+" ~ E) ==> { case ((x, y), z) => "(" + x + ")+(" + z + ")"} || T lazy val T: Parser[String, String] = - (F ~ "*" ~ T) ==> { case ((x, y), z) => "(" + x + ")*("+ z + ")"} | F + (F ~ "*" ~ T) ==> { case ((x, y), z) => "(" + x + ")*("+ z + ")"} || F lazy val F: Parser[String, String] = - ("(" ~ E ~ ")") ==> { case ((x, y), z) => y } | NumParser + ("(" ~ E ~ ")") ==> { case ((x, y), z) => y } || NumParser +*/ println(E.parse_all("1+3+4")) println(E.parse("1+3+4")) @@ -126,9 +128,9 @@ // no left-recursion allowed, otherwise will loop lazy val EL: Parser[String, Int] = - (EL ~ "+" ~ EL ==> { case ((x, y), z) => x + z} | - EL ~ "*" ~ EL ==> { case ((x, y), z) => x * z} | - "(" ~ EL ~ ")" ==> { case ((x, y), z) => y} | + (EL ~ "+" ~ EL ==> { case ((x, y), z) => x + z} || + EL ~ "*" ~ EL ==> { case ((x, y), z) => x * z} || + "(" ~ EL ~ ")" ==> { case ((x, y), z) => y} || NumParserInt) //println(EL.parse_all("1+2+3")) @@ -137,13 +139,16 @@ // non-ambiguous vs ambiguous grammars + +// ambiguous lazy val S : Parser[String, String] = - ("1" ~ S ~ S) ==> { case ((x, y), z) => x + y + z } | "" + ("1" ~ S ~ S) ==> { case ((x, y), z) => x + y + z } || "" -S.parse("1" * 17) +S.parse("1" * 10) +// non-ambiguous lazy val U : Parser[String, String] = - ("1" ~ U) ==> { case (x, y) => x + y } | "" + ("1" ~ U) ==> { case (x, y) => x + y } || "" U.parse("1" * 25) @@ -155,7 +160,7 @@ U.parse_all("1" * 100 + "0") lazy val UCount : Parser[String, Int] = - ("1" ~ UCount) ==> { case (x, y) => y + 1 } | "" ==> { x => 0 } + ("1" ~ UCount) ==> { case (x, y) => y + 1 } || "" ==> { x => 0 } UCount.parse("11111") UCount.parse_all("11111") @@ -173,7 +178,17 @@ (One ~ One ~ One).parse("111") (One ~ One ~ One ~ One).parse("1111") -(One | Two).parse("111") +(One || Two).parse("111") + + +// a problem with the parser -> gets slow with nestedness +E.parse("1") +E.parse("(1)") +E.parse("((1))") +E.parse("(((1)))") +E.parse("((((1))))") +E.parse("((((((1))))))") +E.parse("(((((((1)))))))") \ No newline at end of file diff -r f5214da1976e -r 8067d0a8ba04 progs/comb2.scala --- a/progs/comb2.scala Sun Jul 28 21:10:39 2019 +0100 +++ b/progs/comb2.scala Tue Jul 30 20:19:40 2019 +0100 @@ -110,7 +110,7 @@ // boolean expressions with some simple nesting lazy val BExp: Parser[String, BExp] = - (AExp ~ "==" ~ AExp) ==> { case ((x, y), z) => Bop("==", x, z) }: Bexp || + (AExp ~ "==" ~ AExp) ==> { case ((x, y), z) => Bop("==", x, z): BExp } || (AExp ~ "!=" ~ AExp) ==> { case ((x, y), z) => Bop("!=", x, z): BExp } || (AExp ~ "<" ~ AExp) ==> { case ((x, y), z) => Bop("<", x, z): BExp } || (AExp ~ ">" ~ AExp) ==> { case ((x, y), z) => Bop(">", x, z): BExp } || @@ -120,7 +120,7 @@ ("false" ==> ((_) => False: BExp )) || ("(" ~ BExp ~ ")") ==> { case ((x, y), z) => y} -// statements +// statement / statements lazy val Stmt: Parser[String, Stmt] = (("skip" ==> ((_) => Skip: Stmt)) || (IdParser ~ ":=" ~ AExp) ==> { case ((x, y), z) => Assign(x, z): Stmt } || @@ -133,6 +133,7 @@ (Stmt ~ ";" ~ Stmts) ==> { case ((x, y), z) => x :: z : Block } || (Stmt ==> ((s) => List(s) : Block)) +// blocks (enclosed in curly braces) lazy val Block: Parser[String, Block] = (("{" ~ Stmts ~ "}") ==> { case ((x, y), z) => y} || (Stmt ==> ((s) => List(s)))) @@ -142,19 +143,20 @@ Block.parse_all("{x:=5;y:=8}") Block.parse_all("if(false)then{x:=5}else{x:=10}") -val fib = """{n := 10; - minus1 := 0; - minus2 := 1; - temp := 0; - while (n > 0) do { +val fib = """n := 10; + minus1 := 0; + minus2 := 1; + temp := 0; + while (n > 0) do { temp := minus2; minus2 := minus1 + minus2; minus1 := temp; n := n - 1 - }; - result := minus2}""".replaceAll("\\s+", "") + }; + result := minus2""".replaceAll("\\s+", "") -Block.parse_all(fib) +Stmts.parse_all(fib) + // an interpreter for the WHILE language type Env = Map[String, Int] @@ -198,7 +200,7 @@ // parse + evaluate fib program; then lookup what is // stored under the variable result -println(eval(Block.parse_all(fib).head)("result")) +println(eval(Stmts.parse_all(fib).head)("result")) // more examles @@ -208,20 +210,20 @@ println("Factors") val factors = - """{n := 12; + """n := 12; f := 2; while (f < n / 2 + 1) do { if ((n / f) * f == n) then { write(f) } else { skip }; f := f + 1 - }}""".replaceAll("\\s+", "") + }""".replaceAll("\\s+", "") -eval(Block.parse_all(factors).head) +eval(Stmts.parse_all(factors).head) // calculate all prime numbers up to a number println("Primes") val primes = - """{end := 100; + """end := 100; n := 2; while (n < end) do { f := 2; @@ -232,6 +234,6 @@ }; if (tmp == 0) then { write(n) } else { skip }; n := n + 1 - }}""".replaceAll("\\s+", "") + }""".replaceAll("\\s+", "") -eval(Block.parse_all(primes).head) +eval(Stmts.parse_all(primes).head) diff -r f5214da1976e -r 8067d0a8ba04 progs/compile_arrays.scala --- a/progs/compile_arrays.scala Sun Jul 28 21:10:39 2019 +0100 +++ b/progs/compile_arrays.scala Tue Jul 30 20:19:40 2019 +0100 @@ -69,9 +69,9 @@ .end method """ + // Compiler functions - // for generating new labels var counter = -1 @@ -186,33 +186,21 @@ (beginning ++ instructions.mkString ++ ending).replaceAllLiterally("XXX", class_name) } -// compiling and running files -// -// JVM files can be assembled with -// -// java -jar jvm/jasmin-2.4/jasmin.jar fib.j -// -// and started with -// -// java fib/fib - - +// main compiler functions import scala.util._ import scala.sys.process._ import scala.io def compile_tofile(bl: Block, class_name: String) = { val output = compile(bl, class_name) - val fw = new java.io.FileWriter(class_name + ".j") - fw.write(output) - fw.close() + scala.tools.nsc.io.File(s"${class_name}.j").writeAll(output) } def compile_all(bl: Block, class_name: String) : Unit = { compile_tofile(bl, class_name) println("compiled ") - val test = ("java -jar jvm/jasmin-2.4/jasmin.jar " + class_name + ".j").!! + (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! println("assembled ") } @@ -227,91 +215,20 @@ def compile_run(bl: Block, class_name: String) : Unit = { println("Start compilation") compile_all(bl, class_name) - println("running") - println("Time: " + time_needed(1, ("java " + class_name + "/" + class_name).!)) -} - - -// BF Part - -// simple instructions -def instr(c: Char) : String = c match { - case '>' => "ptr := ptr + 1;" - case '<' => "ptr := ptr - 1;" - case '+' => "field[ptr] := field[ptr] + 1;" - case '-' => "field[ptr] := field[ptr] - 1;" - case '.' => "x := field[ptr]; write x;" - case '[' => "while (field[ptr] != 0) do {" - case ']' => "skip};" - case _ => "" -} - -def instrs(prog: String) : String = - prog.toList.map(instr).mkString - - -// compound instructions -def splice(cs: List[Char], acc: List[(Char, Int)]) : List[(Char, Int)] = (cs, acc) match { - case (Nil, acc) => acc - case (c :: cs, Nil) => splice(cs, List((c, 1))) - case (c :: cs, (d, n) :: acc) => - if (c == d) splice(cs, (c, n + 1) :: acc) - else splice(cs, (c, 1) :: (d, n) :: acc) + println("Start running") + println("Time: " + time_needed(1, (s"java ${class_name}/${class_name}").!)) } -def spl(s: String) = splice(s.toList, Nil).reverse - -def instr2(c: Char, n: Int) : String = c match { - case '>' => s"ptr := ptr + $n;" - case '<' => s"ptr := ptr - $n;" - case '+' => s"field[ptr] := field[ptr] + $n;" - case '-' => s"field[ptr] := field[ptr] - $n;" - case '.' => s"x := field[ptr]; write x;" - case '[' => s"while (field[ptr] != 0) do {" * n - case ']' => s"skip};" * n - case _ => "" -} - -def instrs2(prog: String) : String = - spl(prog).map{ case (c, n) => instr2(c, n) }.mkString - - -def bf_str(prog: String) : String = { - "\n" ++ - //"new field[30000];\n" ++ - "ptr := 15000;" ++ - instrs2(prog) ++ - "skip" -} +// a simple test case +val arr_test = + List(Array("a", 10), // a[10] + Array("b", 2), // b[2] + AssignA("a", Num(0), Num(10)), // a[0] := 10 + Assign("x", Ref("a", Num(0))), // x := a[0] + Write("x"), // write x + AssignA("b", Num(1), Num(5)), // b[1] := 5 + Assign("x", Ref("b", Num(1))), // x := b[1] + Write("x")) // write x -def bf_run(bfprog: String, name: String) = { - println("BF processing start") - val bf_string = bf_str(bfprog).replaceAll("\\s", "") - println(s"BF parsing start (string length ${bf_string.length})") - val bf_prog = Stmts.parse_all(bf_string).toList.head - println("BF Compile start") - compile_run(Array("field", 30000) :: bf_prog, name) -} - - - -val bf1 = """++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[ - ->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<< - ]>.>+[>>]>+]""" +compile_run(arr_test, "a") -bf_run(bf1, "sier") - -bf_run("""++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++ - ..+++.>>.<-.<.+++.------.--------.>>+.>++.""", "hello") - -bf_run("""+++++++++++ - >+>>>>++++++++++++++++++++++++++++++++++++++++++++ - >++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+> - +<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[- - <-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<< - -]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]] - >[<<+>>[-]]<<<<<<<]>>>>>[+++++++++++++++++++++++++ - +++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++ - ++++++++++++++++++++++++++++++++++++++++++++.[-]<< - <<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<< - [-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]""", "fibs") diff -r f5214da1976e -r 8067d0a8ba04 progs/fun-bare.scala --- a/progs/fun-bare.scala Sun Jul 28 21:10:39 2019 +0100 +++ b/progs/fun-bare.scala Tue Jul 30 20:19:40 2019 +0100 @@ -1,5 +1,5 @@ // A Small Compiler for a Simple Functional Language -// (it does not use a parser and lexer) +// (it does not include a parser and lexer) // Abstract syntax trees abstract class Exp @@ -70,17 +70,18 @@ x ++ "_" ++ counter.toString() } -// convenient string interpolations -// for instructions, labels and methods +// convenient string interpolations for +// generating instructions, labels etc import scala.language.implicitConversions import scala.language.reflectiveCalls implicit def sring_inters(sc: StringContext) = new { - def i(args: Any*): String = " " ++ sc.s(args:_*) ++ "\n" - def l(args: Any*): String = sc.s(args:_*) ++ ":\n" - def m(args: Any*): String = sc.s(args:_*) ++ "\n" + def i(args: Any*): String = " " ++ sc.s(args:_*) ++ "\n" + def l(args: Any*): String = sc.s(args:_*) ++ ":\n" + def m(args: Any*): String = sc.s(args:_*) ++ "\n" } +// variable / index environments type Env = Map[String, Int] // compile expressions diff -r f5214da1976e -r 8067d0a8ba04 progs/fun.scala --- a/progs/fun.scala Sun Jul 28 21:10:39 2019 +0100 +++ b/progs/fun.scala Tue Jul 30 20:19:40 2019 +0100 @@ -252,11 +252,13 @@ } } +case class ~[+A, +B](_1: A, _2: B) + class SeqParser[I, T, S](p: => Parser[I, T], - q: => Parser[I, S])(implicit ev: I => Seq[_]) extends Parser[I, (T, S)] { + q: => Parser[I, S])(implicit ev: I => Seq[_]) extends Parser[I, ~[T, S]] { def parse(sb: I) = for ((head1, tail1) <- p.parse(sb); - (head2, tail2) <- q.parse(tail1)) yield ((head1, head2), tail2) + (head2, tail2) <- q.parse(tail1)) yield (new ~(head1, head2), tail2) } class AltParser[I, T](p: => Parser[I, T], @@ -278,7 +280,7 @@ def ListParser[I, T, S](p: => Parser[I, T], q: => Parser[I, S])(implicit ev: I => Seq[_]): Parser[I, List[T]] = { - (p ~ q ~ ListParser(p, q)) ==> { case ((x, y), z) => x :: z : List[T] } || + (p ~ q ~ ListParser(p, q)) ==> { case x ~ _ ~ z => x :: z : List[T] } || (p ==> ((s) => List(s))) } @@ -337,39 +339,39 @@ // arithmetic expressions lazy val Exp: Parser[List[Token], Exp] = (T_KWD("if") ~ BExp ~ T_KWD("then") ~ Exp ~ T_KWD("else") ~ Exp) ==> - { case (((((x, y), z), u), v), w) => If(y, u, w): Exp } || - (M ~ T_SEMI ~ Exp) ==> { case ((x, y), z) => Sequence(x, z): Exp } || M + { case _ ~ x ~ _ ~ y ~ _ ~ z => If(x, y, z): Exp } || + (M ~ T_SEMI ~ Exp) ==> { case x ~ _ ~ y => Sequence(x, y): Exp } || M lazy val M: Parser[List[Token], Exp] = - (T_KWD("write") ~ L) ==> { case (x, y) => Write(y): Exp } || L + (T_KWD("write") ~ L) ==> { case _ ~ y => Write(y): Exp } || L lazy val L: Parser[List[Token], Exp] = - (T ~ T_OP("+") ~ Exp) ==> { case ((x, y), z) => Aop("+", x, z): Exp } || - (T ~ T_OP("-") ~ Exp) ==> { case ((x, y), z) => Aop("-", x, z): Exp } || T + (T ~ T_OP("+") ~ Exp) ==> { case x ~ _ ~ z => Aop("+", x, z): Exp } || + (T ~ T_OP("-") ~ Exp) ==> { case x ~ _ ~ z => Aop("-", x, z): Exp } || T lazy val T: Parser[List[Token], Exp] = - (F ~ T_OP("*") ~ T) ==> { case ((x, y), z) => Aop("*", x, z): Exp } || - (F ~ T_OP("/") ~ T) ==> { case ((x, y), z) => Aop("/", x, z): Exp } || - (F ~ T_OP("%") ~ T) ==> { case ((x, y), z) => Aop("%", x, z): Exp } || F + (F ~ T_OP("*") ~ T) ==> { case x ~ _ ~ z => Aop("*", x, z): Exp } || + (F ~ T_OP("/") ~ T) ==> { case x ~ _ ~ z => Aop("/", x, z): Exp } || + (F ~ T_OP("%") ~ T) ==> { case x ~ _ ~ z => Aop("%", x, z): Exp } || F lazy val F: Parser[List[Token], Exp] = (IdParser ~ T_LPAREN ~ ListParser(Exp, T_COMMA) ~ T_RPAREN) ==> - { case (((x, y), z), w) => Call(x, z): Exp } || - (T_LPAREN ~ Exp ~ T_RPAREN) ==> { case ((x, y), z) => y: Exp } || + { case x ~ _ ~ z ~ _ => Call(x, z): Exp } || + (T_LPAREN ~ Exp ~ T_RPAREN) ==> { case _ ~ y ~ _ => y: Exp } || IdParser ==> { case x => Var(x): Exp } || NumParser ==> { case x => Num(x): Exp } // boolean expressions lazy val BExp: Parser[List[Token], BExp] = - (Exp ~ T_OP("==") ~ Exp) ==> { case ((x, y), z) => Bop("==", x, z): BExp } || - (Exp ~ T_OP("!=") ~ Exp) ==> { case ((x, y), z) => Bop("!=", x, z): BExp } || - (Exp ~ T_OP("<") ~ Exp) ==> { case ((x, y), z) => Bop("<", x, z): BExp } || - (Exp ~ T_OP(">") ~ Exp) ==> { case ((x, y), z) => Bop("<", z, x): BExp } || - (Exp ~ T_OP("<=") ~ Exp) ==> { case ((x, y), z) => Bop("<=", x, z): BExp } || - (Exp ~ T_OP("=>") ~ Exp) ==> { case ((x, y), z) => Bop("<=", z, x): BExp } + (Exp ~ T_OP("==") ~ Exp) ==> { case x ~ _ ~ z => Bop("==", x, z): BExp } || + (Exp ~ T_OP("!=") ~ Exp) ==> { case x ~ _ ~ z => Bop("!=", x, z): BExp } || + (Exp ~ T_OP("<") ~ Exp) ==> { case x ~ _ ~ z => Bop("<", x, z): BExp } || + (Exp ~ T_OP(">") ~ Exp) ==> { case x ~ _ ~ z => Bop("<", z, x): BExp } || + (Exp ~ T_OP("<=") ~ Exp) ==> { case x ~ _ ~ z => Bop("<=", x, z): BExp } || + (Exp ~ T_OP("=>") ~ Exp) ==> { case x ~ _ ~ z => Bop("<=", z, x): BExp } lazy val Defn: Parser[List[Token], Decl] = (T_KWD("def") ~ IdParser ~ T_LPAREN ~ ListParser(IdParser, T_COMMA) ~ T_RPAREN ~ T_OP("=") ~ Exp) ==> - { case ((((((x, y), z), w), u), v), r) => Def(y, w, r): Decl } + { case _ ~ y ~ _ ~ w ~ _ ~ _ ~ r => Def(y, w, r): Decl } lazy val Prog: Parser[List[Token], List[Decl]] = - (Defn ~ T_SEMI ~ Prog) ==> { case ((x, y), z) => x :: z : List[Decl] } || + (Defn ~ T_SEMI ~ Prog) ==> { case x ~ _ ~ z => x :: z : List[Decl] } || (Exp ==> ((s) => List(Main(s)) : List[Decl])) diff -r f5214da1976e -r 8067d0a8ba04 progs/funt.scala --- a/progs/funt.scala Sun Jul 28 21:10:39 2019 +0100 +++ b/progs/funt.scala Tue Jul 30 20:19:40 2019 +0100 @@ -252,11 +252,15 @@ } } +// convenience for matching later on +case class ~[+A, +B](_1: A, _2: B) + + class SeqParser[I, T, S](p: => Parser[I, T], - q: => Parser[I, S])(implicit ev: I => Seq[_]) extends Parser[I, (T, S)] { + q: => Parser[I, S])(implicit ev: I => Seq[_]) extends Parser[I, ~[T, S]] { def parse(sb: I) = for ((head1, tail1) <- p.parse(sb); - (head2, tail2) <- q.parse(tail1)) yield ((head1, head2), tail2) + (head2, tail2) <- q.parse(tail1)) yield (new ~(head1, head2), tail2) } class AltParser[I, T](p: => Parser[I, T], @@ -278,7 +282,7 @@ def ListParser[I, T, S](p: => Parser[I, T], q: => Parser[I, S])(implicit ev: I => Seq[_]): Parser[I, List[T]] = { - (p ~ q ~ ListParser(p, q)) ==> { case ((x, y), z) => x :: z : List[T] } || + (p ~ q ~ ListParser(p, q)) ==> { case x ~ _ ~ z => x :: z : List[T] } || (p ==> ((s) => List(s))) } @@ -337,39 +341,39 @@ // arithmetic expressions lazy val Exp: Parser[List[Token], Exp] = (T_KWD("if") ~ BExp ~ T_KWD("then") ~ Exp ~ T_KWD("else") ~ Exp) ==> - { case (((((x, y), z), u), v), w) => If(y, u, w): Exp } || - (M ~ T_SEMI ~ Exp) ==> { case ((x, y), z) => Sequence(x, z): Exp } || M + { case _ ~ y ~ _ ~ u ~ _ ~ w => If(y, u, w): Exp } || + (M ~ T_SEMI ~ Exp) ==> { case x ~ _ ~ z => Sequence(x, z): Exp } || M lazy val M: Parser[List[Token], Exp] = - (T_KWD("write") ~ L) ==> { case (x, y) => Write(y): Exp } || L + (T_KWD("write") ~ L) ==> { case _ ~ y => Write(y): Exp } || L lazy val L: Parser[List[Token], Exp] = - (T ~ T_OP("+") ~ Exp) ==> { case ((x, y), z) => Aop("+", x, z): Exp } || - (T ~ T_OP("-") ~ Exp) ==> { case ((x, y), z) => Aop("-", x, z): Exp } || T + (T ~ T_OP("+") ~ Exp) ==> { case x ~ _ ~ z => Aop("+", x, z): Exp } || + (T ~ T_OP("-") ~ Exp) ==> { case x ~ _ ~ z => Aop("-", x, z): Exp } || T lazy val T: Parser[List[Token], Exp] = - (F ~ T_OP("*") ~ T) ==> { case ((x, y), z) => Aop("*", x, z): Exp } || - (F ~ T_OP("/") ~ T) ==> { case ((x, y), z) => Aop("/", x, z): Exp } || - (F ~ T_OP("%") ~ T) ==> { case ((x, y), z) => Aop("%", x, z): Exp } || F + (F ~ T_OP("*") ~ T) ==> { case x ~ _ ~ z => Aop("*", x, z): Exp } || + (F ~ T_OP("/") ~ T) ==> { case x ~ _ ~ z => Aop("/", x, z): Exp } || + (F ~ T_OP("%") ~ T) ==> { case x ~ _ ~ z => Aop("%", x, z): Exp } || F lazy val F: Parser[List[Token], Exp] = (IdParser ~ T_LPAREN ~ ListParser(Exp, T_COMMA) ~ T_RPAREN) ==> - { case (((x, y), z), w) => Call(x, z): Exp } || - (T_LPAREN ~ Exp ~ T_RPAREN) ==> { case ((x, y), z) => y: Exp } || + { case x ~ _ ~ z ~ _ => Call(x, z): Exp } || + (T_LPAREN ~ Exp ~ T_RPAREN) ==> { case _ ~ y ~ _ => y: Exp } || IdParser ==> { case x => Var(x): Exp } || NumParser ==> { case x => Num(x): Exp } // boolean expressions lazy val BExp: Parser[List[Token], BExp] = - (Exp ~ T_OP("==") ~ Exp) ==> { case ((x, y), z) => Bop("==", x, z): BExp } || - (Exp ~ T_OP("!=") ~ Exp) ==> { case ((x, y), z) => Bop("!=", x, z): BExp } || - (Exp ~ T_OP("<") ~ Exp) ==> { case ((x, y), z) => Bop("<", x, z): BExp } || - (Exp ~ T_OP(">") ~ Exp) ==> { case ((x, y), z) => Bop("<", z, x): BExp } || - (Exp ~ T_OP("<=") ~ Exp) ==> { case ((x, y), z) => Bop("<=", x, z): BExp } || - (Exp ~ T_OP("=>") ~ Exp) ==> { case ((x, y), z) => Bop("<=", z, x): BExp } + (Exp ~ T_OP("==") ~ Exp) ==> { case x ~ _ ~ z => Bop("==", x, z): BExp } || + (Exp ~ T_OP("!=") ~ Exp) ==> { case x ~ _ ~ z => Bop("!=", x, z): BExp } || + (Exp ~ T_OP("<") ~ Exp) ==> { case x ~ _ ~ z => Bop("<", x, z): BExp } || + (Exp ~ T_OP(">") ~ Exp) ==> { case x ~ _ ~ z => Bop("<", z, x): BExp } || + (Exp ~ T_OP("<=") ~ Exp) ==> { case x ~ _ ~ z => Bop("<=", x, z): BExp } || + (Exp ~ T_OP("=>") ~ Exp) ==> { case x ~ _ ~ z => Bop("<=", z, x): BExp } lazy val Defn: Parser[List[Token], Decl] = (T_KWD("def") ~ IdParser ~ T_LPAREN ~ ListParser(IdParser, T_COMMA) ~ T_RPAREN ~ T_OP("=") ~ Exp) ==> - { case ((((((x, y), z), w), u), v), r) => Def(y, w, r): Decl } + { case x ~ y ~ z ~ w ~ u ~ v ~ r => Def(y, w, r): Decl } lazy val Prog: Parser[List[Token], List[Decl]] = - (Defn ~ T_SEMI ~ Prog) ==> { case ((x, y), z) => x :: z : List[Decl] } || + (Defn ~ T_SEMI ~ Prog) ==> { case x ~ _ ~ z => x :: z : List[Decl] } || (Exp ==> ((s) => List(Main(s)) : List[Decl])) @@ -543,25 +547,3 @@ //examples compile_run("defs") compile_run("fact") - - - - - -// a problem with the parser -/* -val text = "(((((1)))))" -val tokens = tokenise(text) -println(tokens) -val ast = Prog.parse_single(tokens) -println(ast) - -Exp.parse_single(tokens) - - - -val text = "((((1))))" -val tokens = tokenise(text) -println(tokens) -Exp.parse(tokens) -*/