public Token scan() { // skip empty symbols and comments for (; ; readch()) { if (peek == ' ' || peek == '\t') continue; else if (peek == '\n') line++; // skip comments else if (peek == '/') { readch(); if (peek == '/') { do { readch(); } while (peek != '\n'); line++; } else if (peek == '*') { for (; ; ) { readch(); if (peek == '*') if (readch('/')) break; if (peek == '\n') line++; } } else return new Token('/'); } else break; } // scan for not alone math symbols switch (peek) { case '&': if (readch('&')) return Word.and; else return new Token('&'); case '|': if (readch('|')) return Word.or; else return new Token('|'); case '=': if (readch('=')) return Word.eq; else return new Token('='); case '!': if (readch('=')) return Word.ne; else return new Token('!'); case '<': if (readch('=')) return Word.le; else return new Token('<'); case '>': if (readch('=')) return Word.ge; else return new Token('>'); case '+': if (readch('+')) return Word.inc; else return new Token('+'); case '-': if (readch('-')) return Word.dec; else return new Token('-'); } // found quotes, so parse sting for print if (peek == '"') { StringBuffer b = new StringBuffer(); readch(); while (peek != '"') { // found slash, parse special symbol if (peek == '\\') { readch(); if (peek == 'n') b.append('\n'); else if (peek == 't') b.append('\t'); else if (peek == '\\') b.append('\\'); else if (peek == '\'') b.append('\''); else if (peek == '\"') b.append('\"'); else throw new Error("Can't recognise symbol at " + line + " line"); } else b.append(peek); readch(); } readch(); return new Text(b.toString()); } // scan for number if (Character.isDigit(peek)) { StringBuilder b = new StringBuilder(); do { b.append(peek); readch(); } while (Character.isDigit(peek)); // look is number were written in hex or bin format if (peek == 'h' || peek == 'H') { readch(); return new Number(Integer.parseInt(b.toString(), 16)); } if (peek == 'b' || peek == 'B') { readch(); return new Number(Integer.parseInt(b.toString(), 2)); } // look is number float if (peek != '.') return new Number(Integer.parseInt(b.toString())); float x = Integer.parseInt(b.toString()); float d = 10; for (; ; ) { readch(); if (!Character.isDigit(peek)) break; x = x + Character.digit(peek, 10) / d; d = d * 10; } return new Real(x); } // scan for words if (Character.isLetter(peek) || peek == '_') { StringBuilder builder = new StringBuilder(); do { builder.append(peek); readch(); } while (Character.isLetterOrDigit(peek) || peek == '_'); String name = builder.toString(); Word word = words.get(name); if (word != null) return word; word = new Word(name, Tag.ID); reserve(word); return word; } // something other Token t = new Token(peek); peek = ' '; return t; }
public Lexer(InputStream src) { this.source = src; words = new Hashtable<>(); // reserve key words reserve(new Word("for", Tag.FOR)); reserve(new Word("if", Tag.IF)); reserve(new Word("else", Tag.ELSE)); reserve(new Word("while", Tag.WHILE)); reserve(new Word("do", Tag.DO)); reserve(new Word("print", Tag.PRINT)); reserve(new Word("read", Tag.READ)); reserve(Word.True); reserve(Word.False); reserve(Type.Int); reserve(Type.Bool); reserve(Type.Float); }