/// <summary> /// The shunting yard algorithm that processes a postfix list of expressions/operators. /// </summary> /// <param name="context"></param> /// <param name="parser"></param> /// <param name="stack"></param> /// <returns></returns> public static Expr ProcessShuntingYardList(Context context, Parser.Parser parser, List <object> stack) { int index = 0; Expr finalExp = null; // Shunting yard algorithm handles POSTFIX operations. while (index < stack.Count && stack.Count > 0) { // Keep moving forward to the first operator * - + / && that is found // This is a postfix algorithm so it works by creating an expression // from the last 2 items behind an operator. if (!(stack[index] is TokenData)) { index++; continue; } // At this point... we hit an operator // So get the last 2 items on the stack ( they have to be expressions ) // left is 2 behind current position // right is 1 behind current position var left = stack[index - 2] as Expr; var right = stack[index - 1] as Expr; TokenData tdata = stack[index] as TokenData; Token top = tdata.Token; Operator op = Operators.ToOp(top.Text); Expr exp = null; if (Operators.IsMath(op)) { exp = Exprs.Binary(left, op, right, tdata); } else if (Operators.IsConditional(op)) { exp = Exprs.Condition(left, op, right, tdata); } else if (Operators.IsCompare(op)) { exp = Exprs.Compare(left, op, right, tdata); } parser.SetupContext(exp, tdata); stack.RemoveRange(index - 2, 2); index = index - 2; stack[index] = exp; index++; } finalExp = stack[0] as Expr; return(finalExp); }
/// <summary> /// run step 123. /// </summary> /// <returns></returns> public override Expr Parse() { var startToken = _tokenIt.NextToken; var conditionToken = startToken; var assignToken = startToken; var incToken = startToken; var loopToken = startToken; var varToken = startToken; _tokenIt.ExpectIdText("repeat"); Expr varnameExpr = null; Expr startVal = null; Expr endVal = null; Expr incVal = null; Operator op = Operator.LessThanEqual; // Case 1: repeat to 10 if (_tokenIt.NextToken.Token.Text == "to") { var result = ParseTo(); startVal = Exprs.Const(new LNumber(1.0), startToken); op = result.Item1; endVal = result.Item2; incVal = result.Item3; } // Case 2: repeat 1 to 10 else if (_tokenIt.NextToken.Token.Kind == TokenKind.LiteralNumber) { var num = _tokenIt.ExpectNumber(); var result = ParseTo(); startVal = Exprs.Const(new LNumber(num), startToken); op = result.Item1; endVal = result.Item2; incVal = result.Item3; } // Case 3: repeat ndx to 10 else if (_tokenIt.NextToken.Token.Kind == TokenKind.Ident) { var variableName = _tokenIt.ExpectId(); varnameExpr = Exprs.Ident(variableName, _tokenIt.LastToken); if (_tokenIt.NextToken.Token.Type == TokenTypes.Assignment) { _tokenIt.Advance(); // Upto "to" startVal = ParseExpr(_terminatorForTo); } else { startVal = Exprs.Const(new LNumber(0), startToken); } var result = ParseTo(); op = result.Item1; endVal = result.Item2; incVal = result.Item3; } // auto-create variable name. if (varnameExpr == null) { varnameExpr = Exprs.Ident("it", _tokenIt.LastToken); } // Now setup the stmts var start = Exprs.Assign(true, varnameExpr, startVal, varToken); var condition = Exprs.Compare(varnameExpr, op, endVal, varToken); var incExp = Exprs.Unary(varnameExpr.ToQualifiedName(), incVal, 0, Operator.PlusEqual, incToken); var incStmt = Exprs.Assign(false, varnameExpr, incExp, assignToken); var loopStmt = Exprs.For(start, condition, incStmt, loopToken); ParseBlock(loopStmt as BlockExpr); return(loopStmt); }