From: <nu...@us...> - 2010-09-11 15:14:28
|
Revision: 12985 http://pcgen.svn.sourceforge.net/pcgen/?rev=12985&view=rev Author: nuance Date: 2010-09-11 15:14:21 +0000 (Sat, 11 Sep 2010) Log Message: ----------- Rewrote Tom's formula parser for clarity and (hopefully) correctness. Actually I have added a new parser based on Tom's but since Tom told me that the base is for code that isn't PCGen specific and this parser is going to be PCGen specific, I've put it in core.formula.parse instead of base.formula.parse. Have added a visitor class that fixes the parsing of integers separated by dots (Used in the spellbook tokens). Where there is more than one integer in a dot separated block of text, the parser extracts pairs of them as floating point numbers. Since floating point numbrs are not legal at this point, rather than try to fix it in the parser, I scan the result and fix it after the fact. Modified Paths: -------------- sandbox/FormulaCompiler/build.xml sandbox/FormulaCompiler/test/pcgen/base/formula/FormulaTest.java Added Paths: ----------- sandbox/FormulaCompiler/src/pcgen/core/ sandbox/FormulaCompiler/src/pcgen/core/formula/ sandbox/FormulaCompiler/src/pcgen/core/formula/parse/ sandbox/FormulaCompiler/src/pcgen/core/formula/parse/FormulaDisplayer.java sandbox/FormulaCompiler/src/pcgen/core/formula/parse/NumberFixerVisitor.java sandbox/FormulaCompiler/src/pcgen/core/formula/parse/SimpleNode.java sandbox/FormulaCompiler/src/pcgen/core/formula/parse/formula.jjt sandbox/FormulaCompiler/test/pcgen/core/ sandbox/FormulaCompiler/test/pcgen/core/formula/ sandbox/FormulaCompiler/test/pcgen/core/formula/FormulaParseTest.java Modified: sandbox/FormulaCompiler/build.xml =================================================================== --- sandbox/FormulaCompiler/build.xml 2010-09-11 13:42:09 UTC (rev 12984) +++ sandbox/FormulaCompiler/build.xml 2010-09-11 15:14:21 UTC (rev 12985) @@ -1,12 +1,40 @@ -<project name="FormulaCompiler" default="compile" basedir="."> - <property name="lib.dir" value="lib" /> - <target name="tree-compile" description="Compile JavaCC Tree sources"> - <jjtree target="${basedir}/src/pcgen/base/formula/parse/formula.jjt" javacchome="${lib.dir}" outputdirectory="${basedir}/src/pcgen/base/formula/parse/" /> - </target> - <target name="compile-compile" depends="tree-compile" description="Compile JavaCC sources"> - <javacc target="${basedir}/src/pcgen/base/formula/parse/formula.jj" javacchome="${lib.dir}" /> - </target> - <target name="compile" depends="compile-compile" description="Compile Java sources"> - <javac srcdir="${basedir}" deprecation="true" includes="**/*.java;lib\asm-2.2.2.jar" debug="Yes" source="1.5" target="1.5" memoryInitialSize="128m" memoryMaximumSize="512m" fork="true" /> - </target> +<project name="FormulaCompiler" default="ncompile" basedir="."> + <property name="lib.dir" value="lib" /> + <target name="ntree-compile" description="Compile JavaCC Tree sources"> + <jjtree target="src/pcgen/core/formula/parse/formula.jjt" + javacchome="${lib.dir}" + outputdirectory="${basedir}/src/pcgen/core/formula/parse/" /> + </target> + <target name="ncompile-compile" depends="ntree-compile" description="Compile JavaCC sources"> + <javacc target="${basedir}/src/pcgen/core/formula/parse/formula.jj" + javacchome="${lib.dir}" /> + </target> + <target name="ncompile" depends="ncompile-compile" description="Compile Java sources"> + <javac srcdir="${basedir}" + deprecation="true" + includes="**/*.java;lib\asm-2.2.2.jar" + debug="Yes" + source="1.5" + target="1.5" + memoryInitialSize="128m" + memoryMaximumSize="512m" fork="true" /> + </target> + + <target name="tree-compile" description="Compile JavaCC Tree sources"> + <jjtree target="${basedir}/src/pcgen/base/formula/parse/formula.jjt" + javacchome="${lib.dir}" + outputdirectory="${basedir}/src/pcgen/base/formula/parse/" /> + </target> + <target name="compile-compile" depends="tree-compile" description="Compile JavaCC sources"> + <javacc target="${basedir}/src/pcgen/base/formula/parse/formula.jj" javacchome="${lib.dir}" /> + </target> + <target name="compile" depends="compile-compile" description="Compile Java sources"> + <javac srcdir="${basedir}" + deprecation="true" + includes="**/*.java;lib\asm-2.2.2.jar" + debug="Yes" source="1.5" + target="1.5" + memoryInitialSize="128m" + memoryMaximumSize="512m" fork="true" /> + </target> </project> Added: sandbox/FormulaCompiler/src/pcgen/core/formula/parse/FormulaDisplayer.java =================================================================== --- sandbox/FormulaCompiler/src/pcgen/core/formula/parse/FormulaDisplayer.java (rev 0) +++ sandbox/FormulaCompiler/src/pcgen/core/formula/parse/FormulaDisplayer.java 2010-09-11 15:14:21 UTC (rev 12985) @@ -0,0 +1,66 @@ +/* + * Copyright (c) Andrew Wilson, 2010. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ +package pcgen.core.formula.parse; + +import java.io.StringReader; + +/** + * @author Andrew Wilson + */ +public class FormulaDisplayer +{ + public FormulaDisplayer() + { + super(); + } + + public void display(String queryStr) + { + FormulaParser parser = new FormulaParser(new StringReader(queryStr)); + + SimpleNode root = null; + try + { + System.err.println("\nquery = " + queryStr); + root = parser.query(); + } + catch (ParseException e) + { + System.err.print(e.getMessage()); + System.err.println(); + } + catch (TokenMgrError tke) + { + System.err.print(tke.getMessage()); + System.err.println(); + } + + if (root == null) + { + System.err.println("argh: " + queryStr); + } + else + { + NumberFixerVisitor fix = new NumberFixerVisitor(); + fix.visit(root, null); + } + + // dump the result tree to the console for debug purposes + root.dump(""); + } +} \ No newline at end of file Added: sandbox/FormulaCompiler/src/pcgen/core/formula/parse/NumberFixerVisitor.java =================================================================== --- sandbox/FormulaCompiler/src/pcgen/core/formula/parse/NumberFixerVisitor.java (rev 0) +++ sandbox/FormulaCompiler/src/pcgen/core/formula/parse/NumberFixerVisitor.java 2010-09-11 15:14:21 UTC (rev 12985) @@ -0,0 +1,129 @@ +package pcgen.core.formula.parse; + +/** + * Created by IntelliJ IDEA. + * User: Andrew Wilson + * Date: 01-Aug-2010 + * + * + */ +public class NumberFixerVisitor implements FormulaParserVisitor { + + /* Should never be called */ + public Object visit(SimpleNode node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTRoot node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTLogical node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTEquality node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTRelational node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTArithmetic node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTGeometric node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTUnary node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTExpon node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTParen node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTNum node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTUser node, Object data) { + node.childrenAccept(this, data); + return null; + } + + /* This is the only one that actually does any work */ + public Object visit(ASTPCGenToken node, Object data) { + int last = node.jjtGetNumChildren(); + int inx1; + int inx2 = 0; + + Node[] newKids; + newKids = new Node[(last + 1) * 2]; + for (inx1 = 0; inx1 < last; inx1++) + { + SimpleNode k1 = (SimpleNode) node.jjtGetChild(inx1); + if (FormulaParserTreeConstants.JJTNUM == k1.getID() && + k1.getText().indexOf('.') > -1) { + ASTNum k2 = new ASTNum(FormulaParserTreeConstants.JJTNUM); + String image = k1.getText(); + String num1 = image.substring(0,image.indexOf('.')); + String num2 = image.substring(image.indexOf('.') + 1); + k1.setToken(num1); + k2.setToken(num2); + newKids[inx2++] = k1; + newKids[inx2++] = k2; + } else { + newKids[inx2++] = k1; + } + } + + inx2--; + + for (inx1 = inx2; inx1 > 0; inx1--) + { + node.jjtAddChild(newKids[inx1], inx1); + } + + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTVarString node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTBracket node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTFParen node, Object data) { + node.childrenAccept(this, data); + return null; + } + + public Object visit(ASTQuotString node, Object data) { + node.childrenAccept(this, data); + return null; + } +} Added: sandbox/FormulaCompiler/src/pcgen/core/formula/parse/SimpleNode.java =================================================================== --- sandbox/FormulaCompiler/src/pcgen/core/formula/parse/SimpleNode.java (rev 0) +++ sandbox/FormulaCompiler/src/pcgen/core/formula/parse/SimpleNode.java 2010-09-11 15:14:21 UTC (rev 12985) @@ -0,0 +1,145 @@ +/* Generated By:JJTree: Do not edit this line. SimpleNode.java */ + +package pcgen.core.formula.parse; + +public class SimpleNode implements Node { + protected Node parent; + protected Node[] children; + protected int id; + protected FormulaParser parser; + + public SimpleNode(int i) { + id = i; + } + + public SimpleNode(FormulaParser p, int i) { + this(i); + parser = p; + } + + public void jjtOpen() { + } + + public void jjtClose() { + } + + public void jjtSetParent(Node n) { parent = n; } + public Node jjtGetParent() { return parent; } + + public void jjtAddChild(Node n, int i) { + if (children == null) { + children = new Node[i + 1]; + } else if (i >= children.length) { + Node c[] = new Node[i + 1]; + System.arraycopy(children, 0, c, 0, children.length); + children = c; + } + children[i] = n; + } + + public Node jjtGetChild(int i) { + return children[i]; + } + + public int jjtGetNumChildren() { + return (children == null) ? 0 : children.length; + } + + public Object jjtAccept(FormulaParserVisitor visitor, Object data) { + return visitor.visit(this, data); + } + + public Object childrenAccept(FormulaParserVisitor visitor, Object data) { + if (children != null) { + for (Node aChildren : children) { + aChildren.jjtAccept(visitor, data); + } + } + return data; + } + + /* You can override these two methods in subclasses of SimpleNode to + customize the way the node appears when the tree is dumped. If + your output uses more than one line you should override + toString(String), otherwise overriding toString() is probably all + you need to do. */ + + public String toString() { + return FormulaParserTreeConstants.jjtNodeName[id]; + } + + public String toString(String prefix) { + StringBuilder sb = new StringBuilder(prefix ); + + sb.append(toString()); + if (operation != null) + { + sb.append(" ").append(operation); + } + + if (text != null) + { + sb.append(" ").append(text); + } + + return sb.toString(); + } + + /* Override this method if you want to customize how the node dumps + out its children. */ + + public void dump(String prefix) { + System.err.println(toString(prefix)); + if (children != null) { + for (Node aChildren : children) { + SimpleNode n = (SimpleNode) aChildren; + if (n != null) { + n.dump(prefix + " "); + } + } + } + } + + /* + * Copyright (c) Andrew Wilson, 2010. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + public String text; + + public String operation; + + public void setOperation(String op) { + operation = op; + } + + public void setToken(String s) { + text = s; + } + + public int getID() { + return id; + } + + public String getOperation() + { + return operation; + } + + public String getText() { + return text; + } +} \ No newline at end of file Copied: sandbox/FormulaCompiler/src/pcgen/core/formula/parse/formula.jjt (from rev 12697, sandbox/FormulaCompiler/src/pcgen/base/formula/parse/formula.jjt) =================================================================== --- sandbox/FormulaCompiler/src/pcgen/core/formula/parse/formula.jjt (rev 0) +++ sandbox/FormulaCompiler/src/pcgen/core/formula/parse/formula.jjt 2010-09-11 15:14:21 UTC (rev 12985) @@ -0,0 +1,344 @@ +/* + * Copyright (c) Andrew Wilson, 2010. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ +options { + STATIC=false; + VISITOR=true; + MULTI=true; +} +PARSER_BEGIN( FormulaParser ) +package pcgen.core.formula.parse; +import java.util.Map; +import pcgen.base.formula.core.FormulaOperation; + +public class FormulaParser { + + private static final String EQ_STRING = "=="; + private static final String NEQ_STRING = "!="; + private static final String LT_STRING = "<"; + private static final String GT_STRING = ">"; + private static final String LE_STRING = "<="; + private static final String GE_STRING = ">="; + private static final String ADD_STRING = "+"; + private static final String SUB_STRING = "-"; + private static final String MUL_STRING = "*"; + private static final String DIV_STRING = "/"; + private static final String AND_STRING = "&&"; + private static final String OR_STRING = "||"; + private static final String NEG_STRING = "-"; + private static final String EXP_STRING = "^"; + private static final String REM_STRING = "%"; + + private Map<Object, FormulaOperation> formulaMap; + + public void setFormulaMap(Map<Object, FormulaOperation> m) { + formulaMap = m; + } +} +PARSER_END( FormulaParser ) + +SimpleNode query() + #Root : {} { ( logicalExpr() )? <EOF> { return jjtThis; } } + +/****************************************************************************** + * Add Logical expression and function + *****************************************************************************/ +void logicalExpr() + #void : { String f = null; } + { equalityExpr() + ( f = logicalFtn() equalityExpr() #Logical(2) + { ((SimpleNode) jjtree.peekNode()).setOperation(f); } )* + } + +String logicalFtn() + #void : { String f; } + { ( f = orToken() | + f = andToken() ) + { return f; } } + +String orToken() + #void : {} { <OR> {return OR_STRING; } } + +String andToken() + #void : {} { <AND> {return AND_STRING; } } + +/****************************************************************************** + * Add Equality expression and functions + *****************************************************************************/ +void equalityExpr() + #void : {String f = null; } + { relationalExpr() + ( f = equalityFtn() relationalExpr() #Equality(2) + { ((SimpleNode) jjtree.peekNode()).setOperation(f); } )* + } + +String equalityFtn() + #void : { String f; } + { ( f = equalToken() | f = notEqualToken() ) { return f; } } + +String equalToken() + #void : {} { <EQUAL> { return EQ_STRING; } } + +String notEqualToken() + #void : {} { <NOTEQUAL> { return NEQ_STRING; } } + +/****************************************************************************** + * Add Relational expression and functions + *****************************************************************************/ +void relationalExpr() + #void : { String f = null; } + { arithmeticExpr() + ( f = relationalFtn() arithmeticExpr() #Relational(2) + { ((SimpleNode) jjtree.peekNode()).setOperation(f); } )* + } + +String relationalFtn() + #void : { String f; } + { ( f = lessThanToken() | + f = greaterThanToken() | + f = lessThanOrEqualToToken() | + f = greaterThanOrEqualToToken() ) + { return f; } + } + +String lessThanToken() + #void : {} { <LT> { return LT_STRING; } } + +String greaterThanToken() + #void : {} { <GT> { return GT_STRING; } } + +String lessThanOrEqualToToken() + #void : {} { <LTEQ> { return LE_STRING; } } + +String greaterThanOrEqualToToken() + #void : {} { <GTEQ> { return GE_STRING; } } + +/****************************************************************************** + * Add Arithmetic expression and function - addition and subtraction have + * equal precedence + *****************************************************************************/ +void arithmeticExpr() + #void : { String f = null; } + { geometricExpr() + ( f = arithmeticFtn() geometricExpr() #Arithmetic(2) + { ((SimpleNode) jjtree.peekNode()).setOperation(f); } )* + } + +String arithmeticFtn() + #void : { String f; } + { ( f = plusToken() | f = minusToken() ) { return f; } } + +String plusToken() + #void : {} { <PLUS> { return ADD_STRING; } } + +String minusToken() + #void : {} { <MINUS> { return SUB_STRING; } } + +/****************************************************************************** + * Add Geometric expression and functions - multiplication and both types of + * division have equal precedence + *****************************************************************************/ +void geometricExpr() + #void : { String f = null; } + { unaryExpr() + ( f = geometricFtn() unaryExpr() #Geometric(2) + { ((SimpleNode) jjtree.peekNode()).setOperation(f); } )* + } + +String geometricFtn() + #void : { String f; } + { ( f = multToken() | + f = divToken() | + f = remToken() ) + { return f; } } + +String multToken() #void : {} { <MULT> { return MUL_STRING; } } +String divToken() #void : {} { <DIV> { return DIV_STRING; } } +String remToken() #void : {} { <REM> { return REM_STRING; } } + +/****************************************************************************** + * Add Unary expression + *****************************************************************************/ +void unaryExpr() + #void : { Token t = null; } + { ( t=<MINUS> )? exponExpr() #Unary(t != null) + { + if (t != null) { + ((SimpleNode) jjtree.peekNode()).setOperation(NEG_STRING); + } + } + } + +/****************************************************************************** + * Add Exponential expression + *****************************************************************************/ +void exponExpr() + #Expon(>1) : {} + { primitiveExpr() ( <POW> primitiveExpr() )* + { jjtThis.setOperation(EXP_STRING); } } + + +/****************************************************************************** + * Now we're at the productions that will form the leaves of the tree + *****************************************************************************/ +void primitiveExpr() + #void : {} + { parenExpr() | + numberExpr() | + userExpr() } + +void parenExpr() + #Paren : {} + { <OPENPAREN> logicalExpr() <CLOSEPAREN> } + +void numberExpr() + #Num : { Token t1 = null, t2 = null, t3 = null; } + { + ( + (t1 = <INT> ( LOOKAHEAD(2) t2 = <FULLSTOP> t3 = <INT>)? ) | + (t1 = <FULLSTOP> t2 = <INT>) + ) + { + String image; + if (t3 == null) { + if (t2 == null) { + image = t1.image; + } else { + image = "." + t2.image; + } + } else { + image = t1.image + "." + t3.image; + } + jjtThis.setToken(image); + } + } + +/****************************************************************************** + * This is the start of the PCGEN specific stuff. The "Dot separated words" + * are used for our OS tokens and in some of our predefined variables. + *****************************************************************************/ +void userExpr() + #User(>1) : {} + { dotSeparatedWords() ( bracketGroup() | parenGroup() )? + } + +void dotSeparatedWords() + #PCGenToken(>1) : {} + { pcgenWord() + ( <FULLSTOP> ( numberExpr() | pcgenWord() ) ) * + } + +void pcgenWord() + #VarString : { Token t; Token i = null; } + { (i = <REM>)? t = <VARIABLE> + { String image; + if (i == null) { + image = t.image; + } else { + image = i.image + t.image; + } + jjtThis.setToken(image); } } + +void bracketGroup() + #Bracket : {} + { <OPENBRACKET> dotSeparatedWords() <CLOSEBRACKET> } + +void parenGroup() + #FParen : {} + { <OPENPAREN> functionExpr() ( <COMMA> functionExpr() )* <CLOSEPAREN> } + +void functionExpr() + #void : {} + { logicalExpr() | quotedString() } + +void quotedString() + #QuotString : { Token t; } + { t = <STRING_LITERAL> + { jjtThis.setToken(t.image); } } + + +/****************************************************************************** + * And now the tokens, some of these are general, some of them are PCGEN + * specific. + *****************************************************************************/ + +TOKEN : { < #PERCENT : "%" > } +TOKEN : { < #COLON : ":" > } +TOKEN : { < #HYPHEN : "-" > } +TOKEN : { < #SOLIDUS : "/" > } +TOKEN : { < #EQUALSIGN : "=" > } +TOKEN : { < #UNDERSCORE : "_" > } +TOKEN : { < #TILDE : "~" > } +TOKEN : { < #SPACE : " " > } + +TOKEN : { < #O_SPACE : ( <SPACE> )* > } + +TOKEN : { < PLUS : <O_SPACE> "+" <O_SPACE> > } +TOKEN : { < MINUS : <O_SPACE> <HYPHEN> <O_SPACE> > } +TOKEN : { < MULT : <O_SPACE> "*" <O_SPACE> > } +TOKEN : { < DIV : <O_SPACE> <SOLIDUS> <O_SPACE> > } +TOKEN : { < REM : <O_SPACE> <PERCENT> <O_SPACE> > } +TOKEN : { < POW : <O_SPACE> "^" <O_SPACE> > } +TOKEN : { < COMMA : <O_SPACE> "," <O_SPACE> > } +TOKEN : { < OPENPAREN : <O_SPACE> "(" <O_SPACE> > } +TOKEN : { < CLOSEPAREN : <O_SPACE> ")" <O_SPACE> > } +TOKEN : { < OPENBRACKET : <O_SPACE> "[" <O_SPACE> > } +TOKEN : { < CLOSEBRACKET : <O_SPACE> "]" <O_SPACE> > } +TOKEN : { < GT : <O_SPACE> ">" <O_SPACE> > } +TOKEN : { < LT : <O_SPACE> "<" <O_SPACE> > } +TOKEN : { < GTEQ : <O_SPACE> ">=" <O_SPACE> > } +TOKEN : { < LTEQ : <O_SPACE> "<=" <O_SPACE> > } +TOKEN : { < EQUAL : <O_SPACE> "==" <O_SPACE> > } +TOKEN : { < NOTEQUAL : <O_SPACE> "!=" <O_SPACE> > } +TOKEN : { < AND : <O_SPACE> "&&" <O_SPACE> > } +TOKEN : { < OR : <O_SPACE> "||" <O_SPACE> > } +TOKEN : { < FULLSTOP : "." > } + +TOKEN : { < #DIGIT : ["0" - "9"] > } + +TOKEN : { < #BASIC_LETTER : [ + "\u0041"-"\u005a", // Uppercase Latin + "\u0061"-"\u007a", // Lowercase Latin + "\u00c0"-"\u00d6", // Modified Latin (start) + "\u00d8"-"\u00f6", // Modified Latin (middle) + "\u00f8"-"\u00ff", // Modified Latin (end) + "\u0100"-"\u1fff", + "\u3040"-"\u318f", + "\u3300"-"\u337f", + "\u3400"-"\u3d2d", + "\u4e00"-"\u9fff", + "\uf900"-"\ufaff" +] > } + +TOKEN : { < #FINAL_LETTER : ( <TILDE> | + <DIGIT> | + <BASIC_LETTER> ) > } + +TOKEN : { < #MID_LETTER : ( <UNDERSCORE> | + <SPACE> | + <COLON> | + <EQUALSIGN> | + <FINAL_LETTER> ) > } + +TOKEN : { < VARIABLE : <BASIC_LETTER> ( ( <MID_LETTER> )* <FINAL_LETTER> )? > } + +TOKEN : { < INT : ( <DIGIT> )+ > } + +TOKEN : { < STRING_FORBIDDEN: (~["\"","\\","\n","\r"]) > } +TOKEN : { < STRING_ESCAPED: ("\\" ( ["n","t","b","r","f","\\","'","\""] ) ) > } +TOKEN : { < STRING_LITERAL: "\"" ( <STRING_FORBIDDEN> | <STRING_ESCAPED> )* "\"" > } + Modified: sandbox/FormulaCompiler/test/pcgen/base/formula/FormulaTest.java =================================================================== --- sandbox/FormulaCompiler/test/pcgen/base/formula/FormulaTest.java 2010-09-11 13:42:09 UTC (rev 12984) +++ sandbox/FormulaCompiler/test/pcgen/base/formula/FormulaTest.java 2010-09-11 15:14:21 UTC (rev 12985) @@ -272,7 +272,7 @@ return 0; } })); - f = pt.compile("a+3+b+2"); + f = pt.compile("a+ 3 + b +2"); System.err.println(f + "= " + f.resolve(new Reference() { public double getVariable(String s) { if ("a".equals(s)) { Added: sandbox/FormulaCompiler/test/pcgen/core/formula/FormulaParseTest.java =================================================================== --- sandbox/FormulaCompiler/test/pcgen/core/formula/FormulaParseTest.java (rev 0) +++ sandbox/FormulaCompiler/test/pcgen/core/formula/FormulaParseTest.java 2010-09-11 15:14:21 UTC (rev 12985) @@ -0,0 +1,128 @@ +/* + * Copyright (c) Thomas Parker, 2005-2009. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ +package pcgen.core.formula; + +import pcgen.core.formula.parse.FormulaDisplayer; + +/** + * @author Andrew Wilson + */ +public final class FormulaParseTest { + + private FormulaParseTest() { + //Can't instantiate Main class + } + + public static void main(String[] args) { + FormulaDisplayer pt = new FormulaDisplayer(); + + pt.display("1+3"); + pt.display("1+a"); + pt.display("min(4,3)"); + pt.display("5*min(4,3)"); + pt.display("2*(max(18,13.2)-11)"); + pt.display("5*min(4,3)/(2*(max(18,13.2)-11))"); + pt.display("5*min(4,3)/(2*(max(18,13.2)-11))+4*floor(2.2-6.1)"); + pt.display("5*floor(2.2-6.1)"); + pt.display("abs(1-4.2)"); + pt.display("ceil(abs(1-4.3))"); + pt.display("6%2.2"); + pt.display("6==2.2"); + pt.display("6!=2+4"); + pt.display("6^1"); + pt.display("6^2"); + pt.display("6^2^3"); + pt.display("6^(2+1)^2"); + pt.display("6!=2.2"); + pt.display("6==2+4"); + pt.display("2.2!=6"); + pt.display("2+4==6"); + pt.display("2+4==6==1"); + pt.display("2+4>=6"); + pt.display("2+4.1>6"); + pt.display("2+2.9>=6"); + pt.display("2+4<=6"); + pt.display("2+4.1<=6"); + pt.display("2+2.9<6"); + pt.display("round(5.4)"); + pt.display("max(5.4, 2.3, 6.7)"); + pt.display("if(3==1+2,4,(5*3)-1)"); + pt.display("if(3<=1+2,4,(5*3)-1)"); + pt.display("3>4"); + pt.display("(5*3)-1"); + pt.display("if(3,4,5)"); + pt.display("if(3>4,4,(5*3)-1)"); + pt.display("1==2==4"); + pt.display("1<=2>=4"); + pt.display("1<2!=4"); + pt.display("1+2+4"); + pt.display("1-2-4"); + pt.display("1*2*4"); + pt.display("1/2/4"); + pt.display("1%2%4"); + pt.display("1-2+4"); + pt.display("1+2-4"); + pt.display("min(1,2,4)"); + pt.display("max(1,2,4)"); + pt.display("1&&2||0"); + pt.display("1||2&&0"); + pt.display("1&&0||0"); + pt.display("1||0&&0"); + pt.display("(1||0)&&0"); + pt.display("0||0||1"); + pt.display("1&&2&&4"); + pt.display("1&&2&&var"); + pt.display("1&&var&&4"); + pt.display("1&&var&&0"); + pt.display("1||var||0"); + pt.display("1||2||var"); + pt.display("0||var||0"); + pt.display("max(1,2,var)"); + pt.display("max(1,var,4)"); + pt.display("7%2"); + pt.display("round(rnd)"); + pt.display("7%round(rnd)"); + pt.display("1+a+2+b"); + pt.display("a+ 3 + b +2"); + pt.display("a-2-3-b"); + pt.display("1-a-b-3"); + pt.display("string(\"blah\")"); + pt.display("FEAT.FOO.BAR"); + pt.display("6%user[rnd.rndx]"); + pt.display("2+CL=Park Attendant/3"); + pt.display("CL=Park Attendant/3+2"); + pt.display("COUNT[FEAT.FOO.BAR]"); + pt.display("COUNT[FEAT.%FOO.BAR]"); + pt.display("(min(max((CASTERLEVEL/3)+1,2),5))"); + + pt.display("-BASECOST"); + pt.display("BAB"); + pt.display("ceil((TL/2))"); + pt.display("min(25, 10+HD)"); + pt.display("CHA+(2*count(\"ABILITIES\",\"CATEGORY=Mutation\",\"NAME=Neural Mutation - Telepathy\"))"); + + pt.display("(50*%SPELLLEVEL*%CASTERLEVEL)"); + pt.display("Greater Weapon Focus(Longsword)"); + pt.display("COUNT[SPELLBOOK.0]"); + pt.display("COUNT[SPELLBOOK.0.1]"); + pt.display("COUNT[SPELLBOOK.0.1.2]"); + pt.display("COUNT[SPELLBOOK.0.1.2.3]"); + pt.display("HASDIETY:Toerag"); + pt.display("HASFEAT:Skill Focus (Craft(Basket Weaving))"); + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |