using System; using System.Collections.Generic; using System.Text.RegularExpressions; namespace CPF.ReoGrid.Formula { internal static class Parser { public static STNode Parse(IWorkbook workbook, Cell cell, string input) { ExcelFormulaLexer excelFormulaLexer = new ExcelFormulaLexer(workbook, cell, input); STNode result = Parser.ReadExpr(excelFormulaLexer); bool flag = excelFormulaLexer.CurrentToken != null && excelFormulaLexer.CurrentToken.Success; if (flag) { throw Parser.CreateException(excelFormulaLexer, "unexpect token: " + excelFormulaLexer.CurrentToken.Value); } return result; } private static STNode ReadExpr(ExcelFormulaLexer lexer) { return Parser.ReadCompare(lexer); } private static STNode ReadCompare(ExcelFormulaLexer lexer) { STNode stnode = Parser.ReadConnect(lexer); bool flag = stnode == null; STNode result; if (flag) { result = null; } else { bool flag2 = lexer.IsToken("=") || lexer.IsToken("=="); STNodeType type; if (flag2) { type = STNodeType.EQUALS; } else { bool flag3 = lexer.IsToken("<>") || lexer.IsToken("!="); if (flag3) { type = STNodeType.NOT_EQUALS; } else { bool flag4 = lexer.IsToken(">"); if (flag4) { type = STNodeType.GREAT_THAN; } else { bool flag5 = lexer.IsToken("<"); if (flag5) { type = STNodeType.LESS_THAN; } else { bool flag6 = lexer.IsToken(">="); if (flag6) { type = STNodeType.GREAT_EQUALS; } else { bool flag7 = lexer.IsToken("<="); if (!flag7) { return stnode; } type = STNodeType.LESS_EQUALS; } } } } } lexer.NextToken(); STNode stnode2 = Parser.ReadExpr(lexer); bool flag8 = stnode2 == null; if (flag8) { throw Parser.CreateException(lexer, "expect expression"); } stnode = Parser.CreateNode(lexer, type, stnode.Start, lexer.CommittedLength - stnode.Start, new List { stnode, stnode2 }); result = stnode; } return result; } internal static STNode ParseInterCompareExp(Cell cell, string input) { ExcelFormulaLexer excelFormulaLexer = new ExcelFormulaLexer((cell.Worksheet == null) ? null : cell.Worksheet.workbook, cell, input); STNodeType stnodeType = STNodeType.NONE; bool flag = excelFormulaLexer.IsToken("=") || excelFormulaLexer.IsToken("=="); if (flag) { stnodeType = STNodeType.EQUALS; } else { bool flag2 = excelFormulaLexer.IsToken("<>") || excelFormulaLexer.IsToken("!="); if (flag2) { stnodeType = STNodeType.NOT_EQUALS; } else { bool flag3 = excelFormulaLexer.IsToken(">"); if (flag3) { stnodeType = STNodeType.GREAT_THAN; } else { bool flag4 = excelFormulaLexer.IsToken("<"); if (flag4) { stnodeType = STNodeType.LESS_THAN; } else { bool flag5 = excelFormulaLexer.IsToken(">="); if (flag5) { stnodeType = STNodeType.GREAT_EQUALS; } else { bool flag6 = excelFormulaLexer.IsToken("<="); if (flag6) { stnodeType = STNodeType.LESS_EQUALS; } } } } } } bool flag7 = stnodeType > STNodeType.NONE; if (flag7) { excelFormulaLexer.NextToken(); STNode stnode = Parser.ReadExpr(excelFormulaLexer); bool flag8 = stnode != null; if (flag8) { return Parser.CreateNode(excelFormulaLexer, stnodeType, 0, excelFormulaLexer.CommittedLength, new List { null, stnode }); } } STNode stnode2 = Parser.ReadConnect(excelFormulaLexer); return new STNode(STNodeType.EQUALS, 0, input.Length, new List { null, (stnode2 != null && stnode2.Type != STNodeType.IDENTIFIER) ? stnode2 : new STStringNode(input, 0, input.Length) }); } private static STNode ReadConnect(ExcelFormulaLexer lexer) { STNode stnode = Parser.ReadAdd(lexer); bool flag = stnode == null; STNode result; if (flag) { result = null; } else { while (lexer.SkipToken("&")) { STNode stnode2 = Parser.ReadAdd(lexer); bool flag2 = stnode2 == null; if (flag2) { throw Parser.CreateException(lexer, "expect expression"); } stnode = Parser.CreateNode(lexer, STNodeType.CONNECT, stnode.Start, lexer.CommittedLength - stnode.Start, new List { stnode, stnode2 }); } result = stnode; } return result; } private static STNode ReadAdd(ExcelFormulaLexer lexer) { STNode stnode = Parser.ReadMul(lexer); bool flag = stnode == null; if (!flag) { for (;;) { bool flag2 = lexer.IsToken("+"); STNodeType type; if (flag2) { type = STNodeType.ADD; } else { bool flag3 = lexer.IsToken("-"); if (!flag3) { break; } type = STNodeType.SUB; } lexer.NextToken(); STNode stnode2 = Parser.ReadMul(lexer); bool flag4 = stnode2 == null; if (flag4) { goto Block_4; } stnode = Parser.CreateNode(lexer, type, stnode.Start, lexer.CommittedLength - stnode.Start, new List { stnode, stnode2 }); } return stnode; Block_4: throw Parser.CreateException(lexer, "expect expression"); } return null; } private static STNode ReadMul(ExcelFormulaLexer lexer) { STNode stnode = Parser.ReadExponent(lexer); bool flag = stnode == null; if (!flag) { for (;;) { bool flag2 = lexer.IsToken("*"); STNodeType type; if (flag2) { type = STNodeType.MUL; } else { bool flag3 = lexer.IsToken("/"); if (!flag3) { break; } type = STNodeType.DIV; } lexer.NextToken(); STNode stnode2 = Parser.ReadExponent(lexer); bool flag4 = stnode2 == null; if (flag4) { goto Block_4; } stnode = Parser.CreateNode(lexer, type, stnode.Start, lexer.CommittedLength - stnode.Start, new List { stnode, stnode2 }); } return stnode; Block_4: throw Parser.CreateException(lexer, "expect expression"); } return stnode; } private static STNode ReadExponent(ExcelFormulaLexer lexer) { STNode stnode = Parser.ReadPercent(lexer); bool flag = stnode == null; STNode result; if (flag) { result = stnode; } else { while (lexer.SkipToken("^")) { STNode stnode2 = Parser.ReadPercent(lexer); bool flag2 = stnode2 == null; if (flag2) { throw Parser.CreateException(lexer, "expect expression"); } stnode = Parser.CreateNode(lexer, STNodeType.POW, stnode.Start, lexer.CommittedLength - stnode.Start, new List { stnode, stnode2 }); } result = stnode; } return result; } private static STNode ReadPercent(ExcelFormulaLexer lexer) { STNode stnode = Parser.ReadMinus(lexer); bool flag = stnode == null; STNode result; if (flag) { result = null; } else { while (lexer.SkipToken("%")) { stnode = Parser.CreateNode(lexer, STNodeType.UNARY_PERCENT, stnode.Start, lexer.CommittedLength - stnode.Start, new List { stnode }); } result = stnode; } return result; } private static STNode ReadMinus(ExcelFormulaLexer lexer) { bool flag = !lexer.IsToken("-"); STNode result; if (flag) { result = Parser.ReadFunctionCall(lexer); } else { int index = lexer.Index; lexer.NextToken(); STNode stnode = Parser.ReadFunctionCall(lexer); bool flag2 = stnode == null; if (flag2) { throw Parser.CreateException(lexer, "expect expression"); } result = Parser.CreateNode(lexer, STNodeType.UNARY_MINUS, index, lexer.CommittedLength - index, new List { stnode }); } return result; } private static STNode ReadFunctionCall(ExcelFormulaLexer lexer) { STNode stnode = Parser.ReadSheetName(lexer); bool flag = stnode == null; STNode result; if (flag) { result = null; } else { bool flag2 = stnode.Type == STNodeType.CELL; string name; if (flag2) { Group group; bool flag3 = lexer.CurrentToken == null || (group = lexer.CurrentToken.Groups["token"]) == null || !group.Success || group.Value != "("; if (flag3) { return stnode; } name = lexer.Input.Substring(stnode.Start, stnode.Length); lexer.NextToken(); } else { bool flag4 = stnode.Type != STNodeType.IDENTIFIER || !lexer.SkipToken("("); if (flag4) { return stnode; } name = ((STIdentifierNode)stnode).Identifier; } List children = Parser.ReadParameterList(lexer); bool flag5 = !lexer.SkipToken(")"); if (flag5) { throw Parser.CreateException(lexer, "expect )"); } result = new STFunctionNode(name, stnode.Start, lexer.CommittedLength - stnode.Start, children); } return result; } private static List ReadParameterList(ExcelFormulaLexer lexer) { List list = new List(); int num = 0; bool flag; do { STNode item = Parser.ReadExpr(lexer); list.Add(item); num++; flag = !lexer.SkipToken(FormulaExtension.ParameterSeparator); } while (!flag); while (list.Count > 0 && list[list.Count - 1] == null) { list.RemoveAt(list.Count - 1); } return (list.Count == 0) ? null : list; } private static STNode ReadSheetName(ExcelFormulaLexer lexer) { STNode stnode = Parser.ReadPrimary(lexer); bool flag = stnode == null; STNode result; if (flag) { result = null; } else { bool flag2 = stnode.Type != STNodeType.IDENTIFIER; if (flag2) { result = stnode; } else { bool flag3 = lexer.SkipToken("!"); if (flag3) { STNode stnode2 = Parser.ReadPrimary(lexer); bool flag4 = stnode2.Type != STNodeType.CELL && stnode2.Type != STNodeType.RANGE && stnode2.Type != STNodeType.IDENTIFIER; if (flag4) { throw Parser.CreateException(lexer, "expect Cell/Range/Name reference"); } string identifier = ((STIdentifierNode)stnode).Identifier; IWorkbook workbook = lexer.Workbook; bool flag5 = workbook == null && lexer.Cell != null && lexer.Cell.Worksheet != null && lexer.Cell.Worksheet.workbook != null; if (flag5) { workbook = lexer.Cell.Worksheet.workbook; } bool flag6 = workbook != null; if (flag6) { switch (stnode2.Type) { case STNodeType.IDENTIFIER: { STIdentifierNode stidentifierNode = (STIdentifierNode)stnode2; stidentifierNode.Worksheet = workbook.GetWorksheetByName(identifier); break; } case STNodeType.RANGE: { STRangeNode strangeNode = (STRangeNode)stnode2; strangeNode.Worksheet = workbook.GetWorksheetByName(identifier); break; } case STNodeType.CELL: { STCellNode stcellNode = (STCellNode)stnode2; stcellNode.Worksheet = workbook.GetWorksheetByName(identifier); break; } } } result = stnode2; } else { bool flag7 = lexer.SkipToken("."); if (flag7) { STNode stnode3 = Parser.ReadPrimary(lexer); bool flag8 = stnode3.Type != STNodeType.IDENTIFIER; if (flag8) { throw Parser.CreateException(lexer, "expect identifier"); } result = stnode3; } else { result = stnode; } } } } return result; } private static STNode ReadPrimary(ExcelFormulaLexer lexer) { STNode stnode; bool flag = Parser.CommitMatchNode(lexer, "string", STNodeType.STRING, out stnode) || Parser.CommitMatchNode(lexer, "identifier", STNodeType.IDENTIFIER, out stnode) || Parser.CommitMatchNode(lexer, "number", STNodeType.NUMBER, out stnode) || Parser.CommitMatchNode(lexer, "cell", STNodeType.CELL, out stnode) || Parser.CommitMatchNode(lexer, "range", STNodeType.RANGE, out stnode) || Parser.CommitMatchNode(lexer, "true", STNodeType.TRUE, out stnode) || Parser.CommitMatchNode(lexer, "false", STNodeType.FALSE, out stnode) || Parser.CommitMatchNode(lexer, "union_ranges", STNodeType.INTERSECTION, out stnode); STNode result; if (flag) { result = stnode; } else { bool flag2 = lexer.IsToken("("); if (flag2) { int index = lexer.Index; lexer.NextToken(); STNode stnode2 = Parser.ReadExpr(lexer); bool flag3 = stnode2 == null; if (flag3) { throw Parser.CreateException(lexer, "expect expression"); } bool flag4 = !lexer.SkipToken(")"); if (flag4) { throw Parser.CreateException(lexer, "expect )"); } result = Parser.CreateNode(lexer, STNodeType.SUB_EXPR, index, lexer.CommittedLength - index, new List { stnode2 }); } else { result = null; } } return result; } private static FormulaParseException CreateException(ExcelFormulaLexer lexer, string msg) { return new FormulaParseException(msg, lexer.CommittedLength); } private static bool CommitMatchNode(ExcelFormulaLexer lexer, string groupName, STNodeType type, out STNode node) { bool flag = lexer.IsMatch(groupName); bool result; if (flag) { Group group = lexer.CurrentToken.Groups[groupName]; node = Parser.CommitRunAndCreateNode(lexer, type, group.Index, group.Length, null); result = true; } else { node = null; result = false; } return result; } private static STNode CommitRunAndCreateNode(ExcelFormulaLexer lexer, STNodeType type, int start, int len, List nodes) { lexer.NextToken(); return Parser.CreateNode(lexer, type, start, len, nodes); } private static STNode CreateNode(ExcelFormulaLexer lexer, STNodeType type) { return new STNode(type, lexer.CurrentToken.Index, lexer.CurrentToken.Length, null); } private static STNode CreateNode(ExcelFormulaLexer lexer, STNodeType type, int start, int len, List nodes) { switch (type) { case STNodeType.NUMBER: { string s = lexer.Input.Substring(start, len); double value; return double.TryParse(s, out value) ? new STNumberNode(value, start, len) : null; } case STNodeType.STRING: return new STStringNode(lexer.Input, start, len); case STNodeType.IDENTIFIER: return new STIdentifierNode((lexer.Cell == null) ? null : lexer.Cell.Worksheet, lexer.Input.Substring(start, len), start, len); case STNodeType.RANGE: return new STRangeNode(null, new RangePosition(lexer.Input.Substring(start, len)), start, len); case STNodeType.CELL: return new STCellNode(null, new CellPosition(lexer.Input.Substring(start, len)), type, start, len); } return new STNode(type, start, len, nodes); } } }