package de.neuland.jade4j.lexer;
import de.neuland.jade4j.lexer.token.AttributeList;
import java.util.Deque;
import java.util.LinkedList;
public class AttributeLexer {
public enum State {
KEY, KEY_CHAR, VALUE, EXPRESSION, ARRAY, STRING, OBJECT
}
/*
* len = str.length , colons = this.colons , states = ['key'] , key = '' ,
* val = '' , quote , c;
*/
private String key = "";
private String value = "";
private AttributeList token;
private Deque<State> states = new LinkedList<State>();
private char quote = ' ';
public AttributeLexer() {
states.add(State.KEY);
}
public AttributeList getToken(String input, int lineno) {
token = new AttributeList(lineno);
for (int i = 0; i < input.length(); i++) {
parse(input.charAt(i));
}
parse(',');
return token;
}
private State state() {
return states.getFirst();
}
private void parse(char c) {
char real = c;
switch (c) {
case ',':
case '\n':
switch (state()) {
case EXPRESSION:
case ARRAY:
case STRING:
case OBJECT:
value += c;
break;
default:
states.push(State.KEY);
value = value.trim();
key = key.trim();
if ("".equals(key)) {
return;
}
String name = key.replaceAll("^['\"]|['\"]$", "");
String cleanValue = value.replaceAll("^['\"]|['\"]$", "");
if ("".equals(cleanValue) && quote == ' ') {
token.addBooleanAttribute(name, Boolean.TRUE);
} else if (value.matches("^\"[^\"]*\"$") || value.matches("^'[^']*'$")) {
token.addAttribute(name, cleanValue, false);
} else {
token.addExpressionAttribute(name, value, false);
}
key = "";
value = "";
quote = ' ';
break;
}
break;
case '=':
parseAssign(real);
break;
case '(':
parseExpressionStart(c);
break;
case ')':
parseExpressionEnd(c);
break;
case '{':
parseObjectStart(c);
break;
case '}':
parseObjectEnd(c);
break;
case '[':
parseArrayStart(c);
break;
case ']':
parseArrayEnd(c);
break;
case '"':
case '\'':
parseQuotes(c);
break;
default:
parseDefaults(c);
break;
}
}
private void parseAssign(char real) {
switch (state()) {
case KEY_CHAR:
key += real;
break;
case VALUE:
case EXPRESSION:
case ARRAY:
case STRING:
case OBJECT:
value += real;
break;
default:
states.push(State.VALUE);
break;
}
}
private void parseExpressionStart(char c) {
if (state() == State.VALUE || state() == State.EXPRESSION) {
states.push(State.EXPRESSION);
}
value += c;
}
private void parseExpressionEnd(char c) {
if (state() == State.VALUE || state() == State.EXPRESSION) {
states.pop();
}
value += c;
}
private void parseObjectStart(char c) {
if (state() == State.VALUE) {
states.push(State.OBJECT);
}
value += c;
}
private void parseObjectEnd(char c) {
if (state() == State.OBJECT) {
states.pop();
}
value += c;
}
private void parseArrayStart(char c) {
if (state() == State.VALUE) {
states.push(State.ARRAY);
}
value += c;
}
private void parseArrayEnd(char c) {
if (state() == State.ARRAY) {
states.pop();
}
value += c;
}
private void parseQuotes(char c) {
switch (state()) {
case KEY:
states.push(State.KEY_CHAR);
break;
case KEY_CHAR:
states.pop();
break;
case STRING:
if (c == quote) {
states.pop();
}
value += c;
break;
default:
states.push(State.STRING);
value += c;
quote = c;
break;
}
}
private void parseDefaults(char c) {
switch (state()) {
case KEY:
case KEY_CHAR:
key += c;
break;
default:
value += c;
break;
}
}
}