summaryrefslogtreecommitdiff
path: root/src/parser.zig
diff options
context:
space:
mode:
authorNic Gaffney <gaffney_nic@protonmail.com>2024-08-12 00:44:26 -0500
committerNic Gaffney <gaffney_nic@protonmail.com>2024-08-12 00:44:26 -0500
commitcf80bb7f1b6fb4ee1d08d3d6850966b4951274b5 (patch)
treeb7521e70e2e921aef64f58ca2ce04de89f408c8c /src/parser.zig
parent013086f9c55e33f7bfcfd775c8b9d03fb2311de4 (diff)
downloadcalico-cf80bb7f1b6fb4ee1d08d3d6850966b4951274b5.tar.gz
Calling functions and Function args now works.
You can also import functions now.
Diffstat (limited to 'src/parser.zig')
-rw-r--r--src/parser.zig184
1 files changed, 164 insertions, 20 deletions
diff --git a/src/parser.zig b/src/parser.zig
index 08f098c..2e6bd85 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -16,8 +16,13 @@ const ParsingError = error{
UnexpectedEOF,
ExpectedToken,
OutOfMemory,
+ TokenIteratorOnly,
};
+fn errcast(err: anytype) ParsingError {
+ return err[0];
+}
+
pub const Node = union(enum) {
Expr: NodeExpr,
Stmt: NodeStmt,
@@ -84,7 +89,8 @@ pub const NodeStmt = struct {
const blockChildren = map(Node, NodeStmt, block, NodeStmt.asNode);
for (blockChildren) |child| try childrenArray.append(child);
},
- .function => |fun| try childrenArray.append(fun.block.*.asNode()),
+ .function => |fun| if (fun.block == null) {} else try childrenArray.append(fun.block.?.asNode()),
+ .expr => |expr| try childrenArray.append(expr.asNode()),
}
return try childrenArray.toOwnedSlice();
}
@@ -126,7 +132,9 @@ pub const Parser = struct {
const children = try node.children(self.allocator);
defer self.allocator.free(children);
for (children) |child| try self.dinitHelper(child.Stmt);
- self.allocator.destroy(fun.block);
+ self.allocator.free(fun.args);
+ if (fun.block != null)
+ self.allocator.destroy(fun.block.?);
},
else => {},
}
@@ -154,12 +162,39 @@ pub const Parser = struct {
},
.ident => {
const ident = (try self.tokens.consume(.ident)).?;
+ if (tok.checkType(self.tokens.peek().?, .openParen)) {
+ _ = try self.tokens.consume(.openParen);
+
+ break :blk ExprKind{
+ .call = .{
+ .ident = ident,
+ .args = innerblk: {
+ var argExprs = std.ArrayList(NodeExpr).init(self.allocator);
+ while (!tok.checkType(self.tokens.peek().?, .closeParen)) {
+ try argExprs.append(try self.parseExpr());
+ if (tok.checkType(self.tokens.peek().?, .closeParen)) break;
+ _ = try self.tokens.consume(.comma);
+ }
+ _ = try self.tokens.consume(.closeParen);
+
+ break :innerblk try argExprs.toOwnedSlice();
+ },
+ },
+ };
+ }
typ = TypeIdent{
.ident = "i32",
.list = false,
};
break :blk ExprKind{ .ident = ident };
},
+ .stringLit => {
+ typ = TypeIdent{
+ .ident = "[u8]",
+ .list = true,
+ };
+ break :blk ExprKind{ .stringLit = (try self.tokens.consume(.stringLit)).? };
+ },
else => break :blk ParsingError.InvalidExpression,
};
};
@@ -177,22 +212,67 @@ pub const Parser = struct {
.exit => try self.parseExit(),
.constant => try self.parseConstant(),
.variable => try self.parseVariable(),
- .ident => try self.parseAssign(),
- .fun => try self.parseFunc(),
- else => ParsingError.InvalidStatement,
+ .ident => blk: {
+ if (!tok.checkType(self.tokens.peekAhead(1).?, .openParen))
+ break :blk try self.parseAssign();
+ break :blk try self.parseExprStmt();
+ },
+ .fun => try self.parseFunc(false),
+ .import => try self.parseFunc(true),
+ else => self.parseExprStmt(),
+ };
+ }
+
+ fn parseExprStmt(self: *Parser) ParsingError!NodeStmt {
+ const kind: StmtKind = StmtKind{ .expr = try self.parseExpr() };
+ _ = try self.tokens.consume(.semiCol);
+ return NodeStmt{
+ .id = self.reserveId(),
+ .symtable = self.top,
+ .kind = kind,
};
}
- fn parseFunc(self: *Parser) ParsingError!NodeStmt {
+ fn parseFunc(self: *Parser, external: bool) ParsingError!NodeStmt {
+ if (external) _ = try self.tokens.consume(.import);
var typ: ?TypeIdent = null;
_ = try self.tokens.consume(.fun);
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.openParen);
- //TODO: Argument Parsing
+ var args = std.ArrayList(FunctionArg).init(self.allocator);
+ defer args.deinit();
+ while (!tok.checkType(self.tokens.peek().?, .closeParen)) {
+ const argIdent: Token = (try self.tokens.consume(.ident)).?;
+ _ = try self.tokens.consume(.colon);
+ const argTypIdent: TypeIdent = try self.parseType();
+ const funcArg: FunctionArg = .{
+ .ident = argIdent.ident,
+ .typ = argTypIdent,
+ };
+ try args.append(funcArg);
+ if (!tok.checkType(self.tokens.peek().?, .comma)) break;
+ _ = try self.tokens.consume(.comma);
+ }
_ = try self.tokens.consume(.closeParen);
if (tok.checkType(self.tokens.peek().?, .arrow)) {
self.tokens.skip();
- typ = TypeIdent{ .ident = (try self.tokens.consume(.ident)).?.ident, .list = false };
+ typ = try self.parseType();
+ }
+
+ if (external) {
+ _ = try self.tokens.consume(.semiCol);
+ return NodeStmt{
+ .id = self.reserveId(),
+ .kind = StmtKind{
+ .function = .{
+ .ident = ident,
+ .args = try args.toOwnedSlice(),
+ .retType = typ,
+ .block = null,
+ },
+ },
+ .symtable = self.top,
+ };
}
const block = try self.allocator.create(NodeStmt);
@@ -201,7 +281,7 @@ pub const Parser = struct {
const kind = StmtKind{
.function = .{
.ident = ident,
- .args = &[_]TypeIdent{},
+ .args = try args.toOwnedSlice(),
.retType = typ,
.block = block,
},
@@ -214,11 +294,14 @@ pub const Parser = struct {
};
}
- fn parseBlock(self: *Parser) !NodeStmt {
+ fn parseBlock(self: *Parser) ParsingError!NodeStmt {
_ = try self.tokens.consume(.openBrace);
var stmtArr = std.ArrayList(NodeStmt).init(self.allocator);
+ const child = try self.top.makeChild();
+ self.top = child;
while (!tok.checkType(self.tokens.peek().?, .closeBrace))
try stmtArr.append(try self.parseStmt());
+ self.top = self.top.parent().?;
_ = try self.tokens.consume(.closeBrace);
const kind = StmtKind{
.block = try stmtArr.toOwnedSlice(),
@@ -227,11 +310,11 @@ pub const Parser = struct {
return NodeStmt{
.id = self.reserveId(),
.kind = kind,
- .symtable = try self.top.makeChild(),
+ .symtable = child,
};
}
- fn parseAssign(self: *Parser) !NodeStmt {
+ fn parseAssign(self: *Parser) ParsingError!NodeStmt {
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.equal);
const expr = try self.parseExpr();
@@ -250,7 +333,7 @@ pub const Parser = struct {
}
fn parseExit(self: *Parser) ParsingError!NodeStmt {
- _ = try self.tokens.consume(.exit);
+ _ = self.tokens.consume(.exit) catch |err| return errcast(.{err});
const expr = try self.parseExpr();
_ = try self.tokens.consume(.semiCol);
const kind = StmtKind{ .exit = expr };
@@ -261,8 +344,17 @@ pub const Parser = struct {
};
}
- fn parseVariable(self: *Parser) !NodeStmt {
+ fn parseVariable(self: *Parser) ParsingError!NodeStmt {
_ = try self.tokens.consume(.variable);
+ var typ: TypeIdent = undefined;
+ if (self.tokens.consume(.colon)) |_| {
+ typ = .{
+ .ident = (try self.tokens.consume(.ident)).?.ident,
+ .list = false,
+ };
+ } else |err| {
+ if (err != tok.TokenizeError.ExpectedToken) return errcast(.{err});
+ }
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.equal);
const expr = try self.parseExpr();
@@ -270,7 +362,13 @@ pub const Parser = struct {
const kind = StmtKind{
.defVar = NodeVar{
.ident = ident,
- .expr = expr,
+ .expr = NodeExpr{
+ .typ = typ,
+ .id = expr.id,
+ .kind = expr.kind,
+ .isConst = expr.isConst,
+ .symtable = expr.symtable,
+ },
},
};
return NodeStmt{
@@ -280,16 +378,46 @@ pub const Parser = struct {
};
}
- fn parseConstant(self: *Parser) !NodeStmt {
+ fn parseType(self: *Parser) ParsingError!TypeIdent {
+ const list = tok.checkType(self.tokens.peek().?, .openBracket);
+ if (list) {
+ _ = try self.tokens.consume(.openBracket);
+ const typ = (try self.parseType()).ident;
+ _ = try self.tokens.consume(.closeBracket);
+ return .{
+ .ident = try std.fmt.allocPrint(self.allocator, "[{s}]", .{typ}),
+ .list = true,
+ };
+ }
+ return .{
+ .ident = (try self.tokens.consume(.ident)).?.ident,
+ .list = false,
+ };
+ }
+
+ fn parseConstant(self: *Parser) ParsingError!NodeStmt {
_ = try self.tokens.consume(.constant);
+ var typ: ?TypeIdent = null;
+ _ = if (self.tokens.consume(.colon)) |_| {
+ typ = try self.parseType();
+ } else |err| {
+ if (err != tok.TokenizeError.ExpectedToken) return err;
+ };
+
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.equal);
- const expr = try self.parseExpr();
+ const expr: NodeExpr = try self.parseExpr();
_ = try self.tokens.consume(.semiCol);
const kind = StmtKind{
.defValue = NodeValue{
.ident = ident,
- .expr = expr,
+ .expr = NodeExpr{
+ .typ = typ orelse expr.typ,
+ .id = expr.id,
+ .kind = expr.kind,
+ .isConst = expr.isConst,
+ .symtable = expr.symtable,
+ },
},
};
return NodeStmt{
@@ -316,11 +444,16 @@ pub const TypeIdent = struct {
list: bool,
};
+pub const FunctionArg = struct {
+ ident: []const u8,
+ typ: TypeIdent,
+};
+
pub const NodeFunction = struct {
ident: Token,
- args: []const TypeIdent,
+ args: []const FunctionArg,
retType: ?TypeIdent,
- block: *NodeStmt,
+ block: ?*NodeStmt,
};
pub const NodeAssign = struct {
@@ -340,9 +473,15 @@ pub const NodeVar = struct {
pub const NodeExit = NodeExpr;
pub const NodeIntlit = Token;
+pub const NodeStringlit = Token;
pub const NodeIdent = Token;
pub const NodeBlock = []const NodeStmt;
+pub const NodeCall = struct {
+ ident: Token,
+ args: []const NodeExpr,
+};
+
pub const StmtKind = union(enum) {
function: NodeFunction,
exit: NodeExit,
@@ -350,16 +489,21 @@ pub const StmtKind = union(enum) {
defVar: NodeVar,
assignVar: NodeAssign,
block: NodeBlock,
+ expr: NodeExpr,
};
pub const ExprKind = union(enum) {
intLit: NodeIntlit,
+ stringLit: NodeStringlit,
ident: NodeIdent,
+ call: NodeCall,
pub fn isConstant(self: ExprKind) bool {
return switch (self) {
.intLit => true,
+ .stringLit => true,
.ident => false,
+ .call => false,
};
}
};