object HelloWorld def main args Array String class Pos private val pro

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
object HelloWorld {
def main(args: Array[String]) {
}
class Pos private(val prog: String, val offs: Int, val line: Int, val col: Int) {
def this(prog: String) = this(prog, 0, 1, 1)
def ch = if (offs == prog.length) -1 else prog(offs)
def inc = ch match {
case '\n' => new Pos(prog, offs + 1, line + 1, 1)
case -1 => this
case _ => new Pos(prog, offs + 1, line, col + 1)
}
override def toString = "(" + line + ", " + col + ")"
}
object DomainTags extends Enumeration {
type Tag = Value
val ERROR, WHITESPACE, IDENT, NUMBER, END_OF_PROGRAM, OPERATION = Value
}
import DomainTags._
class Scanner {
def scan(start: Pos, list: List[String]): (Tag, Pos, List[String]) = {
(ERROR, start.inc, ("Error at" + start) :: list)
}
}
class Token(val start: Pos, scanner: Scanner, errors: List[String]) {
val (tag, follow, errorList) = start.ch match {
case -1 => (END_OF_PROGRAM, start, errors)
case _ => scanner.scan(start, errors)
}
def image = start.prog.substring(start.offs, follow.offs)
def next = new Token(follow, scanner, errors)
def errList = errors
}
trait Whitespaces extends Scanner {
private def missWhitespace(pos: Pos): Pos = pos.ch match {
case ' ' => missWhitespace(pos.inc)
case '\t' => missWhitespace(pos.inc)
case '\n' => missWhitespace(pos.inc)
case _ => pos
}
override def scan(start: Pos, list: List[String]) = {
val follow = missWhitespace(start)
if (start != follow) (WHITESPACE, follow, list)
else super.scan(start, list)
}
}
trait Numbers extends Scanner {
private def findMinus(pos: Pos): Pos = pos.ch match {
case x if x >= '0' && x <= '9' => findMinus(pos.inc)
case _ => pos
}
private def findNumbers(pos: Pos): Pos = pos.ch match {
case x if x == '-' && pos.inc.ch >= '0' && pos.inc.ch <= '9' => findMinus(pos.inc)
case x if x >= '0' && x <= '9' => findMinus(pos.inc)
case _ => pos
}
override def scan(start: Pos, list: List[String]) = {
val follow = findNumbers(start)
if (start != follow) (NUMBER, follow, list)
else super.scan(start, list)
}
}
trait Idents extends Scanner {
private def findIdents_(pos: Pos): Pos = pos.ch match {
case x if x >= 'a' && x <= 'z' => findIdents_(pos.inc)
case _ => pos
}
private def findIdents(pos: Pos): Pos = pos.ch match {
case x if x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u' || x == 'y' => findIdents_(pos.inc)
case _ => pos
}
override def scan(start: Pos, list: List[String]) = {
val follow = findIdents(start)
if (start != follow) (IDENT, follow, list)
else super.scan(start, list)
}
}
trait Operations extends Scanner {
private def findOperation(pos: Pos): Pos = pos.ch match {
case x if x == '-' && pos.inc.ch == '-' => findOperation(pos.inc.inc)
case x if x == '<' && pos.inc.ch == '=' => findOperation(pos.inc.inc)
case x if x == '<' => findOperation(pos.inc)
case _ => pos
}
override def scan(start: Pos, list: List[String]) = {
val follow = findOperation(start)
if (start != follow) (OPERATION, follow, list)
else super.scan(start, list)
}
}
var t = new Token(
new Pos("-134 5678 -- < <= ogwuygd ldfghjk"),
new Scanner with Operations with Idents with Numbers with Whitespaces,
List()
)
while (t.tag != END_OF_PROGRAM) {
println(t.tag.toString + " " + t.start + "-" + t.follow + ": " + t.image)
t = t.next
}
}