vig/src/ast.zig

104 lines
2.1 KiB
Zig

const tokens = @import("tokens.zig");
const Token = tokens.Token;
pub const ExprType = enum {
Unary,
Binary,
Grouping,
Number,
Bool,
Nil,
String,
};
pub const Expr = union(ExprType) {
Unary: UnaryExpr,
Binary: BinaryExpr,
Grouping: Grouping,
Number: Number,
Bool: Bool,
Nil: Nil,
String: String,
};
pub const UnaryExpr = struct {
operator: Token,
right: *Expr,
};
pub fn mkUnary(operator: Token, right: *Expr) Expr {
return Expr{
.Unary = UnaryExpr{
.operator = operator,
.right = right,
},
};
}
pub const BinaryExpr = struct {
left: *Expr,
operator: Token,
right: *Expr,
};
pub fn mkBinary(left: *Expr, operator: Token, right: *Expr) Expr {
return Expr{
.Binary = BinaryExpr{
.left = left,
.operator = operator,
.right = right,
},
};
}
pub const Grouping = struct {
expression: *Expr,
};
pub fn mkGrouping(expression: *Expr) Expr {
return Expr{
.Grouping = Grouping{
.expression = expression,
},
};
}
/// Represents the default number literals in V.
pub const NumberType = enum {
Integer32,
Integer64,
Unsigned32,
Unsigned64,
Float32,
Float64,
};
/// "translation" of V number types to Zig number types for nicer
/// representation.
pub const Number = union(NumberType) {
Integer32: i32,
Integer64: i64,
Unsigned32: u32,
Unsigned64: u64,
Float32: f32,
Float64: f64,
};
pub fn mkNum(comptime T: type, num: T) Expr {
var expr = switch (T) {
i32 => Expr{ .Number = Number{ .Integer32 = num } },
i64 => Expr{ .Number = Number{ .Integer64 = num } },
u32 => Expr{ .Number = Number{ .Unsigned32 = num } },
u64 => Expr{ .Number = Number{ .Unsigned64 = num } },
f32 => Expr{ .Number = Number{ .Float32 = num } },
f64 => Expr{ .Number = Number{ .Float64 = num } },
else => unreachable,
};
return expr;
}
pub const Bool = bool;
pub const Nil = void;
pub const String = []u8;