123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- using System;
- using System.Collections.Generic;
- using FastReport.Code;
- using FastReport.Utils;
- using FastReport.Table;
- namespace FastReport.AdvMatrix
- {
- internal class ExpressionParser
- {
- private AdvMatrixObject matrix;
- internal static readonly string[] SpecialFunctionNames = {
- "ColumnTotal", "RowTotal", "GrandTotal", "GrandColumnTotal", "GrandRowTotal",
- "SpecificColumn", "SpecificRow", "FirstColumn", "FirstRow", "LastColumn", "LastRow", "PreviousColumn", "PreviousRow", "NextColumn", "NextRow",
- "ColumnMaxValue", "ColumnMinValue", "RowMaxValue", "RowMinValue",
- "PercentOfColumnTotal", "PercentOfRowTotal", "PercentOfGrandTotal", "PercentOfPreviousColumn", "PercentOfPreviousRow" };
- private bool IsAggregate(string ident)
- {
- return Aggregates.Find(ident) != null || ident.StartsWith("_");
- }
- private bool IsSpecialFunction(string ident)
- {
- foreach (string s in SpecialFunctionNames)
- {
- if (s == ident)
- return true;
- }
- return false;
- }
- private string ToSpecialFunctionCall(string name)
- {
- return matrix.Name + ".Data.Context.Get" + name;
- }
- // parse expression:
- // - search for aggregates and collect them in the aggregates list
- // - replace aggregate calls: AggrName(expression) -> MatrixName.Data.Context.GetAggregate("AggrName", "expression")
- // - search for special functions like "PreviousColumn(...)" and collect them in the specialFunctions list
- // - replace special function calls: PreviousColumn() -> MatrixName.Data.Context.GetPreviousColumn()
- private string Parse(string expression, AggregateExpressionPairList aggregates, List<string> specialFunctions)
- {
- FindTextArgs args = new FindTextArgs();
- args.Text = new FastString(expression);
- args.OpenBracket = "(";
- args.CloseBracket = ")";
- // search for method calls
- while (args.StartIndex < args.Text.Length)
- {
- if (CodeUtils.GetExpression(args, false) == null)
- break;
- // get identifier at the left of (
- int i = args.StartIndex;
- while (i > 0)
- {
- char c = args.Text[i - 1];
- if (!(char.IsLetterOrDigit(c) || c == '_'))
- break;
- i--;
- }
- string ident = args.Text.Substring(i, args.StartIndex - i);
- // if ident has preceding . symbol, ignore it
- if (i > 0 && args.Text[i - 1] == '.')
- ident = "";
- if (IsAggregate(ident))
- {
- // ident is either one of predefined aggregates or a user aggregate
- string newText = aggregates.AddUnique(ident, args.FoundText).ToAggregateCall();
- args.Text.Remove(i, args.EndIndex - i);
- args.Text.Insert(i, newText);
- args.StartIndex = i + newText.Length;
- }
- else if (IsSpecialFunction(ident))
- {
- // ident is a special function like PreviousColumn(...)
- if (specialFunctions != null)
- specialFunctions.Add(ident);
- string newText = ToSpecialFunctionCall(ident);
- args.Text.Remove(i, ident.Length);
- args.Text.Insert(i, newText);
- args.StartIndex = i + newText.Length;
- }
- else
- {
- string newText = "(" + Parse(args.FoundText, aggregates, specialFunctions) + ")";
- args.Text.Remove(args.StartIndex, args.EndIndex - args.StartIndex);
- args.Text.Insert(args.StartIndex, newText);
- args.StartIndex += newText.Length;
- }
- }
- return args.Text.ToString();
- }
- // parse expression with single aggregate
- public AggregateExpressionPair Parse(string expression)
- {
- AggregateExpressionPairList list = new AggregateExpressionPairList(matrix);
- Parse(expression, list, null);
- if (list.Count == 1)
- return list[0];
- return null;
- }
- public CellDescriptor ProcessCell(TableCell cell)
- {
- // create cell descriptor and attach it to a cell
- CellDescriptor cellDescriptor = new CellDescriptor(matrix, cell);
- string text = cell.Text;
- string[] brackets = cell.Brackets.Split(',');
- if (String.IsNullOrEmpty(text) || brackets.Length != 2)
- return cellDescriptor;
- // process all expressions in the cell's text
- FindTextArgs args = new FindTextArgs();
- args.Text = new FastString(text);
- args.OpenBracket = brackets[0];
- args.CloseBracket = brackets[1];
- while (args.StartIndex < args.Text.Length)
- {
- string expression = CodeUtils.GetExpression(args, false);
- if (expression == null)
- break;
- expression = Parse(expression, cellDescriptor.Aggregates, cellDescriptor.SpecialFunctions);
- cellDescriptor.Expressions.Add(expression);
- expression = brackets[0] + expression + brackets[1];
- args.Text.Remove(args.StartIndex, args.EndIndex - args.StartIndex);
- args.Text.Insert(args.StartIndex, expression);
- args.StartIndex += expression.Length;
- }
- // set the new text to the cell descriptor
- cellDescriptor.Text = args.Text.ToString();
- cellDescriptor.UpdateContentType();
- return cellDescriptor;
- }
- public ExpressionParser(AdvMatrixObject matrix)
- {
- this.matrix = matrix;
- }
- }
- }
|