private static void ProcessRightParenth(Expression e, Stack <FuncData> tmpStack, int pos) { if (tmpStack.Count == 0) { throw new ArgumentException("unmatching right parenthesis at " + pos); } while (tmpStack.Peek().SpecialKind != SpecialOperandKind.LeftParenthesis) { e.Append(tmpStack.Pop().Func); if (tmpStack.Count == 0) { throw new ArgumentException("unmatching right parenthesis at " + pos); } } tmpStack.Pop(); //remove left parenthesis while (tmpStack.Count > 0 && tmpStack.Peek().IsFunctionOrUnary) //append function/unary minus or both { e.Append(tmpStack.Pop().Func); } }
private static void ProcessComma(Expression e, Stack <FuncData> tmpStack, int pos) { if (tmpStack.Count == 0) { throw new ArgumentException("comma without left parenthesis at " + pos); } while (tmpStack.Peek().SpecialKind != SpecialOperandKind.LeftParenthesis) { e.Append(tmpStack.Pop().Func); if (tmpStack.Count == 0) { throw new ArgumentException("comma without left parenthesis at " + pos); } } }
private static void ProcessOperator(FuncData op, Expression e, Stack <FuncData> tmpStack) { while (tmpStack.Count > 0) //while operators with higher or equal precedence { FuncData fd = tmpStack.Peek(); if (fd.SpecialKind == SpecialOperandKind.NotSpecial && !fd.IsFunctionOrUnary && fd.Precedence >= op.Precedence) { e.Append(tmpStack.Pop().Func); } else { break; } } tmpStack.Push(op); }
public static Expression Parse(string expression, IEnumerable <string> vars) { expression.ToLower(); int pos = 0; Stack <FuncData> tmpStack = new Stack <FuncData>(); Expression e = new Expression(vars); bool noBOperatorExpected = true; bool lParenthExpected = false; while (pos < expression.Length) { string term = ReadTerm(expression, ref pos); if (lParenthExpected && term != "(") { throw new ArgumentException("expected '(' at " + pos); } lParenthExpected = false; //checked, can be turn off //if a number or const or variable, append to the expression double num; if (double.TryParse(term, out num)) //number { e.Append(new Variable() { Value = num, Name = num.ToString() }); noBOperatorExpected = false; continue; } IExpressionElement el; if (_consts.TryGetValue(term, out el)) //const { e.Append(el); noBOperatorExpected = false; continue; } Variable v; if (e.Vars.TryGetValue(term, out v)) //variable { e.Append(v); noBOperatorExpected = false; continue; } //if function -> push to stack FuncData fd; if (_functions.TryGetValue(term, out fd)) { tmpStack.Push(fd); lParenthExpected = true; //dont need to set/reset noBOperatorExpected continue; } if (term.Length == 1) //operators { char termch = term[0]; if (_soperators.TryGetValue(termch, out fd)) { switch (fd.SpecialKind) { case SpecialOperandKind.LeftParenthesis: tmpStack.Push(fd); noBOperatorExpected = true; break; case SpecialOperandKind.RightParenthesis: noBOperatorExpected = false; ProcessRightParenth(e, tmpStack, pos); break; case SpecialOperandKind.Comma: noBOperatorExpected = true; ProcessComma(e, tmpStack, pos); break; } continue; } if (noBOperatorExpected) { if (_uoperators.TryGetValue(termch, out fd)) { tmpStack.Push(fd); //noBOperatorExpected = true; - is already continue; } } else { if (_operators.TryGetValue(termch, out fd)) { ProcessOperator(fd, e, tmpStack); noBOperatorExpected = true; continue; } } } //unrecongnizable throw new ArgumentException("unrecognizable term " + term + " at before " + pos); } //we will be tolerant to closing parenthesis, i.e. the left parenthesis left will be ignored foreach (var f in tmpStack) { if (f.SpecialKind != SpecialOperandKind.LeftParenthesis) { e.Append(f.Func); } else { throw new ArgumentException("unmatching parenthesis"); } } return(e); }
private static void ProcessOperator(FuncData op, Expression e, Stack<FuncData> tmpStack) { while (tmpStack.Count>0) //while operators with higher or equal precedence { FuncData fd = tmpStack.Peek(); if (fd.SpecialKind == SpecialOperandKind.NotSpecial && !fd.IsFunctionOrUnary && fd.Precedence >= op.Precedence) e.Append(tmpStack.Pop().Func); else break; } tmpStack.Push(op); }
private static void ProcessRightParenth(Expression e, Stack<FuncData> tmpStack, int pos) { if (tmpStack.Count == 0) throw new ArgumentException("unmatching right parenthesis at " + pos); while (tmpStack.Peek().SpecialKind != SpecialOperandKind.LeftParenthesis) { e.Append(tmpStack.Pop().Func); if (tmpStack.Count == 0) throw new ArgumentException("unmatching right parenthesis at " + pos); } tmpStack.Pop(); //remove left parenthesis while (tmpStack.Count > 0 && tmpStack.Peek().IsFunctionOrUnary) //append function/unary minus or both e.Append(tmpStack.Pop().Func); }
private static void ProcessComma(Expression e, Stack<FuncData> tmpStack, int pos) { if (tmpStack.Count==0) throw new ArgumentException("comma without left parenthesis at " + pos); while (tmpStack.Peek().SpecialKind!=SpecialOperandKind.LeftParenthesis) { e.Append(tmpStack.Pop().Func); if (tmpStack.Count == 0) throw new ArgumentException("comma without left parenthesis at " + pos); } }
public static Expression Parse(string expression, IEnumerable<string> vars) { expression.ToLower(); int pos = 0; Stack<FuncData> tmpStack=new Stack<FuncData>(); Expression e=new Expression(vars); bool noBOperatorExpected = true; bool lParenthExpected = false; while (pos<expression.Length) { string term = ReadTerm(expression, ref pos); if (lParenthExpected && term!="(") throw new ArgumentException("expected '(' at "+pos); lParenthExpected = false; //checked, can be turn off //if a number or const or variable, append to the expression double num; if (double.TryParse(term, out num)) //number { e.Append(new Variable() {Value = num, Name=num.ToString()}); noBOperatorExpected = false; continue; } IExpressionElement el; if (_consts.TryGetValue(term, out el)) //const { e.Append(el); noBOperatorExpected = false; continue; } Variable v; if (e.Vars.TryGetValue(term, out v)) //variable { e.Append(v); noBOperatorExpected = false; continue; } //if function -> push to stack FuncData fd; if (_functions.TryGetValue(term, out fd)) { tmpStack.Push(fd); lParenthExpected = true; //dont need to set/reset noBOperatorExpected continue; } if (term.Length == 1) //operators { char termch = term[0]; if (_soperators.TryGetValue(termch, out fd)) { switch (fd.SpecialKind) { case SpecialOperandKind.LeftParenthesis: tmpStack.Push(fd); noBOperatorExpected = true; break; case SpecialOperandKind.RightParenthesis: noBOperatorExpected = false; ProcessRightParenth(e, tmpStack, pos); break; case SpecialOperandKind.Comma: noBOperatorExpected = true; ProcessComma(e, tmpStack, pos); break; } continue; } if (noBOperatorExpected) { if (_uoperators.TryGetValue(termch, out fd)) { tmpStack.Push(fd); //noBOperatorExpected = true; - is already continue; } } else { if(_operators.TryGetValue(termch, out fd)) { ProcessOperator(fd, e, tmpStack); noBOperatorExpected = true; continue; } } } //unrecongnizable throw new ArgumentException("unrecognizable term " + term + " at before " + pos); } //we will be tolerant to closing parenthesis, i.e. the left parenthesis left will be ignored foreach (var f in tmpStack) if (f.SpecialKind!=SpecialOperandKind.LeftParenthesis) e.Append(f.Func); else throw new ArgumentException("unmatching parenthesis"); return e; }