private Expr Relational() { var expr = Additive(); while (Match(TokenType.GREATER, TokenType.GREATER_EQUAL, TokenType.LESS, TokenType.LESS_EQUAL)) { Token op = Previous; Expr right = Additive(); if (expr is Expr.Literal l && right is Expr.Literal r) { var typel = new TypeSpecifier { Type = l.Type, Dimensions = 0 }; var typer = new TypeSpecifier { Type = r.Type, Dimensions = 0 }; if (typer.ImplicitCastableTo(typel)) { if (typel.Type == TypeEnum.BOOL) { throw Error($"Boolean values are not comparable with '{op.Type}'"); } if (typel.IsInt()) { return(CompareLiterals <long>(op.Type, l.Value, r.Value)); } else if (typel.IsFloat()) { return(CompareLiterals <double>(op.Type, l.Value, r.Value)); } else { throw Error("Something wrong with literal comparison"); } } else { throw Error($"'{typer}' not implicitly castable to '{typel}'"); } } expr = new Expr.Binary(expr, op, right); } return(expr); }
private Expr Equality() { var expr = Relational(); while (Match(TokenType.NOT_EQUAL, TokenType.EQUAL)) { Token op = Previous; Expr right = Relational(); if (expr is Expr.Literal l && right is Expr.Literal r) { var typel = new TypeSpecifier { Type = l.Type, Dimensions = 0 }; var typer = new TypeSpecifier { Type = r.Type, Dimensions = 0 }; if (typer.ImplicitCastableTo(typel)) { if (op.Type == TokenType.NOT_EQUAL) { return(new Expr.Literal(TypeEnum.BOOL, !l.Value.Equals(r.Value))); } else { return(new Expr.Literal(TypeEnum.BOOL, l.Value.Equals(r.Value))); } } else { throw Error($"'{typer}' not implicitly castable to '{typel}'"); } } expr = new Expr.Binary(expr, op, right); } return(expr); }
private Expr Multiplicative() { var expr = Cast(); while (Match(TokenType.DIV, TokenType.MULT)) { Token op = Previous; Expr right = Cast(); if (expr is Expr.Literal l && right is Expr.Literal r) { var typel = new TypeSpecifier { Type = l.Type, Dimensions = 0 }; var typer = new TypeSpecifier { Type = r.Type, Dimensions = 0 }; if (typer.ImplicitCastableTo(typel)) { if (typel.IsInt()) { long one = (long)l.Value; long two = (long)r.Value; if (op.Type == TokenType.DIV) { return(new Expr.Literal(typel.Type, one / two)); } else { return(new Expr.Literal(typel.Type, one * two)); } } else if (typel.IsFloat()) { double one = (double)l.Value; double two = (double)r.Value; if (op.Type == TokenType.DIV) { return(new Expr.Literal(typel.Type, one / two)); } else { return(new Expr.Literal(typel.Type, one * two)); } } else { throw Error("Something wrong on Multiplicative"); } } else { throw Error($"'{typer}' not implicitly castable to '{typel}'"); } } expr = new Expr.Binary(expr, op, right); } return(expr); }