progs/parser-combinators/comb1.sc
changeset 961 c0600f8b6427
parent 960 c7009356ddd8
child 972 ebb4a40d9bae
--- a/progs/parser-combinators/comb1.sc	Wed May 29 13:25:30 2024 +0100
+++ b/progs/parser-combinators/comb1.sc	Thu Sep 19 15:47:33 2024 +0100
@@ -7,22 +7,30 @@
 
 
 //  Note, in the lectures I did not show the type bound
-//  using is: I => Seq[_], which means that the input
-//  type 'I' needs to be a sequence.
+//  I : IsSeq, which means that the input type 'I' needs 
+//  to be a sequence that can be tested to be empty.
+
+trait IsSeq[I] {
+  extension (i: I) def isEmpty: Boolean
+}
 
-type IsSeq[I] = I => Seq[?]
+given IsSeq[String] = _.isEmpty
+given [I]: IsSeq[Seq[I]] = _.isEmpty
+
 
-abstract class Parser[I: IsSeq, T](using is: IsSeq[I])  {
+// parser class
+//==============
+
+abstract class Parser[I : IsSeq, T]  {
   def parse(in: I): Set[(T, I)]
 
   def parse_all(in: I) : Set[T] =
     for ((hd, tl) <- parse(in);
-        if is(tl).isEmpty) yield hd
+        if tl.isEmpty) yield hd
 }
 
-
 // parser combinators
-
+//====================
 
 // alternative parser
 class AltParser[I : IsSeq, T](p: => Parser[I, T],
@@ -169,14 +177,18 @@
 println(E.parse_all("1+2+3"))
 
 
-// with parser combinators (and other parsing algorithms)
-// no left-recursion is allowed, otherwise the will loop
+// with parser combinators (and many other parsing algorithms)
+// no left-recursion is allowed, otherwise the will loop;
+// newer versions of Scala (3.5) will actually give a warning
+// about this
 
+/*
 lazy val EL: Parser[String, Int] =
   ((EL ~ p"+" ~ EL).map{ case ((x, y), z) => x + z} ||
    (EL ~ p"*" ~ EL).map{ case ((x, y), z) => x * z} ||
    (p"(" ~ EL ~ p")").map{ case ((x, y), z) => y} ||
    NumParserInt)
+*/
 
 // this will run forever:
 //println(EL.parse_all("1+2+3"))