options { TRACK_TOKENS=true; LOOKAHEAD=3; FORCE_LA_CHECK=true; } PARSER_BEGIN(MetaCADParser) package org.reprap.artofillusion.metacad.parser; import org.reprap.artofillusion.metacad.ParsedTree; import org.reprap.artofillusion.metacad.language.*; import java.io.StringReader; import java.util.ArrayList; import java.util.List; /** Simple brace matcher. */ public class MetaCADParser { protected static MetaCADParser theParser = null; public static MetaCADParser getSingleton(String txt) { if (theParser== null) { theParser=new MetaCADParser(new StringReader(txt)); } else { theParser.ReInit(new StringReader(txt)); } return theParser; } public static ParsedTree parseTree(String txt) throws ParseException { MetaCADParser parser = getSingleton(txt); return parser.ParsedTree(); } public static List parseParameters(String txt) throws ParseException { try { MetaCADParser parser = getSingleton(txt); return parser.ParsedStatementList(); } catch (Throwable ex) { ParseException newEx = new ParseException(ex.getMessage() + " in:\n" + txt); newEx.initCause(ex); throw newEx; } } public static String dumpTokens(SimpleNode node) { Token first = node.jjtGetFirstToken(); Token last = node.jjtGetLastToken(); String s=first.image; while (first != last) { first = first.next; s = s + first.image; } return s; } } PARSER_END(MetaCADParser) SKIP : /* WHITE SPACE */ { " " | "\t" | "\n" | "\r" | "\f" } SPECIAL_TOKEN : /* COMMENTS */ { | | } TOKEN : { < LPAREN: "(" > | < RPAREN: ")" > | < LBRACE: "{" > | < RBRACE: "}" > | < COMMA: "," > | < DOT: "." > } TOKEN : { )?)? > | <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+> | < STRING_LITERAL: "\"" ( (~["\"","\\","\n","\r"]) | ("\\" ( ["n","t","b","r","f","\\","'","\""] | ["0"-"7"] ( ["0"-"7"] )? | ["0"-"3"] ["0"-"7"] ["0"-"7"] ) ) )* "\"" > } TOKEN : /* BINARY OPS */ { < PLUS: "+" > | < MINUS: "-" > | < DIVIDE: "/" > | < ASSIGN: "=" > | < LTE: "<=" > | < GTE: ">=" > | < EQUALS: "=="> | < NEQUALS: "!="> | < OTHERBINOP: ["*","^", "<", ">", "?", ":", "."] > } TOKEN : /* IDENTIFIERS */ { (|)*> | < #LETTER: [ "\u0024", "\u0041"-"\u005a", "\u005f", "\u0061"-"\u007a"/*, "\u00c0"-"\u00d6", "\u00d8"-"\u00f6", "\u00f8"-"\u00ff", "\u0100"-"\u1fff", "\u3040"-"\u318f", "\u3300"-"\u337f", "\u3400"-"\u3d2d", "\u4e00"-"\u9fff", "\uf900"-"\ufaff"*/ ] > | < #DIGIT: [ "\u0030"-"\u0039"/*, "\u0660"-"\u0669", "\u06f0"-"\u06f9", "\u0966"-"\u096f", "\u09e6"-"\u09ef", "\u0a66"-"\u0a6f", "\u0ae6"-"\u0aef", "\u0b66"-"\u0b6f", "\u0be7"-"\u0bef", "\u0c66"-"\u0c6f", "\u0ce6"-"\u0cef", "\u0d66"-"\u0d6f", "\u0e50"-"\u0e59", "\u0ed0"-"\u0ed9", "\u1040"-"\u1049"*/ ] > } ParsedTree ParsedTree() : { ParsedTree tree; List children=null; } { tree = FunctionCallList() (children=ParsedTreeList() (";")? | ";") { if (children != null) { ParsedTree bottom = tree; while (bottom.children.size() != 0) { bottom = bottom.children.get(0); }; bottom.children = children; } return tree; } } List ParsedTreeList() : { List list = new ArrayList(); ParsedTree current; } { (current = ParsedTree() { list.add(current); })* { return list; } } ParsedTree FunctionCallList() : { ParsedTree current = null; List trees = new ArrayList(); } { (current = FunctionCall() {trees.add(current);})+ { for (int i = 0; i < trees.size()-1; i++) { trees.get(i).children.add(trees.get(i+1)); } return trees.get(0); } } ParsedTree FunctionCall() : { ParsedTree tree; Token name, nameToken; List params = new ArrayList(); } { name = ((params = ParameterList())?)? { tree = new ParsedTree(); tree.name = name.image; tree.parameters = params; return tree; } | (nameToken=|nameToken=|nameToken=)name= ((params = ParameterList())?)? { String n = nameToken.image+name.image; tree = new ParsedTree(); tree.name = n; tree.parameters = params; return tree; } } List ParameterList() : { List expressions = new ArrayList(); String current; } { current = Expression(){expressions.add(current);}(current=Expression(){expressions.add(current);})* { return expressions; } } void JEPFunctionCall() : { } { ((ParameterList())?)? } /** Brace counting production. */ void UnaryExpression() : { } { | JEPFunctionCall() | Expression() | UnaryExpression() | } /** Brace counting production. */ String Expression() : { } { UnaryExpression()((||||||||)UnaryExpression())* { return dumpTokens(jjtThis); } } VariableAssignment LocalVariableAssignment() : { String name; String formula; Token temp; } { temp={name=temp.image;} formula=Expression() { return new VariableAssignment(name, formula); } ";" } VariableAssignment VariableAssignment() : { String name; String formula; Token temp; } { temp={name=temp.image;} formula=Expression() { return new VariableAssignment(name, formula); } } MacroPrototype MacroPrototype() : { Token temp; String name; List list = new ArrayList(); List children; } { temp={name=temp.image;} (temp = { list.add(temp.image); } ( temp = { list.add(temp.image); })*)? children=ParsedTreeList() { return new MacroPrototype(name, list, children); } } List ParsedStatementList() : { List statements = new ArrayList(); ParsedStatement temp; } { ( temp=MacroPrototype() {statements.add(temp);} | temp=VariableAssignment() {statements.add(temp);} )* { return statements; } }