CiExpr ParseRelExpr() { CiExpr left = ParseShiftExpr(); while (See(CiToken.Less) || See(CiToken.LessOrEqual) || See(CiToken.Greater) || See(CiToken.GreaterOrEqual)) { CiToken op = this.CurrentToken; NextToken(); left = new CiBoolBinaryExpr { Left = left, Op = op, Right = ParseShiftExpr() }; } return left; }
CiExpr ParseCondOrExpr() { CiExpr left = ParseCondAndExpr(); while (Eat(CiToken.CondOr)) left = new CiBoolBinaryExpr { Left = left, Op = CiToken.CondOr, Right = ParseCondAndExpr() }; return left; }
CiExpr ParseEqualityExpr() { CiExpr left = ParseRelExpr(); while (See(CiToken.Equal) || See(CiToken.NotEqual)) { CiToken op = this.CurrentToken; NextToken(); left = new CiBoolBinaryExpr { Left = left, Op = op, Right = ParseRelExpr() }; } return left; }
CiExpr ICiExprVisitor.Visit(CiBoolBinaryExpr expr) { CiExpr left = Resolve(expr.Left); CiExpr right = Resolve(expr.Right); CiType type; switch (expr.Op) { case CiToken.CondAnd: case CiToken.CondOr: type = CiBoolType.Value; break; case CiToken.Equal: case CiToken.NotEqual: type = FindCommonType(left, right); break; default: type = CiIntType.Value; break; } expr.Left = Coerce(left, type); expr.Right = Coerce(right, type); CiConstExpr cleft = expr.Left as CiConstExpr; if (cleft != null) { switch (expr.Op) { case CiToken.CondAnd: return (bool) cleft.Value ? expr.Right : new CiConstExpr(false); case CiToken.CondOr: return (bool) cleft.Value ? new CiConstExpr(true) : expr.Right; case CiToken.Equal: case CiToken.NotEqual: CiConstExpr cright = expr.Right as CiConstExpr; if (cright != null) { bool eq = object.Equals(cleft.Value, cright.Value); return new CiConstExpr(expr.Op == CiToken.Equal ? eq : !eq); } break; default: if (expr.Right is CiConstExpr) { int a = GetConstInt(cleft); int b = GetConstInt(expr.Right); bool result; switch (expr.Op) { case CiToken.Less: result = a < b; break; case CiToken.LessOrEqual: result = a <= b; break; case CiToken.Greater: result = a > b; break; case CiToken.GreaterOrEqual: result = a >= b; break; default: return expr; } return new CiConstExpr(result); } break; } } return expr; }