source: trunk/CrypPlugins/MathParser/Parser.cs @ 2334

Last change on this file since 2334 was 841, checked in by Sören Rinne, 12 years ago
  • some changes in BM, BFP, LFSR, NLFSR
  • BFP now accepts x*.* instead of i_*.*
  • added 2 function parsers
File size: 6.4 KB
Line 
1/* Copyright (C) 2005 <Paratrooper> paratrooper666@gmx.net
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 *  the Free Software Foundation; either version 2 of the License, or
5 *  any later version.
6 */
7
8using System;
9using System.Collections;
10using System.Text.RegularExpressions;
11
12namespace Cryptool.MathParser
13{
14        public enum Mode { RAD, DEG, GRAD };
15
16        public class Parser
17        {
18                private ArrayList FunctionList = new ArrayList( new string[] { "abs", "acos", "asin", "atan", "ceil", "cos", "cosh", "exp", "floor", "ln", "log", "sign", "sin", "sinh", "sqrt", "tan", "tanh" } );
19                private double Value;
20                private double Factor;
21                private Mode mode;
22
23                // Constructor
24                public Parser()
25                {
26                        this.Mode = Mode.RAD;
27                }
28                public Parser( Mode mode )
29                {
30                        this.Mode  = mode;
31                }
32
33                // Getter & Setter
34                public double Result
35                {
36                        get{ return this.Value; }
37                }
38                public Mode Mode
39                {
40                        get{ return this.mode; }
41                        set
42                        {
43                                this.mode = value;
44                                switch( value )
45                                {
46                                        case Mode.RAD :
47                                                this.Factor = 1.0;
48                                                break;
49                                        case Mode.DEG :
50                                                this.Factor = 2.0 * Math.PI / 360.0;
51                                                break;
52                                        case Mode.GRAD :
53                                                this.Factor = 2.0 * Math.PI / 400.0;
54                                                break;
55                                }
56                        }
57                }
58
59                public bool Evaluate( string Expression ) 
60                {
61                        try 
62                        {
63                                // ****************************************************************************************
64                                // ** MathParser in action:                                                              **
65                                // ** Expression = "-(5 - 10)^(-1)  ( 3 + 2(    cos( 3 Pi )+( 2+ ln( exp(1) ) )    ^3))" **
66                                // ****************************************************************************************
67                                //
68                                //
69                                // ----------
70                                // - Step 1 -
71                                // ----------
72                                // Remove blank.
73                                //
74                                // -(5 - 10)^(-1)  ( 3 + 2(    cos( 3 Pi )+( 2+ ln( exp(1) ) )    ^3)) -> -(5-10)^(-1)(3+2(cos(3Pi)+(2+ln(exp(1)))^3))
75                                //
76                                Expression = Expression.Replace( " ", "" );
77                                //
78                                // ----------
79                                // - Step 2 -
80                                // ----------
81                                // Insert '*' if necessary.
82                                //
83                                //                                                             _    _      _
84                                // -(5-10)^(-1)(3+2(cos(3Pi)+(2+ln(exp(1)))^3)) -> -(5-10)^(-1)*(3+2*(cos(3*Pi)+(2+ln(exp(1)))^3))
85                                //             |   |     |
86                                //
87                                Regex regEx = new Regex( @"(?<=[\d\)])(?=[a-df-z\(])|(?<=pi)(?=[^\+\-\*\/\\^!)])|(?<=\))(?=\d)|(?<=[^\/\*\+\-])(?=exp)", RegexOptions.IgnoreCase );
88                                Expression = regEx.Replace( Expression, "*" );
89                                //
90                                // ----------
91                                // - Step 4 -
92                                // ----------
93                                // Search for parentheses an solve the expression between it.
94                                //
95                                /*                                                      _____
96                                * -(5-10)^(-1)*(3+2*(cos(3*3,14)+(2+ln(exp(1)))^3)) -> -{-5}^(-1)*(3+2*(cos(3*3,14)+(2+ln(exp(1)))^3))
97                                *  |_____|
98                                *                                                          __
99                                * -{-5}^(-1)*(3+2*(cos(3*3,14)+(2+ln(exp(1)))^3)) -> -{-5}^-1*(3+2*(cos(3*3,14)+(2+ln(exp(1)))^3))
100                                *       |__|
101                                *                                                                    ____
102                                * -{-5}^-1*(3+2*(cos(3*3,14)+(2+ln(exp(1)))^3)) -> -{-5}^-1*(3+2*(cos9,42+(2+ln(exp(1)))^3))
103                                *                   |______|
104                                *                                                                              _
105                                * -{-5}^-1*(3+2*(cos9,72+(2+ln(exp(1)))^3)) -> -{-5}^-1*(3+2*(cos9,72+(2+ln(exp1))^3))
106                                *                                 |_|
107                                *                                                                        ____
108                                * -{-5}^-1*(3+2*(cos9,72+(2+ln(exp1))^3)) -> -{-5}^-1*(3+2*(cos9,72+(2+ln2,71)^3))
109                                *                             |____|
110                                *                                                                 ____
111                                * -{-5}^-1*(3+2*(cos9,72+(2+ln2,71)^3)) -> -{-5}^-1*(3+2*(cos9,72+{3}^3))
112                                *                        |_________|
113                                *                                                 __
114                                * -{-5}^-1*(3+2*(cos9,72+{3}^3)) -> -{-5}^-1*(3+2*26)
115                                *               |_____________|
116                                *                               __
117                                * -{-5}^-1*(3+2*26) -> -{-5}^-1*55
118                                *          |______|
119                                */
120                                regEx = new Regex( @"([a-z]*)\(([^\(\)]+)\)(\^|!?)", RegexOptions.IgnoreCase );
121                                Match m = regEx.Match( Expression );
122                                while( m.Success )
123                                {
124                                        if( m.Groups[3].Value.Length > 0 ) Expression = Expression.Replace( m.Value, "{" + m.Groups[1].Value + this.Solve( m.Groups[2].Value ) + "}" + m.Groups[3].Value );
125                                        else Expression = Expression.Replace( m.Value, m.Groups[1].Value + this.Solve( m.Groups[2].Value ) );
126                                        m = regEx.Match( Expression );
127                                }
128                                //
129                                // ----------
130                                // - Step 5 -
131                                // ----------
132                                // There are no more parentheses. Solve the expression and convert it to double.
133                                //                __
134                                // -{-5}^-1*55 => 11
135                                // |_________|
136                                //
137                                this.Value = Convert.ToDouble( this.Solve( Expression ) );
138                                return true;
139                        }
140                        catch
141                        {
142                                // Shit!
143                                return false;
144                        }
145                }
146
147                private string Solve( string Expression )
148                {
149            Regex regEx;
150            Match m;
151
152                        // Solve AND
153                        regEx = new Regex( @"([\+-]?\d+,*\d*[eE][\+-]?\d+|[\-\+]?\d+,*\d*)([\/\*])(-?\d+,*\d*[eE][\+-]?\d+|-?\d+,*\d*)" );
154                        m = regEx.Match( Expression, 0 );
155                        while( m.Success )
156                        {
157                                double result;
158                                //switch( m.Groups[2].Value )
159                                //{
160                                //      case "*" :
161                                                result = Convert.ToDouble(Convert.ToInt32( m.Groups[1].Value ) & Convert.ToInt32( m.Groups[3].Value ));
162                                                if(m.Index == 0) Expression = regEx.Replace( Expression, result.ToString(), 1 );
163                                                else Expression = Expression.Replace( m.Value, "+" + result );
164                                                m = regEx.Match( Expression );
165                                //              continue;
166                                //}
167                        }
168                        // Solve XOR.
169                        regEx = new Regex( @"([\+-]?\d+,*\d*[eE][\+-]?\d+|[\+-]?\d+,*\d*)([\+-])(-?\d+,*\d*[eE][\+-]?\d+|-?\d+,*\d*)" );
170                        m = regEx.Match( Expression, 0 );
171                        while( m.Success )
172                        {
173                                double result;
174                                //switch( m.Groups[2].Value )
175                                //{
176                                //      case "+" :
177                                                result = result = Convert.ToDouble(Convert.ToInt32( m.Groups[1].Value ) ^ Convert.ToInt32( m.Groups[3].Value ));
178                                                if(m.Index == 0) Expression = regEx.Replace( Expression, result.ToString(), 1 );
179                                                else Expression = regEx.Replace( Expression, "+" + result, 1 );
180                                                m = regEx.Match( Expression );
181                                //              continue;
182                                //}
183                        }
184                        //if( Expression.StartsWith( "--" ) ) Expression = Expression.Substring(2);
185                        return Expression;
186                }
187        }
188}
Note: See TracBrowser for help on using the repository browser.