mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 12:27:41 +00:00
std.zig.parser refactored call, slice and array access to be suffix op
This commit is contained in:
parent
22e38ffb54
commit
b424cd75ab
183
std/zig/ast.zig
183
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,
|
||||
|
||||
@ -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"),
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user