136 lines
3.6 KiB
Java
136 lines
3.6 KiB
Java
|
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);
|
||
|
}
|
||
|
}
|