diff options
Diffstat (limited to 'src/parser.zig')
| -rw-r--r-- | src/parser.zig | 119 |
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) { |
