Crossfire JXClient, Trunk
ExpressionParser.java
Go to the documentation of this file.
1 /*
2  * This file is part of JXClient, the Fullscreen Java Crossfire Client.
3  *
4  * JXClient is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * JXClient is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with JXClient; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  * Copyright (C) 2005-2008 Yann Chachkoff
19  * Copyright (C) 2006-2017,2019-2023 Andreas Kirschbaum
20  * Copyright (C) 2010-2012,2014-2018,2020-2023 Nicolas Weeger
21  */
22 
23 package com.realtime.crossfire.jxclient.skin.io;
24 
26 import java.io.IOException;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29 import org.jetbrains.annotations.NotNull;
30 
35 public class ExpressionParser {
36 
40  @NotNull
41  private static final Pattern PATTERN_EXPR = Pattern.compile("(.+?) *([+-]) *(.+)");
42 
46  @NotNull
47  private static final Pattern PATTERN_TERM1 = Pattern.compile("([0-9.]+) *[*] *([A-Z_]+)");
48 
52  @NotNull
53  private static final Pattern PATTERN_TERM2 = Pattern.compile("([A-Z_]+) *[*] *([0-9.]+)");
54 
58  private ExpressionParser() {
59  }
60 
68  public static int parseInt(@NotNull final String str) throws IOException {
69  return parseExpression(str).evaluateConstant();
70  }
71 
79  @NotNull
80  public static Expression parseExpression(@NotNull final String str) throws IOException {
81  Matcher matcherExpr = PATTERN_EXPR.matcher(str);
82  if (!matcherExpr.matches()) {
83  return parseTerm(str);
84  }
85 
86  Expression expr = parseTerm(matcherExpr.group(1));
87  while (true) {
88  final boolean negative;
89  switch (matcherExpr.group(2)) {
90  case "+":
91  negative = false;
92  break;
93 
94  case "-":
95  negative = true;
96  break;
97 
98  default:
99  throw new AssertionError("unrecognized operator: "+matcherExpr.group(2));
100  }
101 
102  final Matcher matcherExpr2 = PATTERN_EXPR.matcher(matcherExpr.group(3));
103  if (!matcherExpr2.matches()) {
104  return new Expression(expr, negative, parseTerm(matcherExpr.group(3)));
105  }
106 
107  matcherExpr = matcherExpr2;
108  expr = new Expression(expr, negative, parseTerm(matcherExpr.group(1)));
109  }
110  }
111 
118  @NotNull
119  private static Expression parseTerm(@NotNull final String str) throws IOException {
120  try {
121  return new Expression(Integer.parseInt(str), 0, 0, 0, 0);
122  } catch (final NumberFormatException ignored) {
123  }
124 
125  switch (str) {
126  case "WIDTH":
127  return new Expression(0, 1, 0, 0, 0);
128 
129  case "HEIGHT":
130  return new Expression(0, 0, 1, 0, 0);
131 
132  case "PREF_WIDTH":
133  return new Expression(0, 0, 0, 1, 0);
134 
135  case "PREF_HEIGHT":
136  return new Expression(0, 0, 0, 0, 1);
137 
138  case "WIDTH/2":
139  return new Expression(0, 0.5F, 0, 0, 0);
140 
141  case "HEIGHT/2":
142  return new Expression(0, 0, 0.5F, 0, 0);
143 
144  case "PREF_WIDTH/2":
145  return new Expression(0, 0, 0, 0.5F, 0);
146 
147  case "PREF_HEIGHT/2":
148  return new Expression(0, 0, 0, 0, 0.5F);
149  }
150 
151  final Matcher matcherTerm1 = PATTERN_TERM1.matcher(str);
152  if (matcherTerm1.matches()) {
153  return parseTerm(matcherTerm1.group(1), matcherTerm1.group(2));
154  }
155 
156  final Matcher matcherTerm2 = PATTERN_TERM2.matcher(str);
157  if (matcherTerm2.matches()) {
158  return parseTerm(matcherTerm2.group(2), matcherTerm2.group(1));
159  }
160 
161  throw new IOException("syntax error in '"+str+"'");
162  }
163 
172  @NotNull
173  private static Expression parseTerm(@NotNull final String factor, @NotNull final String constant) throws IOException {
174  final float factor2;
175  try {
176  factor2 = Float.parseFloat(factor);
177  } catch (final NumberFormatException ex) {
178  throw new IOException("invalid value '"+factor+"'", ex);
179  }
180 
181  switch (constant) {
182  case "WIDTH":
183  return new Expression(0, factor2, 0, 0, 0);
184 
185  case "HEIGHT":
186  return new Expression(0, 0, factor2, 0, 0);
187 
188  case "PREF_WIDTH":
189  return new Expression(0, 0, 0, factor2, 0);
190 
191  case "PREF_HEIGHT":
192  return new Expression(0, 0, 0, 0, factor2);
193  }
194 
195  throw new IOException("invalid constant '"+constant+"'");
196  }
197 
198 }
com.realtime.crossfire.jxclient
com.realtime.crossfire.jxclient.skin.io.ExpressionParser.PATTERN_TERM2
static final Pattern PATTERN_TERM2
Definition: ExpressionParser.java:53
com.realtime.crossfire.jxclient.skin.io.ExpressionParser.ExpressionParser
ExpressionParser()
Definition: ExpressionParser.java:58
com.realtime.crossfire.jxclient.skin.io.ExpressionParser.parseInt
static int parseInt(@NotNull final String str)
Definition: ExpressionParser.java:68
com.realtime.crossfire.jxclient.gui.gui.Expression.evaluateConstant
int evaluateConstant()
Definition: Expression.java:106
com.realtime.crossfire.jxclient.gui
com.realtime.crossfire.jxclient.skin.io.ExpressionParser.parseTerm
static Expression parseTerm(@NotNull final String factor, @NotNull final String constant)
Definition: ExpressionParser.java:173
com.realtime.crossfire.jxclient.skin.io.ExpressionParser.parseTerm
static Expression parseTerm(@NotNull final String str)
Definition: ExpressionParser.java:119
com.realtime.crossfire.jxclient.gui.gui
Definition: AbstractGUIElement.java:23
com.realtime.crossfire
com.realtime.crossfire.jxclient.skin.io.ExpressionParser
Definition: ExpressionParser.java:35
com.realtime
com.realtime.crossfire.jxclient.skin.io.ExpressionParser.PATTERN_EXPR
static final Pattern PATTERN_EXPR
Definition: ExpressionParser.java:41
com
com.realtime.crossfire.jxclient.skin.io.ExpressionParser.parseExpression
static Expression parseExpression(@NotNull final String str)
Definition: ExpressionParser.java:80
com.realtime.crossfire.jxclient.gui.gui.Expression
Definition: Expression.java:31
com.realtime.crossfire.jxclient.skin.io.ExpressionParser.PATTERN_TERM1
static final Pattern PATTERN_TERM1
Definition: ExpressionParser.java:47