RpyPlayer/src/com/annimon/everlastingsummer/ConfigParser.java

136 lines
3.6 KiB
Java
Raw Normal View History

package com.annimon.everlastingsummer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author aNNiMON
*/
public final class ConfigParser {
private static final Token EOF = new Token("", TokenType.EOF);
public static ConfigParser parse(List<Token> tokens) {
return new ConfigParser(tokens);
}
private final List<Token> tokens;
private final int tokensCount;
private int position;
private final Map<String, String> values;
private ConfigParser(List<Token> tokens) {
this.tokens = tokens;
tokensCount = tokens.size();
position = 0;
values = new HashMap<String, String>();
}
public void addValue(String key, String value) {
values.put(key, value);
}
public boolean isValueExists(String key) {
return values.containsKey(key);
}
public String getValue(String key) {
if (!isValueExists(key)) return "";
return values.get(key);
}
public double getValueAsDouble(String key) {
if (!isValueExists(key)) return 0;
return Double.parseDouble(values.get(key));
}
public boolean getValueAsBoolean(String key) {
if (!isValueExists(key)) return false;
return "true".equalsIgnoreCase(values.get(key));
}
public void parse() {
while (!match(TokenType.EOF)) {
match(TokenType.COMMAND);
if (lookMatch(0, TokenType.WORD)) {
final String name = consume(TokenType.WORD).getText();
if (match(TokenType.EQ)) {
// variable = expression
addValue(name, expression());
}
if (lookMatch(1, TokenType.EQ) && match(TokenType.PLUS)) {
// variable += expression
consume(TokenType.EQ);
addValue(name, getValue(name) + expression());
}
} else {
position++;
}
}
tokens.clear();
}
private String expression() {
return additive();
}
private String additive() {
String expression = unary();
while (true) {
if (match(TokenType.PLUS)) {
expression += unary();
continue;
}
break;
}
return expression;
}
private String unary() {
match(TokenType.PLUS);
return primary();
}
private String primary() {
final Token current = get(0);
if (match(TokenType.TEXT) || match(TokenType.NUMBER)) {
return current.getText();
}
if (match(TokenType.WORD)) {
return getValue(current.getText());
}
if (match(TokenType.LPAREN)) {
String expr = expression();
match(TokenType.RPAREN);
return expr;
}
return current.getText();
}
private boolean match(TokenType type) {
if (get(0).getType() != type) return false;
position++;
return true;
}
private Token consume(TokenType type) {
if (get(0).getType() != type) throw new RuntimeException("Ожидался токен " + type + ".");
return tokens.get(position++);
}
private boolean lookMatch(int pos, TokenType type) {
return (type == get(pos).getType());
}
private Token get(int offset) {
if (position + offset >= tokensCount) return EOF;
return tokens.get(position + offset);
}
}