diff --git a/src/com/annimon/everlastingsummer/ConfigParser.java b/src/com/annimon/everlastingsummer/ConfigParser.java new file mode 100644 index 0000000..3910c77 --- /dev/null +++ b/src/com/annimon/everlastingsummer/ConfigParser.java @@ -0,0 +1,135 @@ +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 tokens) { + return new ConfigParser(tokens); + } + + private final List tokens; + private final int tokensCount; + private int position; + private final Map values; + + private ConfigParser(List tokens) { + this.tokens = tokens; + tokensCount = tokens.size(); + position = 0; + values = new HashMap(); + } + + 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); + } +}