progs/lecture5.scala
author updated
Fri, 07 Dec 2018 02:38:50 +0000
changeset 238 046f37a262d0
parent 226 progs/lecture4.scala@5e489c9fe47b
child 240 b8cdaf51ffef
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
238
046f37a262d0 updated
updated
parents: 226
diff changeset
     1
// Scala Lecture 5
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     2
//=================
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     3
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     4
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     5
238
046f37a262d0 updated
updated
parents: 226
diff changeset
     6
// Laziness with style
046f37a262d0 updated
updated
parents: 226
diff changeset
     7
//=====================
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     8
238
046f37a262d0 updated
updated
parents: 226
diff changeset
     9
// The concept of lazy evaluation doesn’t really exist in 
046f37a262d0 updated
updated
parents: 226
diff changeset
    10
// non-functional languages, but it is pretty easy to grasp. 
046f37a262d0 updated
updated
parents: 226
diff changeset
    11
// Consider first 
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    12
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    13
def square(x: Int) = x * x
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    14
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    15
square(42 + 8)
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    16
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    17
// this is called strict evaluation
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    18
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    19
// pretty expensive operation
046f37a262d0 updated
updated
parents: 226
diff changeset
    20
def peop(n: BigInt): Boolean = peop(n + 1) 
046f37a262d0 updated
updated
parents: 226
diff changeset
    21
val a = "foo"
046f37a262d0 updated
updated
parents: 226
diff changeset
    22
val b = "foo"
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    23
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    24
if (a == b || peop(0)) println("true") else println("false")
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    25
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    26
// this is called lazy evaluation
046f37a262d0 updated
updated
parents: 226
diff changeset
    27
// you delay compuation until it is really 
046f37a262d0 updated
updated
parents: 226
diff changeset
    28
// needed; once calculated though, does not 
046f37a262d0 updated
updated
parents: 226
diff changeset
    29
// need to be re-calculated
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    30
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    31
// a useful example is
046f37a262d0 updated
updated
parents: 226
diff changeset
    32
def time_needed[T](i: Int, code: => T) = {
046f37a262d0 updated
updated
parents: 226
diff changeset
    33
  val start = System.nanoTime()
046f37a262d0 updated
updated
parents: 226
diff changeset
    34
  for (j <- 1 to i) code
046f37a262d0 updated
updated
parents: 226
diff changeset
    35
  val end = System.nanoTime()
046f37a262d0 updated
updated
parents: 226
diff changeset
    36
  f"${(end - start) / (i * 1.0e9)}%.6f secs"
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    37
}
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    38
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    39
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    40
// streams (I do not care how many)
046f37a262d0 updated
updated
parents: 226
diff changeset
    41
// primes: 2, 3, 5, 7, 9, 11, 13 ....
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    42
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    43
def generatePrimes (s: Stream[Int]): Stream[Int] =
046f37a262d0 updated
updated
parents: 226
diff changeset
    44
  s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0))
046f37a262d0 updated
updated
parents: 226
diff changeset
    45
046f37a262d0 updated
updated
parents: 226
diff changeset
    46
val primes: Stream[Int] = generatePrimes(Stream.from(2))
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    47
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    48
// the first 10 primes
046f37a262d0 updated
updated
parents: 226
diff changeset
    49
primes.take(10).toList
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    50
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    51
//primes.filter(_ > 100).take(2000).toList
046f37a262d0 updated
updated
parents: 226
diff changeset
    52
046f37a262d0 updated
updated
parents: 226
diff changeset
    53
time_needed(1, primes.filter(_ > 100).take(3000).toList)
046f37a262d0 updated
updated
parents: 226
diff changeset
    54
time_needed(1, primes.filter(_ > 100).take(3000).toList)
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    55
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    56
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    57
Stream.from(2)
046f37a262d0 updated
updated
parents: 226
diff changeset
    58
Stream.from(2).take(10)
046f37a262d0 updated
updated
parents: 226
diff changeset
    59
Stream.from(2).take(10).print
046f37a262d0 updated
updated
parents: 226
diff changeset
    60
