progs/parser-combinators/comb1.sc
changeset 972 ebb4a40d9bae
parent 961 c0600f8b6427
child 974 0cb4bf2469d1
equal deleted inserted replaced
971:51e00f223792 972:ebb4a40d9bae
    58 case class CharParser(c: Char) extends Parser[String, Char] {
    58 case class CharParser(c: Char) extends Parser[String, Char] {
    59   def parse(in: String) =
    59   def parse(in: String) =
    60     if (in != "" && in.head == c) Set((c, in.tail)) else Set()
    60     if (in != "" && in.head == c) Set((c, in.tail)) else Set()
    61 }
    61 }
    62 
    62 
       
    63 
       
    64 
    63 val ap = CharParser('a')
    65 val ap = CharParser('a')
    64 val bp = CharParser('b')
    66 val bp = CharParser('b')
    65 
    67 
       
    68 print(ap.parse("aade"))
       
    69 
    66 val abp = SeqParser(ap, bp)
    70 val abp = SeqParser(ap, bp)
       
    71 print(abp.parse("abade"))
       
    72 
       
    73 val abp = AltParser(ap, bp)
       
    74 print(abp.parse("abc"))
       
    75 
    67 MapParser(abp, ab => s"$ab").parse("abc")
    76 MapParser(abp, ab => s"$ab").parse("abc")
    68 
    77 
    69 // an atomic parser for parsing strings according to a regex
    78 // an atomic parser for parsing strings according to a regex
    70 import scala.util.matching.Regex
    79 import scala.util.matching.Regex
    71 
    80 
    76   }
    85   }
    77 }
    86 }
    78 
    87 
    79 // atomic parsers for numbers and "verbatim" strings
    88 // atomic parsers for numbers and "verbatim" strings
    80 val NumParser = RegexParser("[0-9]+".r)
    89 val NumParser = RegexParser("[0-9]+".r)
       
    90 NumParser.parse("123abc345")
       
    91 
    81 def StrParser(s: String) = RegexParser(Regex.quote(s).r)
    92 def StrParser(s: String) = RegexParser(Regex.quote(s).r)
    82 
    93 
    83 NumParser.parse("123a123bc")
    94 NumParser.parse("123a123bc")
    84 StrParser("else").parse("elsethen")
    95 StrParser("else").parse("elsethen")
    85 
    96 
    92 
   103 
    93 // the following string interpolation allows us to write
   104 // the following string interpolation allows us to write
    94 // StrParser(_some_string_) more conveniently as
   105 // StrParser(_some_string_) more conveniently as
    95 //
   106 //
    96 // p"<_some_string_>"
   107 // p"<_some_string_>"
       
   108 
       
   109 
    97 
   110 
    98 extension (sc: StringContext)
   111 extension (sc: StringContext)
    99   def p(args: Any*) = StrParser(sc.s(args*))
   112   def p(args: Any*) = StrParser(sc.s(args*))
   100 
   113 
   101 
   114 
   122 // with this NumParserInt can now be written more conveniently
   135 // with this NumParserInt can now be written more conveniently
   123 // as:
   136 // as:
   124 
   137 
   125 val NumParserInt2 = NumParser.map(_.toInt)
   138 val NumParserInt2 = NumParser.map(_.toInt)
   126 
   139 
   127 val x = 1 + 3
   140 
   128 
   141 
   129 // A parser for palindromes (just returns them as string)
   142 // A parser for palindromes (just returns them as string)
   130 //  since the parser is recursive it needs to be lazy
   143 //  since the parser is recursive it needs to be lazy
   131 lazy val Pal : Parser[String, String] = {
   144 lazy val Pal : Parser[String, String] = {
   132    (p"a" ~ Pal ~ p"a").map{ case ((x, y), z) => s"$x$y$z" } ||
   145    (p"a" ~ Pal ~ p"a").map{ case ((x, y), z) => s"$x$y$z" } ||
   133    (p"b" ~ Pal ~ p"b").map{ case ((x, y), z) => s"$x$y$z" } ||
   146    (p"b" ~ Pal ~ p"b").map{ case ((x, y), z) => s"$x$y$z" } ||
   134     p"a" || p"b" || p""
   147     p"a" || p"b" || p""
   135 }
   148 }
   136 
   149 
   137 // examples
   150 // examples
   138 Pal.parse_all("abacaba")
   151 Pal.parse("abaaba")
   139 Pal.parse("abacaaba")
   152 Pal.parse("abacaaba")
   140 
   153 
   141 println("Palindrome: " + Pal.parse_all("abaaaba"))
   154 println("Palindrome: " + Pal.parse_all("abaaaba"))
   142 
   155 
   143 // A parser for wellnested parentheses
   156 // A parser for wellnested parentheses
   154 println(P.parse_all("(((()()))()))"))
   167 println(P.parse_all("(((()()))()))"))
   155 println(P.parse_all(")("))
   168 println(P.parse_all(")("))
   156 println(P.parse_all("()"))
   169 println(P.parse_all("()"))
   157 
   170 
   158 // A parser for arithmetic expressions (Terms and Factors)
   171 // A parser for arithmetic expressions (Terms and Factors)
       
   172 
   159 
   173 
   160 lazy val E: Parser[String, Int] = {
   174 lazy val E: Parser[String, Int] = {
   161   (T ~ p"+" ~ E).map{ case ((x, _), z) => x + z } ||
   175   (T ~ p"+" ~ E).map{ case ((x, _), z) => x + z } ||
   162   (T ~ p"-" ~ E).map{ case ((x, _), z) => x - z } || T }
   176   (T ~ p"-" ~ E).map{ case ((x, _), z) => x - z } || T }
   163 lazy val T: Parser[String, Int] = {
   177 lazy val T: Parser[String, Int] = {
   176 println(E.parse_all("(1+2)+3"))
   190 println(E.parse_all("(1+2)+3"))
   177 println(E.parse_all("1+2+3"))
   191 println(E.parse_all("1+2+3"))
   178 
   192 
   179 
   193 
   180 // with parser combinators (and many other parsing algorithms)
   194 // with parser combinators (and many other parsing algorithms)
   181 // no left-recursion is allowed, otherwise the will loop;
   195 // no left-recursion is allowed, otherwise they will loop;
   182 // newer versions of Scala (3.5) will actually give a warning
   196 // newer versions of Scala (3.5+) will actually give a warning
   183 // about this
   197 // about this
   184 
   198 
   185 /*
   199 /*
   186 lazy val EL: Parser[String, Int] =
   200 lazy val EL: Parser[String, Int] =
   187   ((EL ~ p"+" ~ EL).map{ case ((x, y), z) => x + z} ||
   201   ((EL ~ p"+" ~ EL).map{ case ((x, y), z) => x + z} ||