# HG changeset patch # User Christian Urban # Date 1698584709 0 # Node ID 6bb67c2dcfd31e015fb07f1e1e57ad36982097a6 # Parent dc31a099dc985fa865eaef9eb0a38386a71fa0bc updated diff -r dc31a099dc98 -r 6bb67c2dcfd3 progs/lexer/lex.sc --- a/progs/lexer/lex.sc Sun Oct 29 00:06:30 2023 +0100 +++ b/progs/lexer/lex.sc Sun Oct 29 13:05:09 2023 +0000 @@ -46,13 +46,10 @@ def ~ (s: Rexp) = SEQ(r, s) } +// to use & for records, instead of $ which had +// its precedence be changed in Scala 3 extension (s: String) { - def | (r: Rexp) = ALT(s, r) - def | (r: String) = ALT(s, r) - def % = STAR(s) - def ~ (r: Rexp) = SEQ(s, r) - def ~ (r: String) = SEQ(s, r) - def $ (r: Rexp) = RECD(s, r) + def & (r: Rexp) = RECD(s, r) } val TEST = ("ab" | "ba").% @@ -166,20 +163,20 @@ val STRING: Rexp = "\"" ~ SYM.% ~ "\"" -val WHILE_REGS = (("k" $ KEYWORD) | - ("i" $ ID) | - ("o" $ OP) | - ("n" $ NUM) | - ("s" $ SEMI) | - ("str" $ STRING) | - ("p" $ (LPAREN | RPAREN)) | - ("w" $ WHITESPACE)).% +val WHILE_REGS = (("k" & KEYWORD) | + ("i" & ID) | + ("o" & OP) | + ("n" & NUM) | + ("s" & SEMI) | + ("str" & STRING) | + ("p" & (LPAREN | RPAREN)) | + ("w" & WHITESPACE)).% val KY : Rexp = "if" | "read" | "write" val WH : Rexp = " " | "\n" -val TRIV_REGS = (("k" $ KY) | - ("w" $ WHITESPACE)).% +val TRIV_REGS = (("k" & KY) | + ("w" & WHITESPACE)).% // Two Simple While Tests //======================== @@ -201,8 +198,3 @@ println(lexing(WHILE_REGS, prog2)) } - - - - -// runs with amm2 and amm3 diff -r dc31a099dc98 -r 6bb67c2dcfd3 progs/parser-combinators/comb1.sc --- a/progs/parser-combinators/comb1.sc Sun Oct 29 00:06:30 2023 +0100 +++ b/progs/parser-combinators/comb1.sc Sun Oct 29 13:05:09 2023 +0000 @@ -23,7 +23,6 @@ // parser combinators - // alternative parser class AltParser[I : IsSeq, T](p: => Parser[I, T], q: => Parser[I, T]) extends Parser[I, T] { @@ -96,9 +95,11 @@ def map[S](f: => T => S) = new MapParser[I, T, S](p, f) } +// simple example of transforming the +// result into capital letters def toU(s: String) = s.map(_.toUpper) -(p"ELSE").map(toU(_)).parse("ELSEifthen") +(p"else").map(toU(_)).parse("elseifthen") // these implicits allow us to use an infix notation for // sequences and alternatives; we also can write the usual @@ -112,6 +113,7 @@ // A parser for palindromes (just returns them as string) +// since the parser is recursive it needs to be lazy lazy val Pal : Parser[String, String] = { (p"a" ~ Pal ~ p"a").map{ case ((x, y), z) => s"$x$y$z" } || (p"b" ~ Pal ~ p"b").map{ case ((x, y), z) => s"$x$y$z" } || diff -r dc31a099dc98 -r 6bb67c2dcfd3 progs/parser-combinators/comb2.sc --- a/progs/parser-combinators/comb2.sc Sun Oct 29 00:06:30 2023 +0100 +++ b/progs/parser-combinators/comb2.sc Sun Oct 29 13:05:09 2023 +0000 @@ -14,9 +14,9 @@ // it allows writing nested patterns as // case x ~ y ~ z => ... +case class ~[+A, +B](x: A, y: B) -case class ~[+A, +B](x: A, y: B) type IsSeq[I] = I => Seq[_] @@ -45,7 +45,7 @@ } // map parser -class maparser[I : IsSeq, T, S](p: => Parser[I, T], +class MapParser[I : IsSeq, T, S](p: => Parser[I, T], f: T => S) extends Parser[I, S] { def parse(in: I) = for ((hd, tl) <- p.parse(in)) yield (f(hd), tl) } @@ -70,7 +70,7 @@ } -// atomic parser for numbers (transformed into ints) +// atomic parser for numbers (transformed into Ints) case object NumParser extends Parser[String, Int] { val reg = "[0-9]+".r def parse(sb: String) = reg.findPrefixOf(sb) match { @@ -95,7 +95,7 @@ extension [I : IsSeq, T](p: Parser[I, T]) { def ||(q : => Parser[I, T]) = new AltParser[I, T](p, q) def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q) - def map[S](f: => T => S) = new maparser[I, T, S](p, f) + def map[S](f: => T => S) = new MapParser[I, T, S](p, f) } @@ -134,8 +134,8 @@ (Fa ~ p"/" ~ Te).map[AExp]{ case x ~ _ ~ z => Aop("/", x, z) } || Fa lazy val Fa: Parser[String, AExp] = (p"(" ~ AExp ~ p")").map{ case _ ~ y ~ _ => y } || - IdParser.map(Var) || - NumParser.map(Num) + IdParser.map(Var(_)) || + NumParser.map(Num(_)) // boolean expressions with some simple nesting lazy val BExp: Parser[String, BExp] =