Commit b9093185f7
Changed files (3)
std/zig/ast.zig
@@ -30,6 +30,8 @@ pub const Node = struct {
ErrorType,
BuiltinCall,
Call,
+ ArrayAccess,
+ SliceExpression,
LineComment,
TestDecl,
};
@@ -57,6 +59,8 @@ pub const Node = struct {
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),
};
@@ -85,6 +89,8 @@ pub const Node = struct {
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(),
};
@@ -113,6 +119,8 @@ pub const Node = struct {
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(),
};
@@ -598,6 +606,64 @@ pub const NodeCall = struct {
}
};
+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,
std/zig/parser.zig
@@ -88,6 +88,7 @@ pub const Parser = struct {
InfixOp: &ast.NodeInfixOp,
PrefixOp: &ast.NodePrefixOp,
SuffixOp: &ast.Node,
+ SliceOrArrayAccess,
AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
TypeExpr: DestPtr,
VarDecl: &ast.NodeVarDecl,
@@ -590,6 +591,11 @@ pub const Parser = struct {
});
continue;
+ } else if (token.id == Token.Id.LBracket) {
+ try stack.append(State.SliceOrArrayAccess);
+ try stack.append(State.ExpectOperand);
+ continue;
+
// TODO: Parse postfix operator
} else {
// no postfix/infix operator after this operand.
@@ -603,6 +609,53 @@ pub const Parser = struct {
try dest_ptr.store(expression);
break;
},
+ State.SliceOrArrayAccess => {
+ var rbracket_or_ellipsis2_token = self.getNextToken();
+
+ 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,
+ };
+
+ try stack.append(State { .SuffixOp = &node.base });
+ try stack.append(State.AfterOperand);
+
+ const rbracket_token = self.getNextToken();
+ if (rbracket_token.id != Token.Id.RBracket) {
+ self.putBackToken(rbracket_token);
+ try stack.append(State {
+ .ExpectTokenSave = ExpectTokenSave {
+ .id = Token.Id.RBracket,
+ .ptr = &node.rbracket_token,
+ }
+ });
+ try stack.append(State { .Expression = DestPtr { .NullableField = &node.end } });
+ } else {
+ node.rbracket_token = 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 });
+ try stack.append(State.AfterOperand);
+ break;
+ },
+ else => return self.parseError(token, "expected ']' or '..', found {}", @tagName(token.id))
+ }
+ },
State.InfixOp => |infix_op| {
infix_op.rhs = expression;
infix_op.lhs = popSuffixOp(&stack);
@@ -857,6 +910,7 @@ pub const Parser = struct {
State.PrefixOp => unreachable,
State.SuffixOp => unreachable,
State.Operand => unreachable,
+ State.SliceOrArrayAccess => unreachable,
}
}
}
@@ -874,6 +928,18 @@ pub const Parser = struct {
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,
}
},
@@ -1594,6 +1660,24 @@ pub const Parser = struct {
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"),
@@ -1978,6 +2062,14 @@ test "zig fmt: indexing" {
\\ a[0 + 5];
\\ a[0..];
\\ a[0..5];
+ \\ a[a[0]];
+ \\ a[a[0..]];
+ \\ a[a[0..5]];
+ \\ a[a[0]..];
+ \\ a[a[0..5]..];
+ \\ a[a[0]..a[0]];
+ \\ a[a[0..5]..a[0]];
+ \\ a[a[0..5]..a[0..5]];
\\}
\\
);
std/zig/tokenizer.zig
@@ -91,6 +91,8 @@ pub const Token = struct {
PercentEqual,
LBrace,
RBrace,
+ LBracket,
+ RBracket,
Period,
Ellipsis2,
Ellipsis3,
@@ -327,6 +329,16 @@ pub const Tokenizer = struct {
self.index += 1;
break;
},
+ '[' => {
+ result.id = Token.Id.LBracket;
+ self.index += 1;
+ break;
+ },
+ ']' => {
+ result.id = Token.Id.RBracket;
+ self.index += 1;
+ break;
+ },
';' => {
result.id = Token.Id.Semicolon;
self.index += 1;