From b424cd75ab9df69f44fe47c10ded3fd25c2d27bb Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Tue, 3 Apr 2018 12:33:06 +0200 Subject: [PATCH] std.zig.parser refactored call, slice and array access to be suffix op --- std/zig/ast.zig | 183 +++++++++++++++++++++------------------------ std/zig/parser.zig | 161 +++++++++++++++++++-------------------- 2 files changed, 160 insertions(+), 184 deletions(-) diff --git a/std/zig/ast.zig b/std/zig/ast.zig index 1e62bd26a8..380dd95aee 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -17,6 +17,7 @@ pub const Node = struct { Block, InfixOp, PrefixOp, + SuffixOp, IntegerLiteral, FloatLiteral, StringLiteral, @@ -29,9 +30,6 @@ pub const Node = struct { Unreachable, ErrorType, BuiltinCall, - Call, - ArrayAccess, - SliceExpression, LineComment, TestDecl, }; @@ -46,6 +44,7 @@ pub const Node = struct { Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index), Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index), Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index), + Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index), Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index), Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index), @@ -58,9 +57,6 @@ pub const Node = struct { Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index), Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index), Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index), - Id.Call => @fieldParentPtr(NodeCall, "base", base).iterate(index), - Id.ArrayAccess => @fieldParentPtr(NodeArrayAccess, "base", base).iterate(index), - Id.SliceExpression => @fieldParentPtr(NodeSliceExpression, "base", base).iterate(index), Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index), Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).iterate(index), }; @@ -76,6 +72,7 @@ pub const Node = struct { Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(), Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(), Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(), + Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(), Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(), Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(), @@ -88,9 +85,6 @@ pub const Node = struct { Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(), Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(), Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(), - Id.Call => @fieldParentPtr(NodeCall, "base", base).firstToken(), - Id.ArrayAccess => @fieldParentPtr(NodeArrayAccess, "base", base).firstToken(), - Id.SliceExpression => @fieldParentPtr(NodeSliceExpression, "base", base).firstToken(), Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(), Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).firstToken(), }; @@ -106,6 +100,7 @@ pub const Node = struct { Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(), Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(), Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(), + Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(), Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(), Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(), @@ -118,9 +113,6 @@ pub const Node = struct { Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(), Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(), Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(), - Id.Call => @fieldParentPtr(NodeCall, "base", base).lastToken(), - Id.ArrayAccess => @fieldParentPtr(NodeArrayAccess, "base", base).lastToken(), - Id.SliceExpression => @fieldParentPtr(NodeSliceExpression, "base", base).lastToken(), Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(), Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(), }; @@ -493,20 +485,28 @@ pub const NodePrefixOp = struct { var i = index; switch (self.op) { + PrefixOp.SliceType => |addr_of_info| { + if (addr_of_info.align_expr) |align_expr| { + if (i < 1) return align_expr; + i -= 1; + } + }, PrefixOp.AddrOf => |addr_of_info| { if (addr_of_info.align_expr) |align_expr| { if (i < 1) return align_expr; i -= 1; } }, + PrefixOp.ArrayType => |size_expr| { + if (i < 1) return size_expr; + i -= 1; + }, PrefixOp.BitNot, PrefixOp.BoolNot, PrefixOp.Deref, PrefixOp.Negation, PrefixOp.NegationWrap, PrefixOp.Return, - PrefixOp.ArrayType, - PrefixOp.SliceType, PrefixOp.Try, PrefixOp.UnwrapMaybe => {}, } @@ -526,6 +526,76 @@ pub const NodePrefixOp = struct { } }; +pub const NodeSuffixOp = struct { + base: Node, + lhs: &Node, + op: SuffixOp, + rtoken: Token, + + const SuffixOp = union(enum) { + Call: CallInfo, + ArrayAccess: &Node, + Slice: SliceRange, + ArrayInitializer: ArrayList(&Node), + StructInitializer: ArrayList(&Node), + }; + + const CallInfo = struct { + params: ArrayList(&Node), + is_async: bool, + }; + + const SliceRange = struct { + start: &Node, + end: ?&Node, + }; + + pub fn iterate(self: &NodeSuffixOp, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.lhs; + i -= 1; + + switch (self.op) { + SuffixOp.Call => |call_info| { + if (i < call_info.params.len) return call_info.params.at(i); + i -= call_info.params.len; + }, + SuffixOp.ArrayAccess => |index_expr| { + if (i < 1) return index_expr; + i -= 1; + }, + SuffixOp.Slice => |range| { + if (i < 1) return range.start; + i -= 1; + + if (range.end) |end| { + if (i < 1) return end; + i -= 1; + } + }, + SuffixOp.ArrayInitializer => |exprs| { + if (i < exprs.len) return exprs.at(i); + i -= exprs.len; + }, + SuffixOp.StructInitializer => |fields| { + if (i < fields.len) return fields.at(i); + i -= fields.len; + }, + } + + return null; + } + + pub fn firstToken(self: &NodeSuffixOp) Token { + return self.lhs.firstToken(); + } + + pub fn lastToken(self: &NodeSuffixOp) Token { + return self.rtoken; + } +}; + pub const NodeIntegerLiteral = struct { base: Node, token: Token, @@ -584,91 +654,6 @@ pub const NodeBuiltinCall = struct { } }; -pub const NodeCall = struct { - base: Node, - callee: &Node, - params: ArrayList(&Node), - rparen_token: Token, - - pub fn iterate(self: &NodeCall, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.callee; - i -= 1; - - if (i < self.params.len) return self.params.at(i); - i -= self.params.len; - - return null; - } - - pub fn firstToken(self: &NodeCall) Token { - return self.callee.firstToken(); - } - - pub fn lastToken(self: &NodeCall) Token { - return self.rparen_token; - } -}; - -pub const NodeArrayAccess = struct { - base: Node, - expr: &Node, - index: &Node, - rbracket_token: Token, - - pub fn iterate(self: &NodeArrayAccess, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.expr; - i -= 1; - - if (i < 1) return self.index; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeArrayAccess) Token { - return self.expr.firstToken(); - } - - pub fn lastToken(self: &NodeArrayAccess) Token { - return self.rbracket_token; - } -}; - -pub const NodeSliceExpression = struct { - base: Node, - expr: &Node, - start: &Node, - end: ?&Node, - rbracket_token: Token, - - pub fn iterate(self: &NodeSliceExpression, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.callee; - i -= 1; - - if (i < 1) return self.start; - i -= 1; - - if (i < 1) return self.end; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeSliceExpression) Token { - return self.expr.firstToken(); - } - - pub fn lastToken(self: &NodeSliceExpression) Token { - return self.rbracket_token; - } -}; - pub const NodeStringLiteral = struct { base: Node, token: Token, diff --git a/std/zig/parser.zig b/std/zig/parser.zig index 671f454f5a..6d5ec54bc8 100644 --- a/std/zig/parser.zig +++ b/std/zig/parser.zig @@ -87,7 +87,7 @@ pub const Parser = struct { AfterOperand, InfixOp: &ast.NodeInfixOp, PrefixOp: &ast.NodePrefixOp, - SuffixOp: &ast.Node, + SuffixOp: &ast.NodeSuffixOp, SliceOrArrayAccess, AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo, TypeExpr: DestPtr, @@ -602,20 +602,19 @@ pub const Parser = struct { } else if (token.id == Token.Id.LParen) { self.putBackToken(token); - const node = try arena.create(ast.NodeCall); - *node = ast.NodeCall { - .base = self.initNode(ast.Node.Id.Call), - .callee = undefined, - .params = ArrayList(&ast.Node).init(arena), - .rparen_token = undefined, - }; - try stack.append(State { .SuffixOp = &node.base }); + const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { + .Call = ast.NodeSuffixOp.CallInfo { + .params = ArrayList(&ast.Node).init(arena), + .is_async = false, // TODO: ASYNC + } + }); + try stack.append(State { .SuffixOp = node }); try stack.append(State.AfterOperand); - try stack.append(State {.ExprListItemOrEnd = &node.params }); + try stack.append(State {.ExprListItemOrEnd = &node.op.Call.params }); try stack.append(State { .ExpectTokenSave = ExpectTokenSave { .id = Token.Id.LParen, - .ptr = &node.rparen_token, + .ptr = &node.rtoken, }, }); continue; @@ -643,16 +642,14 @@ pub const Parser = struct { switch (rbracket_or_ellipsis2_token.id) { Token.Id.Ellipsis2 => { - const node = try arena.create(ast.NodeSliceExpression); - *node = ast.NodeSliceExpression { - .base = self.initNode(ast.Node.Id.SliceExpression), - .expr = undefined, - .start = expression, - .end = null, - .rbracket_token = undefined, - }; + const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { + .Slice = ast.NodeSuffixOp.SliceRange { + .start = expression, + .end = null, + } + }); - try stack.append(State { .SuffixOp = &node.base }); + try stack.append(State { .SuffixOp = node }); try stack.append(State.AfterOperand); const rbracket_token = self.getNextToken(); @@ -661,24 +658,21 @@ pub const Parser = struct { try stack.append(State { .ExpectTokenSave = ExpectTokenSave { .id = Token.Id.RBracket, - .ptr = &node.rbracket_token, + .ptr = &node.rtoken, } }); - try stack.append(State { .Expression = DestPtr { .NullableField = &node.end } }); + try stack.append(State { .Expression = DestPtr { .NullableField = &node.op.Slice.end } }); } else { - node.rbracket_token = rbracket_token; + node.rtoken = rbracket_token; } break; }, Token.Id.RBracket => { - const node = try arena.create(ast.NodeArrayAccess); - *node = ast.NodeArrayAccess { - .base = self.initNode(ast.Node.Id.ArrayAccess), - .expr = undefined, - .index = expression, - .rbracket_token = token, - }; - try stack.append(State { .SuffixOp = &node.base }); + const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { + .ArrayAccess = expression + }); + node.rtoken = token; + try stack.append(State { .SuffixOp = node }); try stack.append(State.AfterOperand); break; }, @@ -950,27 +944,8 @@ pub const Parser = struct { while (true) { switch (stack.pop()) { State.SuffixOp => |suffix_op| { - switch (suffix_op.id) { - ast.Node.Id.Call => { - const call = @fieldParentPtr(ast.NodeCall, "base", suffix_op); - *left_leaf_ptr = &call.base; - left_leaf_ptr = &call.callee; - continue; - }, - ast.Node.Id.ArrayAccess => { - const arr_access = @fieldParentPtr(ast.NodeArrayAccess, "base", suffix_op); - *left_leaf_ptr = &arr_access.base; - left_leaf_ptr = &arr_access.expr; - continue; - }, - ast.Node.Id.SliceExpression => { - const slice_expr = @fieldParentPtr(ast.NodeSliceExpression, "base", suffix_op); - *left_leaf_ptr = &slice_expr.base; - left_leaf_ptr = &slice_expr.expr; - continue; - }, - else => unreachable, - } + *left_leaf_ptr = &suffix_op.base; + left_leaf_ptr = &suffix_op.lhs; }, State.Operand => |operand| { *left_leaf_ptr = operand; @@ -1172,6 +1147,18 @@ pub const Parser = struct { return node; } + fn createSuffixOp(self: &Parser, arena: &mem.Allocator, op: &const ast.NodeSuffixOp.SuffixOp) !&ast.NodeSuffixOp { + const node = try arena.create(ast.NodeSuffixOp); + + *node = ast.NodeSuffixOp { + .base = self.initNode(ast.Node.Id.SuffixOp), + .lhs = undefined, + .op = *op, + .rtoken = undefined, + }; + return node; + } + fn createIdentifier(self: &Parser, arena: &mem.Allocator, name_token: &const Token) !&ast.NodeIdentifier { const node = try arena.create(ast.NodeIdentifier); @@ -1625,6 +1612,43 @@ pub const Parser = struct { ast.NodePrefixOp.PrefixOp.UnwrapMaybe => try stream.write("??"), } }, + ast.Node.Id.SuffixOp => { + const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", base); + + switch (suffix_op.op) { + ast.NodeSuffixOp.SuffixOp.Call => |call_info| { + try stack.append(RenderState { .Text = ")"}); + var i = call_info.params.len; + while (i != 0) { + i -= 1; + const param_node = call_info.params.at(i); + try stack.append(RenderState { .Expression = param_node}); + if (i != 0) { + try stack.append(RenderState { .Text = ", " }); + } + } + try stack.append(RenderState { .Text = "("}); + }, + ast.NodeSuffixOp.SuffixOp.ArrayAccess => |index_expr| { + try stack.append(RenderState { .Text = "]"}); + try stack.append(RenderState { .Expression = index_expr}); + try stack.append(RenderState { .Text = "["}); + }, + ast.NodeSuffixOp.SuffixOp.Slice => |range| { + try stack.append(RenderState { .Text = "]"}); + if (range.end) |end| { + try stack.append(RenderState { .Expression = end}); + } + try stack.append(RenderState { .Text = ".."}); + try stack.append(RenderState { .Expression = range.start}); + try stack.append(RenderState { .Text = "["}); + }, + ast.NodeSuffixOp.SuffixOp.StructInitializer => @panic("TODO: StructInitializer"), + ast.NodeSuffixOp.SuffixOp.ArrayInitializer => @panic("TODO: ArrayInitializer"), + } + + try stack.append(RenderState { .Expression = suffix_op.lhs }); + }, ast.Node.Id.IntegerLiteral => { const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(integer_literal.token)); @@ -1693,39 +1717,6 @@ pub const Parser = struct { } } }, - ast.Node.Id.Call => { - const call = @fieldParentPtr(ast.NodeCall, "base", base); - try stack.append(RenderState { .Text = ")"}); - var i = call.params.len; - while (i != 0) { - i -= 1; - const param_node = call.params.at(i); - try stack.append(RenderState { .Expression = param_node}); - if (i != 0) { - try stack.append(RenderState { .Text = ", " }); - } - } - try stack.append(RenderState { .Text = "("}); - try stack.append(RenderState { .Expression = call.callee }); - }, - ast.Node.Id.ArrayAccess => { - const arr_access = @fieldParentPtr(ast.NodeArrayAccess, "base", base); - try stack.append(RenderState { .Text = "]"}); - try stack.append(RenderState { .Expression = arr_access.index}); - try stack.append(RenderState { .Text = "["}); - try stack.append(RenderState { .Expression = arr_access.expr }); - }, - ast.Node.Id.SliceExpression => { - const slice_expr = @fieldParentPtr(ast.NodeSliceExpression, "base", base); - try stack.append(RenderState { .Text = "]"}); - if (slice_expr.end) |end| { - try stack.append(RenderState { .Expression = end}); - } - try stack.append(RenderState { .Text = ".."}); - try stack.append(RenderState { .Expression = slice_expr.start}); - try stack.append(RenderState { .Text = "["}); - try stack.append(RenderState { .Expression = slice_expr.expr}); - }, ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"), ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),