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); } }