private Expr Unary() { if (Match(TokenType.NOT, TokenType.MINUS)) { Token op = Previous; Expr right = Cast(); if (right is Expr.Literal lit) { var type = new TypeSpecifier { Type = lit.Type, Dimensions = 0 }; if (op.Type == TokenType.NOT) { if (type.IsBool()) { bool value = (bool)lit.Value; return(new Expr.Literal(lit.Type, !value)); } else { throw Error("Trying to invert a non-boolean value"); } } else { if (type.IsInt()) { long value = (long)lit.Value; return(new Expr.Literal(lit.Type, -value)); } else if (type.IsFloat()) { double value = (double)lit.Value; return(new Expr.Literal(lit.Type, -value)); } else { throw Error("Trying to negate a non-numeric value"); } } } return(new Expr.Unary(op, right)); } return(Invoke()); }
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 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); }