std.zig.parser refactored call, slice and array access to be suffix op

This commit is contained in:
Jimmi Holst Christensen 2018-04-03 12:33:06 +02:00
parent 22e38ffb54
commit b424cd75ab
2 changed files with 160 additions and 184 deletions

View File

@ -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,

View File

@ -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"),