2019-09-18 18:59:11 +00:00
|
|
|
const std = @import("std");
|
|
|
|
const tokens = @import("tokens.zig");
|
|
|
|
const Token = tokens.Token;
|
|
|
|
|
2019-09-18 19:53:44 +00:00
|
|
|
pub const NodeList = std.ArrayList(Node);
|
|
|
|
pub const StmtList = std.ArrayList(Stmt);
|
|
|
|
pub const Block = std.ArrayList(Stmt);
|
|
|
|
pub const ExprList = std.ArrayList(Expr);
|
2019-09-18 18:59:11 +00:00
|
|
|
pub const TokenList = std.ArrayList(Token);
|
|
|
|
pub const ParamList = std.ArrayList(ParamDecl);
|
|
|
|
pub const ConstList = std.ArrayList(SingleConst);
|
|
|
|
|
|
|
|
pub const NodeType = enum {
|
|
|
|
Root,
|
|
|
|
FnDecl,
|
|
|
|
ConstDecl,
|
|
|
|
Struct,
|
|
|
|
Enum,
|
|
|
|
Block,
|
|
|
|
Stmt,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const ParamDecl = struct {
|
|
|
|
name: Token,
|
|
|
|
typ: Token,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const MethodData = struct {
|
|
|
|
variable: Token,
|
|
|
|
typ: Token,
|
|
|
|
mutable: bool,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const FnDecl = struct {
|
|
|
|
func_name: Token,
|
|
|
|
params: ParamList,
|
|
|
|
return_type: Token,
|
|
|
|
body: StmtList,
|
|
|
|
method: ?*MethodData,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const SingleConst = struct {
|
|
|
|
name: Token,
|
|
|
|
expr: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const BinaryExpr = struct {
|
|
|
|
left: *Expr,
|
|
|
|
op: Token,
|
|
|
|
right: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const UnaryExpr = struct {
|
|
|
|
op: Token,
|
|
|
|
right: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
// looks like a BinaryExpr, but is not a BinaryExpr
|
|
|
|
pub const LogicalExpr = struct {
|
|
|
|
left: *Expr,
|
|
|
|
op: Token,
|
|
|
|
right: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const LiteralExpr = union(enum) {
|
|
|
|
Bool: bool,
|
|
|
|
Integer: []const u8,
|
|
|
|
Float: []const u8,
|
|
|
|
String: []const u8,
|
|
|
|
Array: ExprList,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const AssignExpr = struct {
|
|
|
|
name: Token,
|
|
|
|
value: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const ExprType = enum {
|
|
|
|
Assign,
|
|
|
|
|
|
|
|
// vardecls as expressions is a hack
|
|
|
|
VarDecl,
|
|
|
|
|
|
|
|
Binary,
|
|
|
|
Unary,
|
|
|
|
Logical,
|
|
|
|
Literal,
|
|
|
|
Variable,
|
|
|
|
Call,
|
|
|
|
Struct,
|
|
|
|
|
|
|
|
Grouping,
|
|
|
|
Get,
|
|
|
|
Set,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const VarDecl = struct {
|
|
|
|
assign: AssignExpr,
|
|
|
|
mutable: bool = false,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const CallExpr = struct {
|
|
|
|
callee: *Expr,
|
|
|
|
paren: Token,
|
|
|
|
arguments: ExprList,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const StructInit = struct {
|
|
|
|
field: Token,
|
|
|
|
expr: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const StructInitList = std.ArrayList(StructInit);
|
|
|
|
|
|
|
|
pub const StructExpr = struct {
|
|
|
|
name: Token,
|
|
|
|
inits: StructInitList,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const GetExpr = struct {
|
|
|
|
struc: *Expr,
|
|
|
|
name: Token,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const SetExpr = struct {
|
|
|
|
struc: *Expr,
|
|
|
|
field: Token,
|
|
|
|
value: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const Expr = union(ExprType) {
|
|
|
|
Assign: AssignExpr,
|
|
|
|
VarDecl: VarDecl,
|
|
|
|
|
|
|
|
Binary: BinaryExpr,
|
|
|
|
Unary: UnaryExpr,
|
|
|
|
Logical: LogicalExpr,
|
|
|
|
Literal: LiteralExpr,
|
|
|
|
Struct: StructExpr,
|
|
|
|
|
|
|
|
Variable: Token,
|
|
|
|
Grouping: *Expr,
|
|
|
|
Call: CallExpr,
|
|
|
|
|
|
|
|
Get: GetExpr,
|
|
|
|
Set: SetExpr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const IfStmt = struct {
|
|
|
|
condition: *Expr,
|
|
|
|
then_branch: Block,
|
|
|
|
else_branch: ?Block,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const LoopStmt = struct {
|
|
|
|
condition: ?*Expr,
|
|
|
|
then_branch: Block,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const ForStmt = struct {
|
|
|
|
index: ?Token,
|
|
|
|
value: Token,
|
|
|
|
array: Token,
|
|
|
|
block: Block,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const Stmt = union(enum) {
|
|
|
|
Expr: *Expr,
|
|
|
|
Println: *Expr,
|
|
|
|
|
|
|
|
If: IfStmt,
|
|
|
|
Loop: LoopStmt,
|
|
|
|
For: ForStmt,
|
|
|
|
|
|
|
|
Return: ReturnStmt,
|
|
|
|
|
|
|
|
pub const ReturnStmt = struct {
|
|
|
|
keyword: Token,
|
|
|
|
value: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub fn mkPrintln(allocator: *std.mem.Allocator, expr: *Expr) !*Stmt {
|
|
|
|
var stmt = try allocator.create(Stmt);
|
|
|
|
stmt.* = Stmt{ .Println = expr };
|
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mkIfStmt(
|
|
|
|
allocator: *std.mem.Allocator,
|
|
|
|
condition: *Expr,
|
|
|
|
then: Block,
|
|
|
|
else_branch: ?Block,
|
|
|
|
) !*Stmt {
|
|
|
|
var stmt = try allocator.create(Stmt);
|
|
|
|
stmt.* = Stmt{
|
|
|
|
.If = IfStmt{
|
|
|
|
.condition = condition,
|
|
|
|
.then_branch = then,
|
|
|
|
.else_branch = else_branch,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mkLoop(
|
|
|
|
allocator: *std.mem.Allocator,
|
|
|
|
condition: ?*Expr,
|
|
|
|
then: Block,
|
|
|
|
) !*Stmt {
|
|
|
|
var stmt = try allocator.create(Stmt);
|
|
|
|
stmt.* = Stmt{
|
|
|
|
.Loop = LoopStmt{
|
|
|
|
.condition = condition,
|
|
|
|
.then_branch = then,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mkFor(allocator: *std.mem.Allocator, index: ?Token, value: Token, array: Token, block: Block) !*Stmt {
|
|
|
|
var stmt = try allocator.create(Stmt);
|
|
|
|
stmt.* = Stmt{
|
|
|
|
.For = ForStmt{
|
|
|
|
.index = index,
|
|
|
|
.value = value,
|
|
|
|
.array = array,
|
|
|
|
.block = block,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mkReturn(allocator: *std.mem.Allocator, tok: Token, value: *Expr) !*Stmt {
|
|
|
|
var stmt = try allocator.create(Stmt);
|
|
|
|
stmt.* = Stmt{
|
|
|
|
.Return = ReturnStmt{
|
|
|
|
.keyword = tok,
|
|
|
|
.value = value,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
return stmt;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const FieldList = std.ArrayList(StructField);
|
|
|
|
|
|
|
|
pub const StructField = struct {
|
|
|
|
name: Token,
|
|
|
|
typ: Token,
|
|
|
|
|
|
|
|
mutable: bool = false,
|
|
|
|
public: bool = false,
|
|
|
|
mutable_outside: bool = false,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const Struct = struct {
|
|
|
|
name: Token,
|
|
|
|
fields: FieldList,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const Enum = struct {
|
|
|
|
name: Token,
|
|
|
|
fields: TokenList,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const Node = union(NodeType) {
|
|
|
|
Root: NodeList,
|
|
|
|
FnDecl: FnDecl,
|
|
|
|
ConstDecl: ConstList,
|
|
|
|
Struct: Struct,
|
|
|
|
Enum: Enum,
|
|
|
|
|
|
|
|
Block: StmtList,
|
|
|
|
|
|
|
|
Stmt: *Stmt,
|
|
|
|
|
|
|
|
pub fn mkRoot(allocator: *std.mem.Allocator) !*Node {
|
|
|
|
var node = try allocator.create(Node);
|
|
|
|
node.* = Node{ .Root = NodeList.init(allocator) };
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2019-09-20 16:54:52 +00:00
|
|
|
pub fn mkFnDecl(
|
|
|
|
allocator: *std.mem.Allocator,
|
|
|
|
name: Token,
|
|
|
|
params: ParamList,
|
|
|
|
return_type: Token,
|
|
|
|
block: StmtList,
|
|
|
|
method: ?*MethodData,
|
|
|
|
) !*Node {
|
|
|
|
var node = try allocator.create(Node);
|
|
|
|
|
|
|
|
node.* = Node{
|
|
|
|
.FnDecl = FnDecl{
|
|
|
|
.func_name = name,
|
|
|
|
.params = params,
|
|
|
|
.return_type = return_type,
|
|
|
|
.body = block,
|
|
|
|
.method = method,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2019-09-18 18:59:11 +00:00
|
|
|
pub fn mkStructDecl(allocator: *std.mem.Allocator, name: Token, fields: FieldList) !*Node {
|
|
|
|
var node = try allocator.create(Node);
|
|
|
|
node.* = Node{
|
|
|
|
.Struct = Struct{
|
|
|
|
.name = name,
|
|
|
|
.fields = fields,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mkEnumDecl(allocator: *std.mem.Allocator, name: Token, fields: TokenList) !*Node {
|
|
|
|
var node = try allocator.create(Node);
|
|
|
|
node.* = Node{
|
|
|
|
.Enum = Enum{
|
|
|
|
.name = name,
|
|
|
|
.fields = fields,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
};
|