Expr ParseExpr() { var OpStack = new Stack<Operator>(); var CStack = new Stack<Expr>(); ExprNext NextCanBe = ExprNext.UExpr | ExprNext.BExpr | ExprNext.Literal | ExprNext.Bracket; while (Index < Tokens.Count) { // token is literal (double, int, bool, string, function call) if (NextCanBe.HasFlag(ExprNext.Literal)) { if (Tokens[Index].isSB) { var stringLiteral = new StringLiteral(); stringLiteral.Value = ((StringBuilder)Tokens[Index]).ToString(); Index++; CStack.Push(stringLiteral); NextCanBe = ExprNext.BExpr; continue; } else if (Tokens[Index].isInt) { var intLiteral = new IntLiteral(); intLiteral.Value = (int)Tokens[Index]; Index++; CStack.Push(intLiteral); NextCanBe = ExprNext.BExpr; continue; } else if (Tokens[Index].isDbl) { var dblLiteral = new DblLiteral(); dblLiteral.Value = (double)Tokens[Index]; NextCanBe = ExprNext.BExpr; Index++; CStack.Push(dblLiteral); continue; } else if (Tokens[Index].isStr && FuncDef.ContainsKey((string)Tokens[Index])) { // If function is exists var function = new ExprFunction(); function.Identity = (string)Tokens[Index]; var P = FuncDef[(string)Tokens[Index]].Parameters.Count; int i = 0; Index++; while (Index < Tokens.Count && i < P) { function.Parameters.Add(ParseExpr()); i++; } if (Index == Tokens.Count && i < P) { throw new RPExeption(29, App.Current.TryFindResource("x_fparnm").ToString(), Line, Column); } CStack.Push(function); NextCanBe = ExprNext.BExpr; continue; } } // if token is not expression either break if (!NextCanBe.HasFlag(ExprNext.UExpr) && !NextCanBe.HasFlag(ExprNext.BExpr) && !NextCanBe.HasFlag(ExprNext.Bracket) || !Tokens[Index].isStr) break; // else token is an operator switch ((string)Tokens[Index]) { case Scanner.BracketStart: if (NextCanBe.HasFlag(ExprNext.Bracket)) { Index++; OpStack.Push(new Group()); NextCanBe = ExprNext.UExpr | ExprNext.BExpr | ExprNext.Literal | ExprNext.Bracket; continue; } break; case Scanner.BracketEnd: { Index++; var o = (OpStack.Count > 0) ? OpStack.Peek() : null; while (OpStack.Count > 0 && !(o is Group)) { if (o.IsBinary) { var expr = new BinaryExpression(); expr.BinaryOperator = OpStack.Pop(); if (expr.BinaryOperator.Level >= OpStack.Peek().Level) { expr.Right = CStack.Pop(); expr.Left = CStack.Pop(); } else { expr.Left = CStack.Pop(); expr.Right = CStack.Pop(); } CStack.Push(expr); } else { var expr = new UnaryExpression(); expr.Right = CStack.Pop(); expr.UnaryOperator = OpStack.Pop(); CStack.Push(expr); } if (OpStack.Count > 0) o = OpStack.Peek(); } if (OpStack.Count > 0) { OpStack.Pop(); NextCanBe = ExprNext.BExpr; } else NextCanBe = 0; continue; } case Scanner.ValueOf: if (NextCanBe.HasFlag(ExprNext.UExpr)) { Index++; var var = new Variable(); var.Identity = (string)Tokens[Index]; CStack.Push(var); OpStack.Push(new ValueOf()); NextCanBe = ExprNext.BExpr; Index++; continue; } break; case Scanner.AsIs: if (NextCanBe.HasFlag(ExprNext.UExpr)) { Index++; var strL = new StringLiteral(); strL.Value = (string)Tokens[Index]; CStack.Push(strL); OpStack.Push(new AsIs()); NextCanBe = ExprNext.BExpr; Index++; continue; } break; case Scanner.And: case Scanner.Or: case Scanner.Xor: case Scanner.Not: case Scanner.Add: case Scanner.Subtract: case Scanner.Multiply: case Scanner.Divide: case Scanner.Equal: case Scanner.Bigger: case Scanner.BiggerEqual: case Scanner.Smaller: case Scanner.SmallerEqual: case Scanner.NotEqual: { var op = Operator.Parse((string)Tokens[Index]); var o = (OpStack.Count > 0) ? OpStack.Peek() : op; while (OpStack.Count > 0 && op.Level >= o.Level && !(o is Group)) { if (o.IsBinary) { var expr = new BinaryExpression(); expr.Right = CStack.Pop(); expr.BinaryOperator = OpStack.Pop(); expr.Left = CStack.Pop(); CStack.Push(expr); } else { var expr = new UnaryExpression(); expr.Right = CStack.Pop(); expr.UnaryOperator = OpStack.Pop(); CStack.Push(expr); } if (OpStack.Count > 0) o = OpStack.Peek(); } if (CStack.Count == 0 && op is Sub || Diff(CStack, OpStack) && op is Sub) op = new Minus(); // If there was no literal before or previous token was also an operator OpStack.Push(op); NextCanBe = ExprNext.BExpr | ExprNext.UExpr | ExprNext.Literal | ExprNext.Bracket; Index++; continue; } } break; } while (OpStack.Count > 0) { var o = OpStack.Peek(); if (o.IsBinary) { var expr = new BinaryExpression(); expr.Right = CStack.Pop(); expr.BinaryOperator = OpStack.Pop(); expr.Left = CStack.Pop(); CStack.Push(expr); } else { var expr = new UnaryExpression(); expr.Right = CStack.Pop(); expr.UnaryOperator = OpStack.Pop(); CStack.Push(expr); } } return CStack.Pop(); }
Expr ParseExpr() { var OpStack = new Stack <Operator>(); var CStack = new Stack <Expr>(); ExprNext NextCanBe = ExprNext.UExpr | ExprNext.BExpr | ExprNext.Literal | ExprNext.Bracket; while (Index < Tokens.Count) { // token is literal (double, int, bool, string, function call) if (NextCanBe.HasFlag(ExprNext.Literal)) { if (Tokens[Index].isSB) { var stringLiteral = new StringLiteral(); stringLiteral.Value = ((StringBuilder)Tokens[Index]).ToString(); Index++; CStack.Push(stringLiteral); NextCanBe = ExprNext.BExpr; continue; } else if (Tokens[Index].isInt) { var intLiteral = new IntLiteral(); intLiteral.Value = (int)Tokens[Index]; Index++; CStack.Push(intLiteral); NextCanBe = ExprNext.BExpr; continue; } else if (Tokens[Index].isDbl) { var dblLiteral = new DblLiteral(); dblLiteral.Value = (double)Tokens[Index]; NextCanBe = ExprNext.BExpr; Index++; CStack.Push(dblLiteral); continue; } else if (Tokens[Index].isStr && FuncDef.ContainsKey((string)Tokens[Index])) { // If function is exists var function = new ExprFunction(); function.Identity = (string)Tokens[Index]; var P = FuncDef[(string)Tokens[Index]].Parameters.Count; int i = 0; Index++; while (Index < Tokens.Count && i < P) { function.Parameters.Add(ParseExpr()); i++; } if (Index == Tokens.Count && i < P) { throw new RPExeption(29, App.Current.TryFindResource("x_fparnm").ToString(), Line, Column); } CStack.Push(function); NextCanBe = ExprNext.BExpr; continue; } } // if token is not expression either break if (!NextCanBe.HasFlag(ExprNext.UExpr) && !NextCanBe.HasFlag(ExprNext.BExpr) && !NextCanBe.HasFlag(ExprNext.Bracket) || !Tokens[Index].isStr) { break; } // else token is an operator switch ((string)Tokens[Index]) { case Scanner.BracketStart: if (NextCanBe.HasFlag(ExprNext.Bracket)) { Index++; OpStack.Push(new Group()); NextCanBe = ExprNext.UExpr | ExprNext.BExpr | ExprNext.Literal | ExprNext.Bracket; continue; } break; case Scanner.BracketEnd: { Index++; var o = (OpStack.Count > 0) ? OpStack.Peek() : null; while (OpStack.Count > 0 && !(o is Group)) { if (o.IsBinary) { var expr = new BinaryExpression(); expr.BinaryOperator = OpStack.Pop(); if (expr.BinaryOperator.Level >= OpStack.Peek().Level) { expr.Right = CStack.Pop(); expr.Left = CStack.Pop(); } else { expr.Left = CStack.Pop(); expr.Right = CStack.Pop(); } CStack.Push(expr); } else { var expr = new UnaryExpression(); expr.Right = CStack.Pop(); expr.UnaryOperator = OpStack.Pop(); CStack.Push(expr); } if (OpStack.Count > 0) { o = OpStack.Peek(); } } if (OpStack.Count > 0) { OpStack.Pop(); NextCanBe = ExprNext.BExpr; } else { NextCanBe = 0; } continue; } case Scanner.ValueOf: if (NextCanBe.HasFlag(ExprNext.UExpr)) { Index++; var var = new Variable(); var.Identity = (string)Tokens[Index]; CStack.Push(var); OpStack.Push(new ValueOf()); NextCanBe = ExprNext.BExpr; Index++; continue; } break; case Scanner.AsIs: if (NextCanBe.HasFlag(ExprNext.UExpr)) { Index++; var strL = new StringLiteral(); strL.Value = (string)Tokens[Index]; CStack.Push(strL); OpStack.Push(new AsIs()); NextCanBe = ExprNext.BExpr; Index++; continue; } break; case Scanner.And: case Scanner.Or: case Scanner.Xor: case Scanner.Not: case Scanner.Add: case Scanner.Subtract: case Scanner.Multiply: case Scanner.Divide: case Scanner.Equal: case Scanner.Bigger: case Scanner.BiggerEqual: case Scanner.Smaller: case Scanner.SmallerEqual: case Scanner.NotEqual: { var op = Operator.Parse((string)Tokens[Index]); var o = (OpStack.Count > 0) ? OpStack.Peek() : op; while (OpStack.Count > 0 && op.Level >= o.Level && !(o is Group)) { if (o.IsBinary) { var expr = new BinaryExpression(); expr.Right = CStack.Pop(); expr.BinaryOperator = OpStack.Pop(); expr.Left = CStack.Pop(); CStack.Push(expr); } else { var expr = new UnaryExpression(); expr.Right = CStack.Pop(); expr.UnaryOperator = OpStack.Pop(); CStack.Push(expr); } if (OpStack.Count > 0) { o = OpStack.Peek(); } } if (CStack.Count == 0 && op is Sub || Diff(CStack, OpStack) && op is Sub) { op = new Minus(); // If there was no literal before or previous token was also an operator } OpStack.Push(op); NextCanBe = ExprNext.BExpr | ExprNext.UExpr | ExprNext.Literal | ExprNext.Bracket; Index++; continue; } } break; } while (OpStack.Count > 0) { var o = OpStack.Peek(); if (o.IsBinary) { var expr = new BinaryExpression(); expr.Right = CStack.Pop(); expr.BinaryOperator = OpStack.Pop(); expr.Left = CStack.Pop(); CStack.Push(expr); } else { var expr = new UnaryExpression(); expr.Right = CStack.Pop(); expr.UnaryOperator = OpStack.Pop(); CStack.Push(expr); } } return(CStack.Pop()); }