/// <summary> /// Parse a formula, return the the tree /// </summary> /// <param name="input">The formula to be parsed.</param> /// <exception cref="ArgumentException"> /// If formula could not be parsed /// </exception> /// <returns>Parse tree</returns> public static ParseTree ParseToTree(string input) { var tree = P.Parse(input); if (tree.HasErrors()) { throw new ArgumentException("Failed parsing input <<" + input + ">>"); } var intersects = tree.Root.AllNodes().Where(node => node.Is(GrammarNames.TokenIntersect)); foreach (ParseTreeNode intersect in intersects) { var newLocation = new SourceLocation(intersect.Span.Location.Position - 1, intersect.Span.Location.Line, intersect.Span.Location.Column - 1); intersect.Span = new SourceSpan(newLocation, 1); } var quotedSheetNodes = tree.Root.AllNodes().Where(node => node.Is(GrammarNames.TokenSheetQuoted)); foreach (ParseTreeNode quotedSheetNode in quotedSheetNodes) { PrefixInfo.FixQuotedSheetNodeForWhitespace(quotedSheetNode, input); } return(tree); }
/// <summary> /// Extract all of the information from a Prefix non-terminal /// </summary> public static PrefixInfo GetPrefixInfo(this ParseTreeNode prefix) => PrefixInfo.From(prefix);
/// <summary> /// Initializes the current object based on the input ParseTreeNode /// </summary> /// <remarks> /// For Reference nodes (Prefix ReferenceItem), it initialize the values derived from the Prefix node and /// is re-invoked for the ReferenceItem node. /// </remarks> public void InitializeReference(ParseTreeNode node) { switch (node.Type()) { case GrammarNames.Reference: PrefixInfo prefix = node.ChildNodes[0].GetPrefixInfo(); Worksheet = prefix.HasSheet ? prefix.Sheet.Replace("''", "'") : "(Undefined sheet)"; if (prefix.HasMultipleSheets) { string[] sheets = prefix.MultipleSheets.Split(':'); Worksheet = sheets[0]; LastWorksheet = sheets[1]; } if (prefix.HasFileNumber) { FileName = prefix.FileNumber.ToString(); } else if (prefix.HasFileName) { FileName = prefix.FileName; } else { FileName = null; } InitializeReference(node.ChildNodes[1]); break; case GrammarNames.Cell: ReferenceType = ReferenceType.Cell; MinLocation = node.ChildNodes[0].Token.ValueString; MaxLocation = MinLocation; break; case GrammarNames.NamedRange: ReferenceType = ReferenceType.UserDefinedName; Name = node.ChildNodes[0].Token.ValueString; if (FileName != null) { MinLocation = "A1"; } break; case GrammarNames.HorizontalRange: string[] horizontalLimits = node.ChildNodes[0].Token.ValueString.Split(':'); ReferenceType = ReferenceType.HorizontalRange; MinLocation = "A" + horizontalLimits[0]; MaxLocation = ConvertColumnToStr(MaxRangeWidth - 1) + horizontalLimits[1]; break; case GrammarNames.VerticalRange: string[] verticalLimits = node.ChildNodes[0].Token.ValueString.Split(':'); ReferenceType = ReferenceType.VerticalRange; MinLocation = verticalLimits[0] + "1"; MaxLocation = verticalLimits[1] + MaxRangeHeight; break; case GrammarNames.RefError: ReferenceType = ReferenceType.RefError; MinLocation = "A1"; break; default: // UDFs MinLocation = "A1"; break; } LocationString = node.Print(); }