class Lexer(ch : CharStream) { val EOL = '\n' val keywords = Map("while" -> WHILE, "if" -> IF, "println" -> PRINTLN, "readln" -> READLN) var current : Token = EOF private def skippedComment : Boolean = { if (ch.current == '/') { ch.next if (ch.current == '/') { ch.next while ((ch.current != EOL) && !ch.eof) ch.next true } else { current = DIV false } } else { false } } private def skipSpaces = { while (((ch.current <= ' ') || skippedComment) && !ch.eof) ch.next } private def isLetter : Boolean = ('A' <= ch.current && ch.current <= 'Z') || ('a' <= ch.current && ch.current <= 'z') || ('_' == ch.current) private def isDigit : Boolean = ('0' <= ch.current) & (ch.current <= '9') private def getIdent = { var s = new StringBuffer() while ((isLetter || isDigit) && !ch.eof) { s.append(ch.current) ch.next } val str = s.toString if (keywords.isDefinedAt(str)) { current = keywords(str) } else { current = ID(str); } } private def getInt = { var k = 0; while (isDigit && !ch.eof) { val digit = ch.current.asInstanceOf[Int] - '0'.asInstanceOf[Int]; k = k * 10 + digit ch.next } current = IntConst(k) } def next : Unit = { if (ch.eof) {current = EOF; return} current = null skipSpaces if (current != null) return if (ch.eof) {current = EOF; return} if (isLetter) {getIdent; return} if (isDigit) {getInt; return} ch.current match { case '(' => {current = OPAREN; ch.next; return} case ')' => {current = CPAREN; ch.next; return} case '{' => {current = OBRACE; ch.next; return} case '}' => {current = CBRACE; ch.next; return} case ';' => {current = SEMICOL; ch.next; return} case '+' => {current = PLUS; ch.next; return} case '-' => {current = MINUS; ch.next; return} case '/' => {current = DIV; ch.next; return} case '*' => {current = MUL; ch.next; return} case '=' => { ch.next if (ch.current=='=') {ch.next; current = CompareEQ; return} else {current = AssignEQ; return} } case '<' => { ch.next if (ch.current=='=') {ch.next; current = LEQ; return} else {current = LESS; return} } case _ => { current = new Unknown(ch.current); ch.next } } } next // initialize lexer to first token }