
cb.parser.Lexer Maven / Gradle / Ivy
/**
* Copyright (c) 2001 Markus Dahm
* Copyright (C) 2015-2018 BITPlan GmbH http://www.bitplan.com
*
* This source is part of
* https://github.com/BITPlan/CrazyBeans
* and the license as outlined there applies
*/
package cb.parser;
import java.io.*;
import java.util.*;
public class Lexer {
private PushbackReader _reader;
private int _line = 1;
public static final int LPAREN = 0;
public static final int RPAREN = 1;
public static final int IDENT = 2;
public static final int INTEGER = 3;
public static final int FLOAT = 4;
public static final int BOOLEAN = 5;
public static final int TAG = 6;
public static final int STRING = 7;
public static final int MULTI_STRING = 8;
public static final int COMMA = 9;
public static final int EOF = -1;
public Lexer(Reader r) {
_reader = new PushbackReader(new BufferedReader(r, 8192));
}
private void skipWS() throws IOException {
int ch;
while(Character.isWhitespace((char)(ch = _reader.read()))) {
if(ch == '\n') {
_line++;
}
}
_reader.unread(ch);
}
private StringBuffer buf = new StringBuffer();
public Token parseNumber() throws IOException {
int kind = INTEGER;
int ch = _reader.read();
buf.setLength(0);
if((ch == '+') || (ch == '-')) {
buf.append((char)ch);
ch = _reader.read();
}
while(Character.isDigit((char)ch) || (ch == '.')) {
if(ch == '.') {
if(kind == FLOAT)
throw new RuntimeException("Lexer Error: Found second . in float");
kind = FLOAT;
}
buf.append((char)ch);
ch = _reader.read();
}
_reader.unread(ch);
return Token.createToken(kind, buf.toString(), _line);
}
public Token parseString() throws IOException {
int ch = _reader.read();
buf.setLength(0);
buf.append('"');
ch = _reader.read();
while(ch != '"') {
if(ch == '\\') {
buf.append('\\');
ch = _reader.read();
buf.append((char)ch);
} else
buf.append((char)ch);
ch = _reader.read();
}
buf.append('"');
return Token.createToken(STRING, buf.toString(), _line);
}
public Token parseMultiString() throws IOException {
int ch = _reader.read();
buf.setLength(0);
while(ch == '|') {
buf.append('|');
while((ch = _reader.read()) != '\n') {
buf.append((char)ch);
}
buf.append('\n');
_line++;
ch = _reader.read();
}
_reader.unread(ch);
return Token.createToken(MULTI_STRING, buf.toString(), _line);
}
public Token parseIdent() throws IOException {
int ch = _reader.read();
buf.setLength(0);
while(Character.isJavaIdentifierPart((char)ch)) {
buf.append((char)ch);
ch = _reader.read();
}
_reader.unread(ch);
String img = buf.toString();
if(img.equals("TRUE"))
return Token.TRUE;
else if(img.equals("FALSE"))
return Token.FALSE;
else
return Token.createToken(IDENT, img, _line);
}
private Stack stack = new Stack();
public void ungetToken(Token t) {
stack.push(t);
}
public Token getToken() {
if(!stack.empty())
return (Token)stack.pop();
int kind;
String image;
try {
skipWS();
int ch = _reader.read();
switch(ch) {
case '(':
return Token.LPAREN;
case ')':
return Token.RPAREN;
case ',':
return Token.COMMA;
case '@':
Token t = parseNumber();
t.image = "@" + t.image;
t.kind = TAG;
return t;
case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9': case '-': case '+': case '.':
_reader.unread(ch);
return parseNumber();
case '"':
_reader.unread(ch);
return parseString();
case '|':
_reader.unread(ch);
return parseMultiString();
case 65535: // -1
return Token.EOF;
default:
if(Character.isJavaIdentifierStart((char)ch)) {
_reader.unread(ch);
return parseIdent();
} else
throw new RuntimeException("Lexer error: Unknown token: " + (char)ch +
"(" + ch + ")" + (ch < 0));
}
} catch(IOException e) {
throw new RuntimeException("Lexer error: " + e);
}
}
public int getLine() { return _line; }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy