package org.uva.sea.ql.parser.jacc; import java.io.IOException; import java.io.Reader; import java.util.HashMap; import java.util.Map; import org.uva.sea.ql.ast.ASTNode; import org.uva.sea.ql.ast.expr.Ident; import org.uva.sea.ql.ast.expr.Int; public class QLLexer implements QLTokens { private static final Map<String, Integer> KEYWORDS; static { KEYWORDS = new HashMap<String, Integer>(); } private int token; private int c = ' '; private ASTNode yylval; private final Reader input; public QLLexer(Reader input) { this.input = input; nextChar(); } private void nextChar() { if (c >= 0) { try { c = input.read(); } catch (IOException e) { c = -1; } } } public int nextToken() { boolean inComment = false; for (;;) { if (inComment) { while (c != '*' && c != -1) { nextChar(); } if (c == '*') { nextChar(); if (c == '/') { nextChar(); inComment = false; } continue; } } while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { nextChar(); } if (c < 0) { return token = ENDINPUT; } switch (c) { case '/': { nextChar(); if (c == '*') { inComment = true; nextChar(); continue; } return token = '/'; } case ')': nextChar(); return token = ')'; case '(': nextChar(); return token = '('; case '*': { nextChar(); if (inComment && c == '/') { inComment = false; nextChar(); continue; } return token = '*'; } case '+': nextChar(); return token = '+'; case '-': nextChar(); return token = '-'; case '&': { nextChar(); if (c == '&') { nextChar(); return token = AND; } throw new RuntimeException("Unexpected character: " + (char)c); } case '|': { nextChar(); if (c == '|') { nextChar(); return token = OR; } throw new RuntimeException("Unexpected character: " + (char)c); } case '!': nextChar(); return token = '!'; case '<': { nextChar(); if (c == '=') { nextChar(); return token = LEQ; } return '<'; } case '=': { nextChar(); if (c == '=') { return token = EQ; } throw new RuntimeException("Unexpected character: " + (char)c); } case '>': { nextChar(); if (c == '=') { nextChar(); return token = GEQ; } return token = '>'; } default: { if (Character.isDigit(c)) { int n = 0; do { n = 10 * n + (c - '0'); nextChar(); } while (Character.isDigit(c)); yylval = new Int(n); return token = INT; } if (Character.isLetter(c)) { StringBuilder sb = new StringBuilder(); do { sb.append((char)c); nextChar(); } while (Character.isLetterOrDigit(c)); String name = sb.toString(); if (KEYWORDS.containsKey(name)) { return token = KEYWORDS.get(name); } yylval = new Ident(name); return token = IDENT; } throw new RuntimeException("Unexpected character: " + (char)c); } } } } public int getToken() { return token; } public ASTNode getSemantic() { return yylval; } }