Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions examples/if.sub
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
fn main() void {
print("Helloworld", "maman", "Harold", "Reese",);
fn_call("I like to play with people");
var sub: i32 = "Bonjour";
if "bonjour" {
print("in if statement");
foo("in foo statement");
if "maman" {
bar("foo", "bar", "baz",);
var inner_var: Foo = "bonsoir";
} elseif "else_expr" {
fn_else("in_fn_else",);
} else {
print("without condition");
}
} elseif best("else_if_expr") {
bazz("in bazz");
fuzz("in bazz");
} else {
var else_inner: f32 = "for now, expr can just be strings";
}
}
103 changes: 89 additions & 14 deletions src/ast.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const std = @import("std");

const panic = std.debug.panic;
const assert = std.debug.assert;

//////////// Program Block

Expand All @@ -13,7 +14,7 @@ pub const Ast = struct {

pub fn print(ast: Ast) void {
for (ast.decls.items) |decl| {
decl.print();
decl.print(0);
std.debug.print("\n\n", .{});
}
}
Expand Down Expand Up @@ -43,9 +44,9 @@ pub const ProgramDecl = union(ProgramDeclTag) {
} };
}

pub fn print(self: Self) void {
pub fn print(self: Self, nindent: usize) void {
switch (self) {
.fn_decl => |fn_decl| fn_decl.print(),
.fn_decl => |fn_decl| fn_decl.print(nindent),
}
}
};
Expand All @@ -58,20 +59,20 @@ const FnDecl = struct {
body: std.ArrayList(Stmt),
return_type: []const u8,

pub fn print(self: Self) void {
pub fn print(self: Self, indent: usize) void {
print_nindent(indent);
std.debug.print("fn {s}(", .{self.name});
for (self.args.items) |arg| {
std.debug.print("{s}, ", .{arg});
}

std.debug.print(") {s} {{\n", .{self.return_type});
const indent = 1;

for (self.body.items) |stmt| {
print_nindent(indent);
stmt.print();
stmt.print(indent + 1);
}

print_nindent(indent);
std.debug.print("}}", .{});
}
};
Expand Down Expand Up @@ -147,6 +148,7 @@ const VarDeclExpr = struct {
const StmtTag = enum {
assign,
no_assign,
if_,
};

//////////// Stmt structs
Expand All @@ -155,6 +157,7 @@ pub const Stmt = union(StmtTag) {

assign: AssignStmt,
no_assign: NoAssignStmt,
if_: IfStmt,

pub fn create_assign(var_: ?[]const u8, value: Expr) Stmt {
return .{ .assign = .{
Expand All @@ -163,12 +166,29 @@ pub const Stmt = union(StmtTag) {
} };
}

pub fn print(self: Self) void {
pub fn create_if(
if_eval: Expr,
if_body: std.ArrayList(Stmt),
elseif_evals: std.ArrayList(Expr),
elseif_thens: std.ArrayList(std.ArrayList(Stmt)),
else_then: ?std.ArrayList(Stmt),
) Stmt {
return .{ .if_ = .{
.if_eval = if_eval,
.if_body = if_body,
.elseif_evals = elseif_evals,
.elseif_thens = elseif_thens,
.else_then = else_then,
} };
}

pub fn print(self: Self, indent: usize) void {
switch (self) {
.assign => |assign| assign.print(),
.no_assign => |no_assign| no_assign.print(),
.assign => |assign| assign.print(indent),
.no_assign => |no_assign| no_assign.print(indent),
.if_ => |if_| if_.print(indent),
}
std.debug.print(";\n", .{});
std.debug.print("\n", .{});
}
};

Expand All @@ -179,23 +199,78 @@ const AssignStmt = struct {
type_: []const u8,
value: Expr,

pub fn print(self: Self) void {
pub fn print(self: Self, indent: usize) void {
print_nindent(indent);
std.debug.print("var {s}: {s} = ", .{ self.var_, self.type_ });
self.value.print();
std.debug.print(";", .{});
}
};

const NoAssignStmt = struct {
const Self = @This();
value: Expr,

pub fn print(self: Self) void {
pub fn print(self: Self, indent: usize) void {
print_nindent(indent);
self.value.print();
std.debug.print(";", .{});
}
};

const IfStmt = struct {
const Self = @This();

if_eval: Expr,
if_body: std.ArrayList(Stmt),

elseif_evals: std.ArrayList(Expr),
elseif_thens: std.ArrayList(std.ArrayList(Stmt)),

else_then: ?std.ArrayList(Stmt),

pub fn print(self: Self, indent: usize) void {
print_nindent(indent);
std.debug.print("if ", .{});
self.if_eval.print();
std.debug.print(" {{\n", .{});
for (self.if_body.items) |stmt| {
stmt.print(indent + 1);
}
print_nindent(indent);
std.debug.print("}}", .{});

assert(self.elseif_evals.items.len == self.elseif_thens.items.len);
for (0..self.elseif_evals.items.len) |i| {
const eval = self.elseif_evals.items[i];
const then = self.elseif_thens.items[i];

std.debug.print(" elseif ", .{});
eval.print();
std.debug.print(" {{\n", .{});

for (then.items) |then_stmt| {
then_stmt.print(indent + 1);
}
print_nindent(indent);
std.debug.print("}}", .{});
}

if (self.else_then != null) {
const else_then = self.else_then.?;

std.debug.print(" else {{\n", .{});
for (else_then.items) |then_stmt| {
then_stmt.print(indent + 1);
}
print_nindent(indent);
std.debug.print("}}", .{});
}
}
};

fn print_nindent(n: usize) void {
for (0..n) |_| {
std.debug.print(" ", .{});
std.debug.print(" ", .{});
}
}
12 changes: 8 additions & 4 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ const Parser = parser_pkg.Parser;

const LIMIT = 1024 * 10;

const assert = std.debug.assert;

pub fn main(init: std.process.Init) !void {
_ = ast_pkg;
const io = init.io;
const alloc = std.heap.page_allocator;

const args = try init.minimal.args.toSlice(alloc);
assert(args.len == 2);
const io = init.io;

const current_dir = std.Io.Dir.cwd();
const file_path = "examples/helloworld.sub";
const file_path = args[1];
const content: []const u8 = try current_dir.readFileAlloc(
io,
file_path,
Expand All @@ -25,7 +29,7 @@ pub fn main(init: std.process.Init) !void {

var l = Lexer.init(
content,
"main.sub",
file_path,
);
var parser = Parser.init(&l, alloc);
const ast = try parser.parse();
Expand Down
65 changes: 60 additions & 5 deletions src/parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,25 @@ pub const Parser = struct {
while (l.token != .cbrace) {
const stmt = try parse_stmt(l, alloc);
try body.append(alloc, stmt);
l.eat(.semicolon);
// l.eat(.semicolon);
}
l.eat(.cbrace);

return ProgramDecl.create_fn(id, args, body, return_type);
}

fn parse_stmt(l: *Lexer, alloc: Allocator) !Stmt {
fn parse_stmt(l: *Lexer, alloc: Allocator) error{OutOfMemory}!Stmt {
if (l.token == .var_) {
// var declaration
return parse_var_decl_stmt(l, alloc);
const stmt = parse_var_decl_stmt(l, alloc);
l.eat(.semicolon);
return stmt;
} else if (l.token == .if_) {
return parse_if_stmt(l, alloc);
} else {
return parse_no_var_decl_stmt(l, alloc);
const stmt = parse_no_var_decl_stmt(l, alloc);
l.eat(.semicolon);
return stmt;
}
}

Expand All @@ -119,6 +125,56 @@ pub const Parser = struct {
} };
}

fn parse_if_stmt(l: *Lexer, alloc: Allocator) !Stmt {
l.eat(.if_);
const if_eval = try parse_expr(l, alloc);
var if_body: std.ArrayList(Stmt) = .empty;
l.eat(.obrace);
while (l.token != .cbrace) {
const stmt = try parse_stmt(l, alloc);
try if_body.append(alloc, stmt);
}
l.eat(.cbrace);
var elseif_evals: std.ArrayList(Expr) = .empty;
var elseif_thens: std.ArrayList(std.ArrayList(Stmt)) = .empty;

while (l.token == .elseif) {
l.eat(.elseif);
const eval = try parse_expr(l, alloc);

var then: std.ArrayList(Stmt) = .empty;
l.eat(.obrace);
while (l.token != .cbrace) {
const stmt = try parse_stmt(l, alloc);
try then.append(alloc, stmt);
}
l.eat(.cbrace);
try elseif_evals.append(alloc, eval);
try elseif_thens.append(alloc, then);
}

var else_then: ?std.ArrayList(Stmt) = null;

if (l.token == .else_) {
l.eat(.else_);
l.eat(.obrace);
else_then = .empty;
while (l.token != .cbrace) {
const stmt = try parse_stmt(l, alloc);
try else_then.?.append(alloc, stmt);
}
l.eat(.cbrace);
}

return Stmt.create_if(
if_eval,
if_body,
elseif_evals,
elseif_thens,
else_then,
);
}

fn parse_expr(l: *Lexer, alloc: Allocator) error{OutOfMemory}!Expr {
if (l.token == .id) {
const next_l = l.nextl();
Expand All @@ -129,7 +185,6 @@ pub const Parser = struct {
} else if (l.token == .str) {
return parse_str(l);
}

panic("parse_expr panics with {}, name: {s}", .{ l.token, l.name.as_str(l.content) });
}

Expand Down
Loading