private static AstFor ParseForIn(TokenStream tks) { var si = tks.SourceInfo; tks.Expect(TokenType.For); var ident = tks.Expect(TokenType.Ident).StringValue; tks.Expect(TokenType.In); var @from = ParseExpression(tks); tks.Expect(TokenType.DotDot); var to = ParseExpression(tks); var opTk = tks.Accept(TokenType.Plus, TokenType.Minus); var updateOp = opTk?.Type ?? TokenType.Plus; tks.Expect(TokenType.LCurBracket); var body = ParseBody(tks); tks.Expect(TokenType.RCurBracket); var pre = new AstDeclaration(si, ident, null, @from); var condOp = (updateOp == TokenType.Plus) ? TokenType.LessThanEquals : TokenType.GreaterThanEquals; var itrId = new AstIdent(si, ident); var cond = new AstBinaryOp(si, itrId, condOp, to); var update_ = new AstBinaryOp(si, itrId, updateOp, new AstNumber(si, 1)); var update = new AstAssign(si, itrId, update_); return(new AstFor(si, new List <AstNode> { pre }, cond, new List <AstExpression> { update }, body)); }
private static AstExpression ParseBinaryOpHelper(TokenStream tks, AstExpression lhs, int minPrec) { var si = tks.SourceInfo; var binOps = BinaryOpPrec.Select(kvp => kvp.Key).ToArray(); while (true) { var op = tks.Current; var thisPrec = GetBinOpPrec(op); if (thisPrec < minPrec) { return(lhs); } tks.ThrowIfTokenIsNotIn(binOps); tks.Advance(); var rhs = ParseUnaryOp(tks); var next = tks.Current; var nextPrec = GetBinOpPrec(next); if (thisPrec < nextPrec || (thisPrec == nextPrec && IsBinOpRightAssoc(op))) { rhs = ParseBinaryOpHelper(tks, rhs, thisPrec + 1); } lhs = new AstBinaryOp(si, lhs, op.Type, rhs); } }