summaryrefslogtreecommitdiff
path: root/src/parser.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.zig')
-rw-r--r--src/parser.zig119
1 files changed, 112 insertions, 7 deletions
diff --git a/src/parser.zig b/src/parser.zig
index f2dba0a..66d02a2 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -68,6 +68,7 @@ pub const NodeExpr = struct {
.call => |call| if (table.getValue(call.ident.ident)) |symbol| try symbol.typ.Function.output.toTypeIdent(allocator) else TypeError.UnknownIdentifier,
.ident => |id| if (table.getValue(id.ident)) |symbol| try symbol.typ.toTypeIdent(allocator) else TypeError.UnknownIdentifier,
.intLit => TypeIdent{ .ident = "i32", .list = false },
+ .binaryOp => TypeIdent{ .ident = "i32", .list = false },
.stringLit => TypeIdent{ .ident = "[u8]", .list = true },
};
if (self.typ) |typ| {
@@ -107,6 +108,7 @@ pub const NodeStmt = struct {
const blockChildren = map(Node, NodeStmt, block, NodeStmt.asNode);
for (blockChildren) |child| try childrenArray.append(child);
},
+ .ifstmt => |ifstmt| try childrenArray.append(ifstmt.body.*.asNode()),
.function => |fun| if (fun.block == null) {} else try childrenArray.append(fun.block.?.asNode()),
.expr => |expr| try childrenArray.append(expr.asNode()),
}
@@ -167,9 +169,30 @@ pub const Parser = struct {
self.nodes.deinit();
}
+ fn parseCall(self: *Parser, typ: ?TypeIdent, expr: NodeExpr) ParsingError!NodeExpr {
+ if (self.tokens.peek().? != .openParen) return expr;
+ _ = try self.tokens.consume(.openParen);
+ var args = std.ArrayList(NodeExpr).init(self.allocator);
+ while (self.tokens.peek().? != .closeParen) {
+ try args.append(try self.parseExpr());
+ if (self.tokens.peek().? != .comma) break;
+ }
+ _ = try self.tokens.consume(.closeParen);
+
+ const kind = ExprKind{ .call = .{ .ident = expr.kind.ident, .args = args } };
+ return NodeExpr{
+ .kind = kind,
+ .isConst = false,
+ .typ = typ,
+ .id = self.reserveId(),
+ .symtable = self.top,
+ };
+ }
+
fn parseExpr(self: *Parser) !NodeExpr {
var typ: ?TypeIdent = null;
- const kind = try blk: {
+ var isIdent = false;
+ const kind: ExprKind = try blk: {
try switch (self.tokens.peek().?) {
.intLit => {
typ = TypeIdent{
@@ -179,6 +202,7 @@ pub const Parser = struct {
break :blk ExprKind{ .intLit = (try self.tokens.consume(.intLit)).? };
},
.ident => {
+ isIdent = true;
const ident = (try self.tokens.consume(.ident)).?;
if (tok.checkType(self.tokens.peek().?, .openParen)) {
_ = try self.tokens.consume(.openParen);
@@ -195,7 +219,7 @@ pub const Parser = struct {
}
_ = try self.tokens.consume(.closeParen);
- break :innerblk try argExprs.toOwnedSlice();
+ break :innerblk try argExprs.clone();
},
},
};
@@ -210,20 +234,66 @@ pub const Parser = struct {
};
break :blk ExprKind{ .stringLit = (try self.tokens.consume(.stringLit)).? };
},
- else => break :blk ParsingError.InvalidExpression,
+ else => |expr| break :blk errorblk: {
+ std.debug.print("Invalid Expression: {any}\n", .{expr});
+ break :errorblk ParsingError.InvalidExpression;
+ },
};
};
- return NodeExpr{
+
+ const lhs = NodeExpr{
.id = self.reserveId(),
+ .isConst = false,
.kind = kind,
- .isConst = kind.isConstant(),
- .typ = typ,
.symtable = self.top,
+ .typ = typ,
};
+
+ const lhsptr = try self.allocator.create(NodeExpr);
+ lhsptr.* = lhs;
+
+ const precTable: []const []const tok.TokenType = &.{
+ &.{ .plus, .minus },
+ &.{ .star, .slash },
+ &.{.eqleql},
+ };
+
+ return try self.genBinOp(precTable[0], typ, lhsptr) //.
+ orelse try self.genBinOp(precTable[1], typ, lhsptr) //.
+ orelse try self.genBinOp(precTable[2], typ, lhsptr) //.
+ orelse if (isIdent) blk: {
+ break :blk try self.parseCall(typ, lhsptr.*);
+ } //.
+ else lhs;
+ }
+
+ fn genBinOp(self: *Parser, comptime ops: []const tok.TokenType, typ: ?TypeIdent, lhs: *NodeExpr) ParsingError!?NodeExpr {
+ for (ops) |op|
+ if (self.tokens.peek().? == op) {
+ const oper = self.tokens.next();
+ const rhsptr = try self.allocator.create(NodeExpr);
+ rhsptr.* = try self.parseExpr();
+ const kind = ExprKind{
+ .binaryOp = .{
+ .lhs = lhs,
+ .rhs = rhsptr,
+ .op = oper.?,
+ },
+ };
+ return NodeExpr{
+ .id = self.reserveId(),
+ .isConst = false,
+ .kind = kind,
+ .symtable = self.top,
+ .typ = typ,
+ };
+ };
+ return null;
}
fn parseStmt(self: *Parser) ParsingError!NodeStmt {
return switch (self.tokens.peek().?) {
+ .ifstmt => try self.parseIf(),
.exit => try self.parseExit(),
.constant => try self.parseConstant(),
.variable => try self.parseVariable(),
@@ -232,6 +302,7 @@ pub const Parser = struct {
break :blk try self.parseAssign();
break :blk try self.parseExprStmt();
},
+ .openBrace => self.parseBlock(),
.fun => try self.parseFunc(false),
.import => try self.parseFunc(true),
else => self.parseExprStmt(),
@@ -248,6 +319,28 @@ pub const Parser = struct {
};
}
+ fn parseIf(self: *Parser) ParsingError!NodeStmt {
+ _ = try self.tokens.consume(.ifstmt); // if
+
+ _ = try self.tokens.consume(.openParen); // (
+ const expr = try self.parseExpr(); // EXPR
+ _ = try self.tokens.consume(.closeParen); // )
+
+ const body = try self.allocator.create(NodeStmt);
+ body.* = try self.parseStmt();
+
+ const kind = StmtKind{
+ .ifstmt = .{
+ .expr = expr,
+ .body = body,
+ },
+ };
+ return NodeStmt{
+ .id = self.reserveId(),
+ .kind = kind,
+ .symtable = self.top,
+ };
+ }
fn parseFunc(self: *Parser, external: bool) ParsingError!NodeStmt {
if (external) _ = try self.tokens.consume(.import);
var typ: ?TypeIdent = null;
@@ -485,18 +578,25 @@ pub const NodeVar = struct {
expr: NodeExpr,
};
+pub const NodeIf = struct {
+ expr: NodeExpr,
+ body: *NodeStmt,
+};
+
pub const NodeExit = NodeExpr;
pub const NodeIntlit = Token;
pub const NodeStringlit = Token;
pub const NodeIdent = Token;
pub const NodeBlock = []const NodeStmt;
+pub const NodeBinOp = Token;
pub const NodeCall = struct {
ident: Token,
- args: []const NodeExpr,
+ args: std.ArrayList(NodeExpr),
};
pub const StmtKind = union(enum) {
+ ifstmt: NodeIf,
function: NodeFunction,
exit: NodeExit,
defValue: NodeValue,
@@ -511,6 +611,11 @@ pub const ExprKind = union(enum) {
stringLit: NodeStringlit,
ident: NodeIdent,
call: NodeCall,
+ binaryOp: struct {
+ lhs: *NodeExpr,
+ rhs: *NodeExpr,
+ op: NodeBinOp,
+ },
pub fn isConstant(self: ExprKind) bool {
return switch (self) {