internal ColumnFormula( CellValueCalculator cellValueCalculator, FormulaExpressionsCompiler formulaExpressionsCompiler) { _cellCalculator = formulaExpressionsCompiler.CompileCellValueCalculator(cellValueCalculator); _aggregatedValueCalculators = formulaExpressionsCompiler.CompileAggregatedValueCalculators(cellValueCalculator.AggregatedValuesCalculators); _expressionText = cellValueCalculator.ToString(); }
public CellValueCalculator All(FormulaExpressionsCompiler compiler) { var precalculatedAggregatedValueKey = "all:" + CalculateExpression; var exactEnumerableType = typeof(IEnumerable <>).MakeGenericType(ResultType); return(new CellValueCalculator( exactEnumerableType, GetPrecalculatedAggregatedValue(exactEnumerableType, compiler.Parameters, precalculatedAggregatedValueKey), ImmutableList.Create( KeyValuePair.Create(precalculatedAggregatedValueKey, compiler.CallEnumerableSelect(CalculateExpression, ResultType))), canBeAggregated: true)); }
public ColumnFormulaBuilder( Type rowDataType, TryParse <Type> tryGetPropertyTypeByName, TryParse <IReadOnlyCollection <MethodInfo> > tryGetFunctionsByName) { var parameters = new FormulaParameters(rowDataType); _formulaCompiler = new FormulaExpressionsCompiler(parameters); var integerLiteral = NumericLiteral(new TryParse <int>(int.TryParse)); var decimalLiteral = NumericLiteral(new TryParse <decimal>(decimal.TryParse)); var dateTimeLiteral = ParsedQuotedLiteral(new TryParse <DateTime>(DateTime.TryParse)); var stringLiteral = QuotedLiteral.Select(Constant); var literal = dateTimeLiteral.Or(stringLiteral).Or(integerLiteral).Or(decimalLiteral); var quotedPropertyName = from openingBracket in Lexem("[") from nameChars in Repeat(ch => ch != ']' && ch != '\r' && ch != '\n') from closingBraket in Lexem("]") select string.Join( string.Empty, nameChars .Where(ch => ch != ' ' && ch != '\t') .Select(ch => char.IsLetterOrDigit(ch) ? ch.ToString() : $"_char_{(int)ch}_")); var propertyName = quotedPropertyName.Or(Identifier); var propertyAccessor = from name in propertyName from propertyType in name.Try(tryGetPropertyTypeByName, n => $"Unknown property: '{n}'").StopParsingIfFailed() select new CellValueCalculator(propertyType, Expression.Property(parameters.CurrentRow, name)); var aggregatableExpression = CreateFormulaParser(literal, propertyAccessor, tryGetFunctionsByName, parameters); var aggregatedPropertyAccessor = from openingBracket in Lexem("[") from aggregationMethodText in Identifier from colon in Lexem(":") from aggregationMethod in aggregationMethodText.Try <AggregationMethod>( Enum.TryParse, m => $"Invalid aggregation method {m} specified: only '" + string.Join("', '", Enum.GetNames(typeof(AggregationMethod)) + "' are supported")).StopParsingIfFailed() from calculator in aggregatableExpression from closingBraket in Lexem("]") select aggregationMethod == AggregationMethod.all ? calculator.All(_formulaCompiler) : calculator.FirstOrLast(aggregationMethod, _formulaCompiler); _formulaTextParser = CreateFormulaParser( literal, aggregatedPropertyAccessor.Or(propertyAccessor), tryGetFunctionsByName, parameters); }
public CellValueCalculator FirstOrLast(AggregationMethod aggregationMethod, FormulaExpressionsCompiler compiler) { var allRowsCalculator = All(compiler); var key = $"{aggregationMethod}:{CalculateExpression}"; return(new CellValueCalculator( ResultType, GetPrecalculatedAggregatedValue(ResultType, compiler.Parameters, key), allRowsCalculator.AggregatedValuesCalculators.Insert( 0, KeyValuePair.Create( key, compiler.CallEnumerableFirstOrLast( allRowsCalculator.CalculateExpression, aggregationMethod, ResultType))), canBeAggregated: true)); }