--- 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
--- 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)
--- 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")
--- 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
--- 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]))
--- 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)
-*/