home *** CD-ROM | disk | FTP | other *** search
Wrap
package allaire.util.template; import allaire.util.TypeConversionException; import allaire.util.TypelessValue; import netscape.util.Enumeration; import netscape.util.Hashtable; import netscape.util.Vector; public class ExpressionParser { protected TemplateRuntimeContext m_runtimeContext; private Hashtable m_functionLibs = new Hashtable(); private static FunctionLibrary m_libString = new StringFunctionLibrary(); private static FunctionLibrary m_libRuntime = new RuntimeFunctionLibrary(); public void removeAllFunctionLibraries() { this.m_functionLibs.clear(); } public String resolveExpression(String var1) throws ExpressionException { ExpressionLexer var2 = new ExpressionLexer(var1); try { TypelessValue var3 = this.expression(var2); if (var2.lookAhead().getType() != -1) { throw new ExpressionException(100, "Unexpected token '" + var2.lookAhead().getValue().asString() + "' found at the end of the expression."); } else { return var3.asString(); } } catch (ExpressionException var5) { ((TemplateException)var5).addDiagnostics("Expression: " + var1); throw var5; } } private TypelessValue comparison(ExpressionLexer var1) throws ExpressionException { TypelessValue var2 = this.additive(var1); while(true) { int var3 = var1.lookAhead().getType(); switch (var3) { case 1: case 2: case 3: case 4: case 5: case 6: var1.read(); TypelessValue var5 = this.additive(var1); int var4; try { var4 = var2.compareTo(var5); } catch (TypeConversionException var6) { throw new ExpressionException(105, "Illegal attempt to compare the values '" + var2.asString() + "' and '" + var5.asString() + "' (their types are incompatible)."); } boolean var7; switch (var3) { case 1: var7 = var4 < 0; break; case 2: var7 = var4 <= 0; break; case 3: var7 = var4 > 0; break; case 4: var7 = var4 >= 0; break; case 5: var7 = var4 == 0; break; case 6: var7 = var4 != 0; break; default: var7 = false; } var2 = new TypelessValue(var7); break; default: return var2; } } } private void arglist(String var1, ExpressionLexer var2, Vector var3) throws ExpressionException { for(int var4 = var2.lookAhead().getType(); var4 != 41 && var4 != -1; var4 = var2.lookAhead().getType()) { var3.addElement(this.expression(var2)); if (var2.lookAhead().getType() != 41) { if (var2.lookAhead().getType() != 44) { throw new ExpressionException(103, "Expected comma (,) was not found in call" + " to function '" + var1 + "'."); } var2.read(); } } } private TypelessValue logicalNOT(ExpressionLexer var1) throws ExpressionException { boolean var2 = false; while(var1.lookAhead().getType() == 9) { var2 = !var2; var1.read(); } TypelessValue var3 = this.comparison(var1); if (var2) { double var4 = this.convertToNumber(var3); boolean var6 = TypelessValue.numberToBoolean(var4); var3 = new TypelessValue(!var6); } return var3; } private TypelessValue logicalAND(ExpressionLexer var1) throws ExpressionException { TypelessValue var2; boolean var4; for(var2 = this.logicalNOT(var1); var1.lookAhead().getType() == 7; var2 = new TypelessValue(var4)) { var1.read(); TypelessValue var3 = this.logicalNOT(var1); try { var4 = var2.asBoolean() && var3.asBoolean(); } catch (TypeConversionException var5) { throw new ExpressionException(105, "Illegal attempt to convert the values '" + var2.asString() + "' and '" + var3.asString() + "' to boolean. One of " + "these values is not a valid boolean."); } } return var2; } protected TypelessValue callFunction(String var1, Vector var2) throws ExpressionException { Enumeration var3 = this.m_functionLibs.elements(); while(var3.hasMoreElements()) { FunctionLibrary var4 = (FunctionLibrary)var3.nextElement(); Function var5 = var4.lookupFunction(var1); if (var5 != null) { return var5.call(this.m_runtimeContext, var2); } } throw new ExpressionException(101, "The function named '" + var1 + "' was not found."); } public void removeFunctionLibrary(String var1) { this.m_functionLibs.remove(var1.toUpperCase()); } private TypelessValue expression(ExpressionLexer var1) throws ExpressionException { TypelessValue var2; String var3; for(var2 = this.logicalOR(var1); var1.lookAhead().getType() == 38; var2 = new TypelessValue(var3)) { var1.read(); var3 = var2.asString().concat(this.logicalOR(var1).asString()); } return var2; } public ExpressionParser(TemplateRuntimeContext var1) { this.m_runtimeContext = var1; this.addFunctionLibrary(m_libRuntime); this.addFunctionLibrary(m_libString); } private double convertToNumber(TypelessValue var1) throws ExpressionException { try { return var1.asReal(); } catch (TypeConversionException var2) { throw new ExpressionException(105, "Error attempting to convert the value '" + var1.asString() + "' to a number"); } } public void addFunctionLibrary(FunctionLibrary var1) { this.m_functionLibs.put(var1.getName().toUpperCase(), var1); } private TypelessValue primary(ExpressionLexer var1) throws ExpressionException { Token var2 = var1.lookAhead(); switch (var2.getType()) { case -1: throw new ExpressionException(102, "Expression is incomplete (check for unmatched parentheses)."); case 10: TypelessValue var3 = var1.read().getValue(); if (var1.lookAhead().getType() == 40) { var1.read(); Vector var9 = new Vector(); this.arglist(var3.asString(), var1, var9); if (var1.lookAhead().getType() != 41) { throw new ExpressionException(102, "Expected end parentheses ')' was not found for " + "function '" + var3.asString() + "'."); } var1.read(); return this.callFunction(var3.asString(), var9); } else { try { return new TypelessValue(this.m_runtimeContext.getSymbolTable().getStringRequired(var3.asString())); } catch (SymbolTableException var7) { throw new ExpressionException(((TemplateException)var7).getErrorNumber(), (String)((TemplateException)var7).getDiagnostics().firstElement()); } } case 11: StringBuffer var8 = new StringBuffer(); var8.append(var1.read().getValue().asString()); while(var1.lookAhead().getType() == 11) { Token var5 = var1.read(); var8.append(var5.getQuoteChar()); var8.append(var5.getValue().asString()); } return new TypelessValue(new String(var8)); case 12: return var1.read().getValue(); case 40: var1.read(); TypelessValue var4 = this.expression(var1); if (var1.lookAhead().getType() != 41) { throw new ExpressionException(102, "Expected end parentheses ')' was not found."); } var1.read(); return var4; case 43: var1.read(); return new TypelessValue(this.convertToNumber(this.primary(var1))); case 45: var1.read(); return new TypelessValue(-this.convertToNumber(this.primary(var1))); default: String var10 = String.valueOf((char)var2.getType()); throw new ExpressionException(100, "Unexpected token '" + var10 + "' found while parsing expression."); } } private TypelessValue logicalOR(ExpressionLexer var1) throws ExpressionException { TypelessValue var2; boolean var4; for(var2 = this.logicalAND(var1); var1.lookAhead().getType() == 8; var2 = new TypelessValue(var4)) { var1.read(); TypelessValue var3 = this.logicalAND(var1); try { var4 = var2.asBoolean() || var3.asBoolean(); } catch (TypeConversionException var5) { throw new ExpressionException(105, "Illegal attempt to convert the values '" + var2.asString() + "' and '" + var3.asString() + "' to boolean. One of " + "these values is not a valid boolean."); } } return var2; } private TypelessValue multiplicative(ExpressionLexer var1) throws ExpressionException { TypelessValue var2 = this.primary(var1); while(true) { switch (var1.lookAhead().getType()) { case 42: var1.read(); double var7 = this.convertToNumber(var2) * this.convertToNumber(this.primary(var1)); var2 = new TypelessValue(var7); break; case 43: case 44: case 45: case 46: default: return var2; case 47: var1.read(); double var3 = this.convertToNumber(this.primary(var1)); if (var3 == (double)0.0F) { throw new ExpressionException(104, "Attempted to divide '" + var2.asString() + "' by zero."); } double var5 = this.convertToNumber(var2) / var3; var2 = new TypelessValue(var5); } } } private TypelessValue additive(ExpressionLexer var1) throws ExpressionException { TypelessValue var2 = this.multiplicative(var1); while(true) { switch (var1.lookAhead().getType()) { case 43: var1.read(); double var5 = this.convertToNumber(var2) + this.convertToNumber(this.multiplicative(var1)); var2 = new TypelessValue(var5); break; case 44: default: return var2; case 45: var1.read(); double var3 = this.convertToNumber(var2) - this.convertToNumber(this.multiplicative(var1)); var2 = new TypelessValue(var3); } } } }