Stream.from(10).take(10).print
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    61
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    62
Stream.from(2).take(10).force
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    63
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    64
// itterative version of the Fibonacci numbers
046f37a262d0 updated
updated
parents: 226
diff changeset
    65
def fibIter(a: BigInt, b: BigInt): Stream[BigInt] =
046f37a262d0 updated
updated
parents: 226
diff changeset
    66
  a #:: fibIter(b, a + b)
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    67
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    68
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    69
fibIter(1, 1).take(10).force
046f37a262d0 updated
updated
parents: 226
diff changeset
    70
fibIter(8, 13).take(10).force
046f37a262d0 updated
updated
parents: 226
diff changeset
    71
046f37a262d0 updated
updated
parents: 226
diff changeset
    72
fibIter(1, 1).drop(10000).take(1).print
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    73
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    74
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    75
// good for testing
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    76
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    77
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    78
// Regular expressions - the power of DSLs in Scala
238
046f37a262d0 updated
updated
parents: 226
diff changeset
    79
//                                     and Laziness
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    80
//==================================================
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    81
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    82
abstract class Rexp
226
5e489c9fe47b updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    83
case object ZERO extends Rexp                     // nothing
5e489c9fe47b updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    84
case object ONE extends Rexp                      // the empty string
5e489c9fe47b updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    85
case class CHAR(c: Char) extends Rexp             // a character c
5e489c9fe47b updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    86
case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative  r1 + r2
5e489c9fe47b updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    87
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence     r1 . r2  
5e489c9fe47b updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    88
case class STAR(r: Rexp) extends Rexp             // star         r*
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    89
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    90
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    91
226
5e489c9fe47b updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    92
// writing (ab)* in the format above is 
5e489c9fe47b updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    93
// tedious
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    94
val r0 = STAR(SEQ(CHAR('a'), CHAR('b')))
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    95
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    96
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    97
// some convenience for typing in regular expressions
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    98
import scala.language.implicitConversions    
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    99
import scala.language.reflectiveCalls 
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   100
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   101
def charlist2rexp(s: List[Char]): Rexp = s match {
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   102
  case Nil => ONE
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   103
  case c::Nil => CHAR(c)
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   104
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   105
}
224
42d760984496 updated
Christian Urban <urbanc@in.tum.de>
parents: 223
diff changeset
   106
implicit def string2rexp(s: String): Rexp = 
42d760984496 updated
Christian Urban <urbanc@in.tum.de>
parents: 223
diff changeset
   107
  charlist2rexp(s.toList)
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   108
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   109
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   110
val r1 = STAR("ab")
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   111
val r2 = STAR(ALT("ab", "baa baa black sheep"))
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   112
val r3 = STAR(SEQ("ab", ALT("a", "b")))
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   113
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   114
implicit def RexpOps (r: Rexp) = new {
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   115
  def | (s: Rexp) = ALT(r, s)
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   116
  def % = STAR(r)
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   117
  def ~ (s: Rexp) = SEQ(r, s)
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   118
}
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   119
226
5e489c9fe47b updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   120
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   121
implicit def stringOps (s: String) = new {
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   122
  def | (r: Rexp) = ALT(s, r)
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   123
  def | (r: String) = ALT(s, r)
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   124
  def % = STAR(s)
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   125
  def ~ (r: Rexp) = SEQ(s, r)
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   126
  def ~ (r: String) = SEQ(s, r)
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   127
}
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   128
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   129
046f37a262d0 updated
updated
parents: 226
diff changeset
   130
