1313import java .util .regex .Matcher ;
1414import java .util .regex .Pattern ;
1515
16- public record BooleanExpressionEvaluator (String expression , List <Token > tokens , Stack <Boolean > values , Stack <Operator > operators ) {
16+ public record BooleanExpressionEvaluator (String expression , List <Token > tokens , Stack <Boolean > values , Stack <Operator > operators , TokenProcessor processor ) {
1717 public static final LoadingCache <String , BooleanExpressionEvaluator > EXPRESSION_CACHE = CacheBuilder .newBuilder ().expireAfterWrite (Duration .ofMinutes (15 )).build (CacheLoader .from (BooleanExpressionEvaluator ::create ));
1818
1919 private static final Pattern TOKEN_PATTERN = Pattern .compile ("(\\ $\\ {[\\ dA-Za-z_.-]+})|(:?(?:false|true))|(:?\\ d+\\ .?\\ d*)|(!|&&|&|\\ |\\ ||\\ |)|(==|!=|>=|<=|>|<)" );
2020
2121 public BooleanExpressionEvaluator (String expression , List <Token > tokens ){
22- this (expression , tokens , new Stack <>(), new Stack <>());
22+ this (expression , tokens , new Stack <>(), new Stack <>(), new TokenProcessor () );
2323 }
2424
2525 public static BooleanExpressionEvaluator create (String expression ) {
@@ -35,8 +35,8 @@ public Boolean evaluate(VariableResolver variableResolver) {
3535 values .clear ();
3636 operators .clear ();
3737 try {
38- for (Token token : tokens ) {
39- token .process (this , variableResolver );
38+ for (int i = 0 ; i < tokens . size (); i ++ ) {
39+ processor .process (i , this , variableResolver );
4040 }
4141
4242 while (!operators .isEmpty ()) {
@@ -75,67 +75,90 @@ public static List<Token> tokenize(String expression) {
7575 }
7676
7777 public interface Token {
78- void process (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver );
79- default Token relativeToken (BooleanExpressionEvaluator evaluator , int ordinal ){
80- int tokenIndex = evaluator .tokens .indexOf (this ) + ordinal ;
81- return tokenIndex < evaluator .tokens .size () && tokenIndex >= 0 ? null : evaluator .tokens .get (tokenIndex );
78+ void process (TokenProcessor processor );
79+ }
80+
81+ public static class TokenProcessor {
82+ private BooleanExpressionEvaluator evaluator ;
83+ private int index ;
84+ private VariableResolver resolver ;
85+
86+ public Token relative (int offset ){
87+ int relative = index + offset ;
88+ return relative < evaluator .tokens .size () && relative >= 0 ? evaluator .tokens .get (relative ) : null ;
89+ }
90+
91+ public void process (int index , BooleanExpressionEvaluator evaluator , VariableResolver resolver ){
92+ this .index = index ;
93+ this .evaluator = evaluator ;
94+ this .resolver = resolver ;
95+ evaluator .tokens .get (index ).process (this );
96+ }
97+
98+ public BooleanExpressionEvaluator evaluator (){
99+ return evaluator ;
100+ }
101+
102+ public VariableResolver resolver () {
103+ return resolver ;
82104 }
83105 }
84106
85107 public record Variable (String name ) implements NumberLikeValue , BooleanLikeValue {
86108 @ Override
87- public Number numberValue (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
88- return variableResolver . getNumber (name , relativeToken ( evaluator , 1 ) instanceof NumberLikeValue value ? value .numberValue (evaluator , variableResolver ) : null );
109+ public Number numberValue (TokenProcessor processor ) {
110+ return processor . resolver (). getNumber (name , processor . relative ( 1 ) instanceof NumberLikeValue value ? value .numberValue (processor ) : null );
89111 }
90112
91113 @ Override
92- public Boolean booleanValue (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
93- return variableResolver . getBoolean (name , relativeToken ( evaluator , 1 ) instanceof BooleanLikeValue value ? value .booleanValue (evaluator , variableResolver ) : null );
114+ public Boolean booleanValue (TokenProcessor processor ) {
115+ return processor . resolver (). getBoolean (name , processor . relative ( 1 ) instanceof BooleanLikeValue value ? value .booleanValue (processor ) : null );
94116 }
95117
96118 @ Override
97- public void process (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
98- if (numberValue (evaluator , variableResolver ) != null ) return ;
99- BooleanLikeValue .super .process (evaluator , variableResolver );
119+ public void process (TokenProcessor processor ) {
120+ if (numberValue (processor ) != null ) return ;
121+ BooleanLikeValue .super .process (processor );
100122 }
101123 }
102124
103125 public record BooleanValue (boolean value ) implements BooleanLikeValue {
104126 @ Override
105- public Boolean booleanValue (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
127+ public Boolean booleanValue (TokenProcessor processor ) {
106128 return value ;
107129 }
108130
109131 @ Override
110- public void process (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
111- if (relativeToken ( evaluator , -1 ) instanceof Variable v && v .booleanValue (evaluator , variableResolver ) != null ) return ;
112- BooleanLikeValue .super .process (evaluator , variableResolver );
132+ public void process (TokenProcessor processor ) {
133+ if (processor . relative ( -1 ) instanceof Variable v && v .booleanValue (processor ) != null ) return ;
134+ BooleanLikeValue .super .process (processor );
113135 }
114136 }
115137
116138 public interface BooleanLikeValue extends Token {
117- Boolean booleanValue (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver );
118- default void process (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
139+ Boolean booleanValue (TokenProcessor processor );
140+
141+ default void process (TokenProcessor processor ) {
119142 Boolean variable ;
120- if ((variable = booleanValue (evaluator , variableResolver )) == null ) return ;
121- if (!evaluator .operators .isEmpty () && evaluator .operators .peek ().symbol ().equals ("!" )) {
143+ if ((variable = booleanValue (processor )) == null ) return ;
144+ if (!processor . evaluator () .operators .isEmpty () && processor . evaluator () .operators .peek ().symbol ().equals ("!" )) {
122145 variable = !variable ;
123- evaluator .operators .pop ();
146+ processor . evaluator () .operators .pop ();
124147 }
125- evaluator .values .push (variable );
148+ processor . evaluator () .values .push (variable );
126149 }
127150 }
128151
129152 public interface NumberLikeValue extends Token {
130- Number numberValue (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver );
153+ Number numberValue (TokenProcessor processor );
131154 @ Override
132- default void process (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
155+ default void process (TokenProcessor processor ) {
133156 }
134157 }
135158
136159 public record NumberValue (Number value ) implements NumberLikeValue {
137160 @ Override
138- public Number numberValue (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
161+ public Number numberValue (TokenProcessor processor ) {
139162 return value ();
140163 }
141164 }
@@ -154,9 +177,8 @@ public boolean applyEquality(double b, double a) {
154177 }
155178
156179 @ Override
157- public void process (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
158- int tokenIndex = evaluator .tokens ().indexOf (this );
159- if (tokenIndex > 0 && tokenIndex < evaluator .tokens ().size () - 1 && evaluator .tokens ().get (tokenIndex - 1 ) instanceof NumberLikeValue n && evaluator .tokens ().get (tokenIndex + 1 ) instanceof NumberLikeValue n1 ) evaluator .values .push (applyEquality (n1 .numberValue (evaluator , variableResolver ).doubleValue (), n .numberValue (evaluator , variableResolver ).doubleValue ()));
180+ public void process (TokenProcessor processor ) {
181+ if (processor .relative (-1 ) instanceof NumberLikeValue n && processor .relative (1 ) instanceof NumberLikeValue n1 ) processor .evaluator ().values .push (applyEquality (n1 .numberValue (processor ).doubleValue (), n .numberValue (processor ).doubleValue ()));
160182 }
161183 }
162184
@@ -173,23 +195,23 @@ public boolean operate(boolean b, boolean a) {
173195 }
174196
175197 @ Override
176- public void process (BooleanExpressionEvaluator evaluator , VariableResolver variableResolver ) {
198+ public void process (TokenProcessor processor ) {
177199 if (!symbol ().equals ("(" ) && !symbol ().equals (")" )){
178- while (!evaluator .operators .isEmpty ()) {
179- evaluator .values .push (evaluator .operators .pop ().operate (evaluator .values .pop (), evaluator .values .pop ()));
200+ while (!processor . evaluator () .operators .isEmpty ()) {
201+ processor . evaluator () .values .push (processor . evaluator () .operators .pop ().operate (processor . evaluator () .values .pop (), processor . evaluator () .values .pop ()));
180202 }
181203 } else if (symbol ().equals (")" )){
182- while (evaluator .operators .peek ().symbol ().equals ("(" )) {
183- evaluator .values .push (evaluator .operators .pop ().operate (evaluator .values .pop (), evaluator .values .pop ()));
204+ while (processor . evaluator () .operators .peek ().symbol ().equals ("(" )) {
205+ processor . evaluator () .values .push (processor . evaluator () .operators .pop ().operate (processor . evaluator () .values .pop (), processor . evaluator () .values .pop ()));
184206 }
185- evaluator .operators .pop ();
186- if ("!" .equals (evaluator .operators .peek ().symbol ())) {
187- evaluator .values .push (!evaluator .values .pop ());
188- evaluator .operators .pop ();
207+ processor . evaluator () .operators .pop ();
208+ if ("!" .equals (processor . evaluator () .operators .peek ().symbol ())) {
209+ processor . evaluator () .values .push (!processor . evaluator () .values .pop ());
210+ processor . evaluator () .operators .pop ();
189211 }
190212 return ;
191213 }
192- evaluator .operators .push (this );
214+ processor . evaluator () .operators .push (this );
193215 }
194216 }
195217}
0 commit comments