00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package com.realtime.crossfire.jxclient.skin.io;
00023
00024 import com.realtime.crossfire.jxclient.gui.gui.Expression;
00025 import java.io.IOException;
00026 import java.util.regex.Matcher;
00027 import java.util.regex.Pattern;
00028 import org.jetbrains.annotations.NotNull;
00029
00034 public class ExpressionParser {
00035
00040 @NotNull
00041 private static final String WIDTH = "WIDTH";
00042
00047 @NotNull
00048 private static final String HEIGHT = "HEIGHT";
00049
00054 @NotNull
00055 private static final String PREF_WIDTH = "PREF_WIDTH";
00056
00061 @NotNull
00062 private static final String PREF_HEIGHT = "PREF_HEIGHT";
00063
00067 @NotNull
00068 private static final Pattern PATTERN_EXPR = Pattern.compile("([0-9]+|"+WIDTH+"|"+HEIGHT+"|"+WIDTH+"/2|"+HEIGHT+"/2|"+PREF_WIDTH+"|"+PREF_HEIGHT+"|"+PREF_WIDTH+"/2|"+PREF_HEIGHT+"/2)([-+])(.+)");
00069
00073 private ExpressionParser() {
00074 }
00075
00083 public static int parseInt(@NotNull final String str) throws IOException {
00084 return parseExpression(str).evaluateConstant();
00085 }
00086
00094 @NotNull
00095 public static Expression parseExpression(@NotNull final String str) throws IOException {
00096 try {
00097 return parseIntegerConstant(str);
00098 } catch (final NumberFormatException ignored) {
00099
00100 }
00101
00102 Matcher matcher = PATTERN_EXPR.matcher(str);
00103 if (!matcher.matches()) {
00104 throw new IOException("invalid number: "+str);
00105 }
00106 Expression value;
00107 try {
00108 value = parseIntegerConstant(matcher.group(1));
00109 while (true) {
00110 final boolean negative = matcher.group(2).equals("-");
00111 final String rest = matcher.group(3);
00112
00113 matcher = PATTERN_EXPR.matcher(rest);
00114 if (!matcher.matches()) {
00115 final Expression expressionRest = parseIntegerConstant(rest);
00116 value = new Expression(value, negative, expressionRest);
00117 break;
00118 }
00119
00120 final Expression valueRest = parseIntegerConstant(matcher.group(1));
00121 value = new Expression(value, negative, valueRest);
00122 }
00123 } catch (final NumberFormatException ex) {
00124 throw new IOException("invalid number: "+str, ex);
00125 }
00126
00127 return value;
00128 }
00129
00136 @NotNull
00137 private static Expression parseIntegerConstant(@NotNull final String str) {
00138 try {
00139 return new Expression(Integer.parseInt(str), 0, 0, 0, 0);
00140 } catch (final NumberFormatException ex) {
00141 if (str.equals(WIDTH)) {
00142 return new Expression(0, 2, 0, 0, 0);
00143 }
00144
00145 if (str.equals(HEIGHT)) {
00146 return new Expression(0, 0, 2, 0, 0);
00147 }
00148
00149 if (str.equals(WIDTH+"/2")) {
00150 return new Expression(0, 1, 0, 0, 0);
00151 }
00152
00153 if (str.equals(HEIGHT+"/2")) {
00154 return new Expression(0, 0, 1, 0, 0);
00155 }
00156
00157 if (str.equals(PREF_WIDTH)) {
00158 return new Expression(0, 0, 0, 2, 0);
00159 }
00160
00161 if (str.equals(PREF_HEIGHT)) {
00162 return new Expression(0, 0, 0, 0, 2);
00163 }
00164
00165 if (str.equals(PREF_WIDTH+"/2")) {
00166 return new Expression(0, 0, 0, 1, 0);
00167 }
00168
00169 if (str.equals(PREF_HEIGHT+"/2")) {
00170 return new Expression(0, 0, 0, 0, 1);
00171 }
00172
00173 throw ex;
00174 }
00175 }
00176
00177 }