def depth(r: Rexp) : Int = r match {
046f37a262d0 updated
updated
parents: 226
diff changeset
   131
  case ZERO => 0
046f37a262d0 updated
updated
parents: 226
diff changeset
   132
  case ONE => 0
046f37a262d0 updated
updated
parents: 226
diff changeset
   133
  case CHAR(_) => 0
046f37a262d0 updated
updated
parents: 226
diff changeset
   134
  case ALT(r1, r2) => Math.max(depth(r1), depth(r2)) + 1
046f37a262d0 updated
updated
parents: 226
diff changeset
   135
  case SEQ(r1, r2) => Math.max(depth(r1), depth(r2)) + 1 
046f37a262d0 updated
updated
parents: 226
diff changeset
   136
  case STAR(r1) => depth(r1) + 1
046f37a262d0 updated
updated
parents: 226
diff changeset
   137
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   138
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   139
//example regular expressions
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   140
val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   141
val sign = "+" | "-" | ""
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   142
val number = sign ~ digit ~ digit.% 
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   143
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   144
// task: enumerate exhaustively regular expression
046f37a262d0 updated
updated
parents: 226
diff changeset
   145
// starting from small ones towards bigger ones.
046f37a262d0 updated
updated
parents: 226
diff changeset
   146
046f37a262d0 updated
updated
parents: 226
diff changeset
   147
// 1st idea: enumerate them up to a level
046f37a262d0 updated
updated
parents: 226
diff changeset
   148
046f37a262d0 updated
updated
parents: 226
diff changeset
   149
def enuml(l: Int, s: String) : Set[Rexp] = l match {
046f37a262d0 updated
updated
parents: 226
diff changeset
   150
  case 0 => Set(ZERO, ONE) ++ s.map(CHAR).toSet
046f37a262d0 updated
updated
parents: 226
diff changeset
   151
  case n =>  
046f37a262d0 updated
updated
parents: 226
diff changeset
   152
    val rs = enuml(n - 1, s)
046f37a262d0 updated
updated
parents: 226
diff changeset
   153
    rs ++
046f37a262d0 updated
updated
parents: 226
diff changeset
   154
    (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) ++
046f37a262d0 updated
updated
parents: 226
diff changeset
   155
    (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) ++
046f37a262d0 updated
updated
parents: 226
diff changeset
   156
    (for (r1 <- rs) yield STAR(r1))
046f37a262d0 updated
updated
parents: 226
diff changeset
   157
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   158
046f37a262d0 updated
updated
parents: 226
diff changeset
   159
enuml(1, "a").size
046f37a262d0 updated
updated
parents: 226
diff changeset
   160
enuml(2, "a").size
046f37a262d0 updated
updated
parents: 226
diff changeset
   161
enuml(3, "a").size // out of heap space
046f37a262d0 updated
updated
parents: 226
diff changeset
   162
046f37a262d0 updated
updated
parents: 226
diff changeset
   163
046f37a262d0 updated
updated
parents: 226
diff changeset
   164
def enum(rs: Stream[Rexp]) : Stream[Rexp] = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   165
  rs #::: enum( (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) #:::
046f37a262d0 updated
updated
parents: 226
diff changeset
   166
                (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #:::
046f37a262d0 updated
updated
parents: 226
diff changeset
   167
                (for (r1 <- rs) yield STAR(r1)) )
046f37a262d0 updated
updated
parents: 226
diff changeset
   168
046f37a262d0 updated
updated
parents: 226
diff changeset
   169
046f37a262d0 updated
updated
parents: 226
diff changeset
   170
enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(200).force
046f37a262d0 updated
updated
parents: 226
diff changeset
   171
enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(200000).force
046f37a262d0 updated
updated
parents: 226
diff changeset
   172
046f37a262d0 updated
updated
parents: 226
diff changeset
   173
046f37a262d0 updated
updated
parents: 226
diff changeset
   174
val is = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   175
  (enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR))
046f37a262d0 updated
updated
parents: 226
diff changeset
   176
    .dropWhile(depth(_) < 3)
046f37a262d0 updated
updated
parents: 226
diff changeset
   177
    .take(10).foreach(println))
046f37a262d0 updated
updated
parents: 226
diff changeset
   178
046f37a262d0 updated
updated
parents: 226
diff changeset
   179
046f37a262d0 updated
updated
parents: 226
diff changeset
   180
046f37a262d0 updated
updated
parents: 226
diff changeset
   181
// Parsing - The Solved Problem That Isn't
046f37a262d0 updated
updated
parents: 226
diff changeset
   182
//=========================================
046f37a262d0 updated
updated
parents: 226
diff changeset
   183
//
046f37a262d0 updated
updated
parents: 226
diff changeset
   184
// https://tratt.net/laurie/blog/entries/parsing_the_solved_problem_that_isnt.html
046f37a262d0 updated
updated
parents: 226
diff changeset
   185
