Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2915-AbsoluteSymbol/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/FormulaParsing/ExpressionGraph/ExpressionCompiler.cs @ 16300

Last change on this file since 16300 was 12074, checked in by sraggl, 10 years ago

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 6.4 KB
Line 
1/*******************************************************************************
2 * You may amend and distribute as you like, but don't remove this header!
3 *
4 * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
5 * See http://www.codeplex.com/EPPlus for details.
6 *
7 * Copyright (C) 2011  Jan Källman
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
17 * See the GNU Lesser General Public License for more details.
18 *
19 * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
20 * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
21 *
22 * All code and executables are provided "as is" with no warranty either express or implied.
23 * The author accepts no liability for any damage or loss of business that this product may cause.
24 *
25 * Code change notes:
26 *
27 * Author             Change            Date
28 * ******************************************************************************
29 * Mats Alm                       Added                   2013-03-01 (Prior file history on https://github.com/swmal/ExcelFormulaParser)
30 *******************************************************************************/
31using System;
32using System.Collections.Generic;
33using System.Linq;
34using System.Text;
35using OfficeOpenXml.FormulaParsing.Excel.Operators;
36using OfficeOpenXml.FormulaParsing.ExpressionGraph.CompileStrategy;
37
38namespace OfficeOpenXml.FormulaParsing.ExpressionGraph
39{
40    public class ExpressionCompiler : IExpressionCompiler
41    {
42        private IEnumerable<Expression> _expressions;
43        private IExpressionConverter _expressionConverter;
44        private ICompileStrategyFactory _compileStrategyFactory;
45
46        public ExpressionCompiler()
47            : this(new ExpressionConverter(), new CompileStrategyFactory())
48        {
49 
50        }
51
52        public ExpressionCompiler(IExpressionConverter expressionConverter, ICompileStrategyFactory compileStrategyFactory)
53        {
54            _expressionConverter = expressionConverter;
55            _compileStrategyFactory = compileStrategyFactory;
56        }
57
58        public CompileResult Compile(IEnumerable<Expression> expressions)
59        {
60            _expressions = expressions;
61            return PerformCompilation();
62        }
63        public CompileResult Compile(string worksheet, int row, int column, IEnumerable<Expression> expressions)
64        {
65            _expressions = expressions;
66            return PerformCompilation(worksheet, row, column);
67        }
68
69        private CompileResult PerformCompilation(string worksheet="", int row=-1, int column=-1)
70        {
71            var compiledExpressions = HandleGroupedExpressions();
72            while(compiledExpressions.Any(x => x.Operator != null))
73            {
74                var prec = FindLowestPrecedence();
75                compiledExpressions = HandlePrecedenceLevel(prec);
76            }
77            if (_expressions.Any())
78            {
79                return compiledExpressions.First().Compile();
80            }
81            return CompileResult.Empty;
82        }
83
84        private IEnumerable<Expression> HandleGroupedExpressions()
85        {
86            if (!_expressions.Any()) return Enumerable.Empty<Expression>();
87            var first = _expressions.First();
88            var groupedExpressions = _expressions.Where(x => x.IsGroupedExpression);
89            foreach(var groupedExpression in groupedExpressions)
90            {
91                var result = groupedExpression.Compile();
92                if (result == CompileResult.Empty) continue;
93                var newExp = _expressionConverter.FromCompileResult(result);
94                newExp.Operator = groupedExpression.Operator;
95                newExp.Prev = groupedExpression.Prev;
96                newExp.Next = groupedExpression.Next;
97                if (groupedExpression.Prev != null)
98                {
99                    groupedExpression.Prev.Next = newExp;
100                }
101                if (groupedExpression.Next != null)
102                {
103                    groupedExpression.Next.Prev = newExp;
104                }
105                if (groupedExpression == first)
106                {
107                    first = newExp;
108                }
109            }
110            return RefreshList(first);
111        }
112
113        private IEnumerable<Expression> HandlePrecedenceLevel(int precedence)
114        {
115            var first = _expressions.First();
116            var expressionsToHandle = _expressions.Where(x => x.Operator != null && x.Operator.Precedence == precedence);
117            var last = expressionsToHandle.Last();
118            var expression = expressionsToHandle.First();
119            do
120            {
121                var strategy = _compileStrategyFactory.Create(expression);
122                var compiledExpression = strategy.Compile();
123                if(compiledExpression is ExcelErrorExpression)
124                {
125                    return RefreshList(compiledExpression);
126                }
127                if (expression == first)
128                {
129                    first = compiledExpression;
130                }
131
132                expression = compiledExpression;
133            }
134            while (expression != null && expression.Operator != null && expression.Operator.Precedence == precedence);
135            return RefreshList(first);
136        }
137
138        private int FindLowestPrecedence()
139        {
140            return _expressions.Where(x => x.Operator != null).Min(x => x.Operator.Precedence);
141        }
142
143        private IEnumerable<Expression> RefreshList(Expression first)
144        {
145            var resultList = new List<Expression>();
146            var exp = first;
147            resultList.Add(exp);
148            while (exp.Next != null)
149            {
150                resultList.Add(exp.Next);
151                exp = exp.Next;
152            }
153            _expressions = resultList;
154            return resultList;
155        }
156    }
157}
Note: See TracBrowser for help on using the repository browser.