-options {\r
- JDK_VERSION = "1.8";\r
- STATIC = false;\r
- IGNORE_CASE = false;\r
- UNICODE_INPUT = true;\r
- JAVA_UNICODE_ESCAPE = false;\r
-}\r
-\r
-PARSER_BEGIN(SheetFormulaParser)\r
-package org.simantics.spreadsheet.graph.parser;\r
-\r
-import org.simantics.spreadsheet.graph.parser.ast.*;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.Collections;\r
-\r
-/**\r
- * Parser for spreadsheet formulas\r
- * @author Antti Villberg\r
- */\r
-public class SheetFormulaParser { \r
-}\r
-PARSER_END(SheetFormulaParser)\r
-\r
-/*** Lexer *********************************************************/\r
-\r
-SKIP:\r
-{ <WHITESPACE: " " | "\n" | "\r" | "\t" > \r
-| <COMMENT1: "/*" (~["*"] | "*" ~["/"])* "*/" > \r
-| <COMMENT2: "//" (~["\n"])* >\r
-}\r
-\r
-TOKEN:\r
-{ ";" | "(" | ")" | "?" | "[" | "]"\r
-| "{" | "}" | "|" | "&" | "+" | "*" | "/" | "^" \r
-| "," | ".." | "." | "=" | "<" | ">" | "<>"\r
-| "true" | "false" | "null" | "TRUE" | "FALSE"\r
-| < #LETTER: [\r
- "\u0024", //DOLLAR SIGN: milreis, escudo\r
- "\u0041"-"\u005a", //LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z\r
- "\u005f", //LOW LINE: spacing underscore\r
- "\u0061"-"\u007a", //LATIN SMALL LETTER A - LATIN SMALL LETTER Z\r
- "\u00aa"-"\u00ad", // 00AA FEMININE ORDINAL INDICATOR: spanish\r
- // 00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK: left guillemet\r
- // 00AC NOT SIGN: angled dash\r
- // 00AD SOFT HYPHEN: discretionary hyphen\r
- "\u00b5"-"\u00b6", // 00B5 MICRO SIGN: greek small letter mu\r
- // 00B6 PILCROW SIGN: paragraph sign\r
- "\u00ba"-"\u00bb", // 00BA MASCULINE ORDINAL INDICATOR: spanish\r
- // 00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK : right guillemet \r
- "\u00c0"-"\u00d6", //LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS\r
- "\u00d8"-"\u00f6", //LATIN CAPITAL LETTER O WITH STROKE - LATIN SMALL LETTER O WITH DIAERESIS\r
- "\u00f8"-"\u00ff", //LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER Y WITH DIAERESIS\r
- "\u0100"-"\u1fff", //LATIN CAPITAL LETTER A WITH MACRON - GREEK DASIA:reversed comma\r
- "\u3040"-"\u318f", //Hiragana - Hangul\r
- "\u3300"-"\u337f", //Squared Katakana\r
- "\u3400"-"\u3d2d", //CJK Unified Ideographs Extension A\r
- "\u4e00"-"\u9fff", //CJK Unified Ideographs\r
- "\uf900"-"\ufaff", //CJK Compatibility Ideographs\r
- "\ufb00"-"\ufb06", //LATIN SMALL LIGATURE FF -LATIN SMALL LIGATURE ST\r
- "\ufb13"-"\ufb17", //ARMENIAN SMALL LIGATURE MEN NOW - ARMENIAN SMALL LIGATURE MEN XEH\r
- "\ufb1f"-"\ufb28", //HEBREW LIGATURE YIDDISH YOD YOD PATAH -HEBREW LETTER WIDE TAV\r
- "\ufb2a"-"\ufb36", //HEBREW LETTER SHIN WITH SHIN DOT - HEBREW LETTER ZAYIN WITH DAGESH\r
- "\ufb38"-"\ufb3e", //HEBREW LETTER TET WITH DAGESH - HEBREW LETTER MEM WITH DAGESH\r
- "\ufb40"-"\ufb41", //HEBREW LETTER NUN WITH DAGESH - HEBREW LETTER SAMEKH WITH DAGESH\r
- "\ufb43"-"\ufb44", //HEBREW LETTER FINAL PE WITH DAGESH - HEBREW LETTER PE WITH DAGESH\r
- "\ufb46"-"\ufb4f", //HEBREW LETTER TSADI WITH DAGESH - HEBREW LIGATURE ALEF LAMED\r
- "\ufb50"-"\ufdd7", //Arabic Presentation Forms(A) - ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM\r
- "\ufdf0"-"\ufdfd", //ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM -ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM\r
- "\ufe70"-"\ufefc", //Arabic Presentation Forms(B) - ARABIC LIGATURE LAM WITH ALEF FINAL FORM\r
- "\uff1f"-"\uff3a", //FULLWIDTH QUESTION MARK - FULLWIDTH LATIN CAPITAL LETTER Z\r
- "\uff3f"-"\uff5e", //FULLWIDTH LOW LINE - FULLWIDTH TILDE\r
- "\uff61"-"\uffbe", //Halfwidth CJK punctuation:HALFWIDTH IDEOGRAPHIC FULL STOP - HALFWIDTH HANGUL LETTER HIEUH\r
- "\uffc2"-"\uffc7", //HALFWIDTH HANGUL LETTER A - HALFWIDTH HANGUL LETTER E\r
- "\uffca"-"\uffcf", //HALFWIDTH HANGUL LETTER YEO - HALFWIDTH HANGUL LETTER OE\r
- "\uffd2"-"\uffd7", //HALFWIDTH HANGUL LETTER YO - HALFWIDTH HANGUL LETTER YU\r
- "\uffda"-"\uffdc" //HALFWIDTH HANGUL LETTER EU - HALFWIDTH HANGUL LETTER I\r
- ]\r
- >\r
-| <#ALPHANUM: < LETTER > | ["0"-"9"] >\r
-| <STRING: "\"" (~["\"", "\\", "\n"] | "\\" ~["\n"])* "\"">\r
- { matchedToken.image = SheetParserUtils.unescape(\r
- matchedToken.image.substring(1,matchedToken.image.length()-1)); }\r
-| <SHEET_NAME: "'" (~["'", "\\", "\n"] | "\\" ~["\n"])* "'">\r
- { matchedToken.image = SheetParserUtils.unescape(\r
- matchedToken.image.substring(1,matchedToken.image.length()-1)); }\r
-| <LONG_STRING: "\"\"\"" (~["\""] | "\"" ~["\""] | "\"\"" ~["\""])* "\"\"\"">\r
- { matchedToken.image = matchedToken.image.substring(3,matchedToken.image.length()-3); }\r
-| <CELL_SINGLE: (["$"]){0,1}(["A"-"Z"]){1,5}(["$"]){0,1}(["0"-"9"]){1,5} >\r
-| <#CELL_RANGE_PART: (["$"]){0,1}(["A"-"Z"]){1,5}(["$"]){0,1}(["0"-"9"]){0,5} >\r
-| <CELL_RANGE: <CELL_RANGE_PART> [":"] <CELL_RANGE_PART>> \r
-| <IDENT: < LETTER > (< ALPHANUM >)* >\r
-| <#POSITIVE_INTEGER: (["0"-"9"])+ >\r
-| <FLOAT: \r
- ( <POSITIVE_INTEGER> "." <POSITIVE_INTEGER> (["e","E"] <INTEGER>)?\r
- | "." <POSITIVE_INTEGER> (["e","E"] <INTEGER>)?\r
- | <POSITIVE_INTEGER> ["e","E"] <INTEGER>\r
- ) >\r
-| <INTEGER: <POSITIVE_INTEGER> >\r
-\r
-}\r
-\r
-AstValue primary() : {\r
- Token tok;\r
- AstValue temp;\r
- AstRange tempRange;\r
-} {\r
- "null" { return AstNull.NULL; }\r
- | "true" { return AstBoolean.TRUE; }\r
- | "false" { return AstBoolean.FALSE; }\r
- | "TRUE" { return AstBoolean.TRUE; }\r
- | "FALSE" { return AstBoolean.FALSE; }\r
- | <STRING> { return new AstString(token.image); }\r
- | <LONG_STRING> { return new AstString(token.image); }\r
- | <FLOAT> { return new AstDouble(token.image); }\r
- | <INTEGER> { return new AstInteger(Integer.parseInt(token.image)); }\r
- | LOOKAHEAD(2) (tok = <IDENT> | tok = <SHEET_NAME>) "!" tempRange = range() { return tempRange.inSheet(tok.image); }\r
- | LOOKAHEAD(2) temp = apply() { return temp; }\r | "(" temp = relation() ")" { return temp; }\r
- | temp = range() { return temp; }\r
- | temp = array() { return temp; }\r
- | <IDENT> { return new AstIdentifier(token.image); }\r
-}\r
-\r
-AstApply apply() : {\r AstArgList al;\r
- Token tok;\r
-} {\r
- LOOKAHEAD(3) tok = <IDENT> "(" ")" { return new AstApply(tok.image, null); } |\r
- tok = <IDENT> "(" al = arglist() ")" { return new AstApply(tok.image, al); }\r}\r
-\r
-AstValue array() : {\r
- AstArray arr = new AstArray();\r
- AstValue temp;\r
-} {\r
- LOOKAHEAD(2) "{" "}" { return new AstArray(); } |\r
- "{" temp = relation() { arr.add(temp); } "," ( temp = relation() { arr.add(temp); } )* "}" { return arr; }\r}\r
-\r
-AstRange range() : {\r
- Token temp1;\r
- Token temp2;\r
-} {\r
- LOOKAHEAD(2) <CELL_RANGE> { return new AstRange(token.image); }\r
- | <CELL_SINGLE> { return new AstRange(token.image); }\r
- | "#REF!" { return AstRange.REF; }\r
-}\r
-\r
-AstArgList arglist() : {\r
- AstArgList ret = new AstArgList();\r
- AstValue temp;\r
-} {\r
- temp = relation() { ret.add(temp); }\r ( (";"|",") { temp = AstNothing.INSTANCE; } (temp = relation())? { ret.add(temp); } )* { return ret; }\r
-}\r
-\r
-AstValue relation() : {\r
- AstRelation ret;\r
- String op;\r
- AstValue ex;\r
-} {\r
- ex = arithmetic_expression() { ret = new AstRelation(ex); } ( op = rel_op() ex = arithmetic_expression() { ret.setRight(op, ex); } )? { return ret.simplify(); }\r}\r
-\r
-String rel_op() : {\r
-} {\r
- "<" { return "< ";} | "<=" { return "<=";} | ">" { return " >";} | ">=" { return " >=";} | "=" { return "=";} | "<>" { return "<>";}\r
-}\r
-\r
-// \r
-AstValue arithmetic_expression() : {\r
- AstArithmeticExpression ret;\r
- String op = null;\r
- AstValue temp;\r
-} {\r
- (op = add_op())? temp = term() { ret = new AstArithmeticExpression(op, temp); } ( LOOKAHEAD(2) op = add_op() temp = term() { ret.add(op, temp); } )* { return ret.simplify(); }\r
-}\r
-\r
-String add_op() : {\r
-} {\r
- "+" { return "+";} | "-" { return "-";} | "&" { return "&";}\r
-}\r
-\r
-AstValue term() : {\r
- AstTerm ret;\r
- String op;\r
- AstValue temp;\r
-} {\r
- temp = factor() { ret = new AstTerm(temp); } (op = mul_op() temp = factor() { ret.add(op, temp); } )* { return ret.simplify(); }\r
-}\r
-\r
-\r
-String mul_op() : {\r
-} {\r
- "*" { return "*";} | "/" { return "/";} \r
-}\r
-\r
-AstValue factor() : {\r
- AstFactor ret;\r
- String op;\r
- AstValue temp;\r
-} {\r
- temp = primary() { ret = new AstFactor(temp); } (op = factor_op() temp = primary() { ret.add(op, temp); } )* { return ret.simplify(); }\r
-}\r
-\r
-String factor_op() : {\r
-} {\r
- "^" { return "^";}\r
-}\r
-\r