//
046f37a262d0 updated
updated
parents: 226
diff changeset
   186
// Or, A topic of endless "fun"(?)
046f37a262d0 updated
updated
parents: 226
diff changeset
   187
046f37a262d0 updated
updated
parents: 226
diff changeset
   188
046f37a262d0 updated
updated
parents: 226
diff changeset
   189
// input type: String
046f37a262d0 updated
updated
parents: 226
diff changeset
   190
// output type: Int
046f37a262d0 updated
updated
parents: 226
diff changeset
   191
Integer.parseInt("123456")
046f37a262d0 updated
updated
parents: 226
diff changeset
   192
046f37a262d0 updated
updated
parents: 226
diff changeset
   193
/* Note, in the previous lectures I did not show the type consraint
046f37a262d0 updated
updated
parents: 226
diff changeset
   194
 * I <% Seq[_] , which means that the input type I can be
046f37a262d0 updated
updated
parents: 226
diff changeset
   195
 * treated, or seen, as a sequence. */
046f37a262d0 updated
updated
parents: 226
diff changeset
   196
046f37a262d0 updated
updated
parents: 226
diff changeset
   197
abstract class Parser[I <% Seq[_], T] {
046f37a262d0 updated
updated
parents: 226
diff changeset
   198
  def parse(ts: I): Set[(T, I)]
046f37a262d0 updated
updated
parents: 226
diff changeset
   199
046f37a262d0 updated
updated
parents: 226
diff changeset
   200
  def parse_all(ts: I) : Set[T] =
046f37a262d0 updated
updated
parents: 226
diff changeset
   201
    for ((head, tail) <- parse(ts); 
046f37a262d0 updated
updated
parents: 226
diff changeset
   202
        if (tail.isEmpty)) yield head
046f37a262d0 updated
updated
parents: 226
diff changeset
   203
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   204
046f37a262d0 updated
updated
parents: 226
diff changeset
   205
// the idea is that a parser can parse something
046f37a262d0 updated
updated
parents: 226
diff changeset
   206
// from the input and leaves something unparsed => pairs
046f37a262d0 updated
updated
parents: 226
diff changeset
   207
046f37a262d0 updated
updated
parents: 226
diff changeset
   208
class AltParser[I <% Seq[_], T](
046f37a262d0 updated
updated
parents: 226
diff changeset
   209
  p: => Parser[I, T], 
046f37a262d0 updated
updated
parents: 226
diff changeset
   210
  q: => Parser[I, T]) extends Parser[I, T] {
046f37a262d0 updated
updated
parents: 226
diff changeset
   211
046f37a262d0 updated
updated
parents: 226
diff changeset
   212
  def parse(sb: I) = p.parse(sb) ++ q.parse(sb)   
046f37a262d0 updated
updated
parents: 226
diff changeset
   213
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   214
046f37a262d0 updated
updated
parents: 226
diff changeset
   215
046f37a262d0 updated
updated
parents: 226
diff changeset
   216
class SeqParser[I <% Seq[_], T, S](
046f37a262d0 updated
updated
parents: 226
diff changeset
   217
  p: => Parser[I, T], 
046f37a262d0 updated
updated
parents: 226
diff changeset
   218
  q: => Parser[I, S]) extends Parser[I, (T, S)] {
046f37a262d0 updated
updated
parents: 226
diff changeset
   219
046f37a262d0 updated
updated
parents: 226
diff changeset
   220
  def parse(sb: I) = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   221
    for ((head1, tail1) <- p.parse(sb); 
046f37a262d0 updated
updated
parents: 226
diff changeset
   222
         (head2, tail2) <- q.parse(tail1)) yield ((head1, head2), tail2)
046f37a262d0 updated
updated
parents: 226
diff changeset
   223
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   224
046f37a262d0 updated
updated
parents: 226
diff changeset
   225
046f37a262d0 updated
updated
parents: 226
diff changeset
   226
class FunParser[I <% Seq[_], T, S](
046f37a262d0 updated
updated
parents: 226
diff changeset
   227
  p: => Parser[I, T], 
046f37a262d0 updated
updated
parents: 226
diff changeset
   228
  f: T => S) extends Parser[I, S] {
046f37a262d0 updated
updated
parents: 226
diff changeset
   229
046f37a262d0 updated
updated
parents: 226
diff changeset
   230
  def parse(sb: I) = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   231
    for ((head, tail) <- p.parse(sb)) yield (f(head), tail)
046f37a262d0 updated
updated
parents: 226
diff changeset
   232
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   233
046f37a262d0 updated
updated
parents: 226
diff changeset
   234
046f37a262d0 updated
updated
parents: 226
diff changeset
   235
implicit def ParserOps[I<% Seq[_], T](p: Parser[I, T]) = new {
046f37a262d0 updated
updated
parents: 226
diff changeset
   236
  def | (q : => Parser[I, T]) = new AltParser[I, T](p, q)
046f37a262d0 updated
updated
parents: 226
diff changeset
   237
  def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f)
046f37a262d0 updated
updated
parents: 226
diff changeset
   238
  def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)
046f37a262d0 updated
updated
parents: 226
diff changeset
   239
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   240
046f37a262d0 updated
updated
parents: 226
diff changeset
   241
implicit def StringOps(s: String) = new {
046f37a262d0 updated
updated
parents: 226
diff changeset
   242
  def | (q : => Parser[String, String]) = new AltParser[String, String](s, q)
046f37a262d0 updated
updated
parents: 226
diff changeset
   243
  def | (r: String) = new AltParser[String, String](s, r)
046f37a262d0 updated
updated
parents: 226
diff changeset
   244
  def ==>[S] (f: => String => S) = new FunParser[String, String, S](s, f)
046f37a262d0 updated
updated
parents: 226
diff changeset
   245
  def ~[S] (q : => Parser[String, S]) = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   246
    new SeqParser[String, String, S](s, q)
046f37a262d0 updated
updated
parents: 226
diff changeset
   247
  def ~ (r: String) = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   248
    new SeqParser[String, String, String](s, r)
046f37a262d0 updated
updated
parents: 226
diff changeset
   249
}
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   250
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   251
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   252
// atomic parsers  
046f37a262d0 updated
updated
parents: 226
diff changeset
   253
case class CharParser(c: Char) extends Parser[String, Char] {
046f37a262d0 updated
updated
parents: 226
diff changeset
   254
  def parse(sb: String) = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   255
    if (sb != "" && sb.head == c) Set((c, sb.tail)) else Set()
046f37a262d0 updated
updated
parents: 226
diff changeset
   256
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   257
046f37a262d0 updated
updated
parents: 226
diff changeset
   258
import scala.util.matching.Regex
046f37a262d0 updated
updated
parents: 226
diff changeset
   259
case class RegexParser(reg: Regex) extends Parser[String, String] {
046f37a262d0 updated
updated
parents: 226
diff changeset
   260
  def parse(sb: String) = reg.findPrefixMatchOf(sb) match {
046f37a262d0 updated
updated
parents: 226
diff changeset
   261
    case None => Set()
046f37a262d0 updated
updated
parents: 226
diff changeset
   262
    case Some(m) => Set((m.matched, m.after.toString))  
046f37a262d0 updated
updated
parents: 226
diff changeset
   263
  }
046f37a262d0 updated
updated
parents: 226
diff changeset
   264
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   265
046f37a262d0 updated
updated
parents: 226
diff changeset
   266
val NumParser = RegexParser("[0-9]+".r)
046f37a262d0 updated
updated
parents: 226
diff changeset
   267
def StringParser(s: String) = RegexParser(Regex.quote(s).r)
046f37a262d0 updated
updated
parents: 226
diff changeset
   268
046f37a262d0 updated
updated
parents: 226
diff changeset
   269
println(NumParser.parse_all("12345"))
046f37a262d0 updated
updated
parents: 226
diff changeset
   270
println(NumParser.parse_all("12u45"))
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   271
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   272
046f37a262d0 updated
updated
parents: 226
diff changeset
   273
// convenience
046f37a262d0 updated
updated
parents: 226
diff changeset
   274
implicit def string2parser(s: String) = StringParser(s)
046f37a262d0 updated
updated
parents: 226
diff changeset
   275
implicit def char2parser(c: Char) = CharParser(c)
046f37a262d0 updated
updated
parents: 226
diff changeset
   276
046f37a262d0 updated
updated
parents: 226
diff changeset
   277
implicit def ParserOps[I<% Seq[_], T](p: Parser[I, T]) = new {
046f37a262d0 updated
updated
parents: 226
diff changeset
   278
  def | (q : => Parser[I, T]) = new AltParser[I, T](p, q)
046f37a262d0 updated
updated
parents: 226
diff changeset
   279
  def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f)
046f37a262d0 updated
updated
parents: 226
diff changeset
   280
  def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)
046f37a262d0 updated
updated
parents: 226
diff changeset
   281
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   282
046f37a262d0 updated
updated
parents: 226
diff changeset
   283
implicit def StringOps(s: String) = new {
046f37a262d0 updated
updated
parents: 226
diff changeset
   284
  def | (q : => Parser[String, String]) = new AltParser[String, String](s, q)
046f37a262d0 updated
updated
parents: 226
diff changeset
   285
  def | (r: String) = new AltParser[String, String](s, r)
046f37a262d0 updated
updated
parents: 226
diff changeset
   286
  def ==>[S] (f: => String => S) = new FunParser[String, String, S](s, f)
046f37a262d0 updated
updated
parents: 226
diff changeset
   287
  def ~[S] (q : => Parser[String, S]) = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   288
    new SeqParser[String, String, S](s, q)
046f37a262d0 updated
updated
parents: 226
diff changeset
   289
  def ~ (r: String) = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   290
    new SeqParser[String, String, String](s, r)
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   291
}
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   292
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   293
046f37a262d0 updated
updated
parents: 226
diff changeset
   294
val NumParserInt = NumParser ==> (s => s.toInt)
046f37a262d0 updated
updated
parents: 226
diff changeset
   295
046f37a262d0 updated
updated
parents: 226
diff changeset
   296
NumParser.parse_all("12345")
046f37a262d0 updated
updated
parents: 226
diff changeset
   297
NumParserInt.parse_all("12345")
046f37a262d0 updated
updated
parents: 226
diff changeset
   298
NumParserInt.parse_all("12u45")
046f37a262d0 updated
updated
parents: 226
diff changeset
   299
046f37a262d0 updated
updated
parents: 226
diff changeset
   300
046f37a262d0 updated
updated
parents: 226
diff changeset
   301
// grammar for arithmetic expressions
046f37a262d0 updated
updated
parents: 226
diff changeset
   302
//
046f37a262d0 updated
updated
parents: 226
diff changeset
   303
//  E ::= T + E | T - E | T
046f37a262d0 updated
updated
parents: 226
diff changeset
   304
//  T ::= F * T | F
046f37a262d0 updated
updated
parents: 226
diff changeset
   305
//  F ::= ( E ) | Number
046f37a262d0 updated
updated
parents: 226
diff changeset
   306
046f37a262d0 updated
updated
parents: 226
diff changeset
   307
046f37a262d0 updated
updated
parents: 226
diff changeset
   308
lazy val E: Parser[String, Int] = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   309
  (T ~ "+" ~ E) ==> { case ((x, y), z) => x + z } |
046f37a262d0 updated
updated
parents: 226
diff changeset
   310
  (T ~ "-" ~ E) ==> { case ((x, y), z) => x - z } | T 
046f37a262d0 updated
updated
parents: 226
diff changeset
   311
lazy val T: Parser[String, Int] = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   312
  (F ~ "*" ~ T) ==> { case ((x, y), z) => x * z } | F
046f37a262d0 updated
updated
parents: 226
diff changeset
   313
lazy val F: Parser[String, Int] = 
046f37a262d0 updated
updated
parents: 226
diff changeset
   314
  ("(" ~ E ~ ")") ==> { case ((x, y), z) => y } | NumParserInt
046f37a262d0 updated
updated
parents: 226
diff changeset
   315
046f37a262d0 updated
updated
parents: 226
diff changeset
   316
println(E.parse_all("1+3+4"))
046f37a262d0 updated
updated
parents: 226
diff changeset
   317
println(E.parse_all("4*2+3"))
046f37a262d0 updated
updated
parents: 226
diff changeset
   318
println(E.parse_all("4*(2+3)"))
046f37a262d0 updated
updated
parents: 226
diff changeset
   319
println(E.parse_all("(4)*((2+3))"))
046f37a262d0 updated
updated
parents: 226
diff changeset
   320
println(E.parse_all("4/2+3"))
046f37a262d0 updated
updated
parents: 226
diff changeset
   321
println(E.parse_all("(1+2)+3"))
046f37a262d0 updated
updated
parents: 226
diff changeset
   322
println(E.parse_all("1+2+3")) 
046f37a262d0 updated
updated
parents: 226
diff changeset
   323
046f37a262d0 updated
updated
parents: 226
diff changeset
   324
046f37a262d0 updated
updated
parents: 226
diff changeset
   325
046f37a262d0 updated
updated
parents: 226
diff changeset
   326
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   327
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   328
// The End ... Almost Christimas
046f37a262d0 updated
updated
parents: 226
diff changeset
   329
//===============================
046f37a262d0 updated
updated
parents: 226
diff changeset
   330
046f37a262d0 updated
updated
parents: 226
diff changeset
   331
// I hope you had fun!
046f37a262d0 updated
updated
parents: 226
diff changeset
   332
046f37a262d0 updated
updated
parents: 226
diff changeset
   333
// A function should do one thing, and only one thing.
046f37a262d0 updated
updated
parents: 226
diff changeset
   334
046f37a262d0 updated
updated
parents: 226
diff changeset
   335
// Make your variables immutable, unless there's a good 
046f37a262d0 updated
updated
parents: 226
diff changeset
   336
// reason not to.
046f37a262d0 updated
updated
parents: 226
diff changeset
   337
046f37a262d0 updated
updated
parents: 226
diff changeset
   338
// I did it, but this is actually not a good reason:
046f37a262d0 updated
updated
parents: 226
diff changeset
   339
// generating new labels
046f37a262d0 updated
updated
parents: 226
diff changeset
   340
var counter = -1
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   341
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   342
def Fresh(x: String) = {
046f37a262d0 updated
updated
parents: 226
diff changeset
   343
  counter += 1
046f37a262d0 updated
updated
parents: 226
diff changeset
   344
  x ++ "_" ++ counter.toString()
046f37a262d0 updated
updated
parents: 226
diff changeset
   345
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   346
046f37a262d0 updated
updated
parents: 226
diff changeset
   347
Fresh("x")
046f37a262d0 updated
updated
parents: 226
diff changeset
   348
Fresh("x")
046f37a262d0 updated
updated
parents: 226
diff changeset
   349
046f37a262d0 updated
updated
parents: 226
diff changeset
   350
046f37a262d0 updated
updated
parents: 226
diff changeset
   351
046f37a262d0 updated
updated
parents: 226
diff changeset
   352
// You can be productive on Day 1, but the language is deep.
046f37a262d0 updated
updated
parents: 226
diff changeset
   353
//
046f37a262d0 updated
updated
parents: 226
diff changeset
   354
// http://scalapuzzlers.com
046f37a262d0 updated
updated
parents: 226
diff changeset
   355
//
046f37a262d0 updated
updated
parents: 226
diff changeset
   356
// http://www.latkin.org/blog/2017/05/02/when-the-scala-compiler-doesnt-help/
046f37a262d0 updated
updated
parents: 226
diff changeset
   357
046f37a262d0 updated
updated
parents: 226
diff changeset
   358
List(1, 2, 3) contains "your mom"
046f37a262d0 updated
updated
parents: 226
diff changeset
   359
046f37a262d0 updated
updated
parents: 226
diff changeset
   360
// I like best about Scala that it lets me often write
046f37a262d0 updated
updated
parents: 226
diff changeset
   361
// concise, readable code. And it hooks up with the 
046f37a262d0 updated
updated
parents: 226
diff changeset
   362
// Isabelle theorem prover.
046f37a262d0 updated
updated
parents: 226
diff changeset
   363