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, Block,
InfixOp, InfixOp,
PrefixOp, PrefixOp,
SuffixOp,
IntegerLiteral, IntegerLiteral,
FloatLiteral, FloatLiteral,
StringLiteral, StringLiteral,
@ -29,9 +30,6 @@ pub const Node = struct {
Unreachable, Unreachable,
ErrorType, ErrorType,
BuiltinCall, BuiltinCall,
Call,
ArrayAccess,
SliceExpression,
LineComment, LineComment,
TestDecl, TestDecl,
}; };
@ -46,6 +44,7 @@ pub const Node = struct {
Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index), Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index), Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "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.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index),
Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index),
Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "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.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index),
Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index), Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index),
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "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.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index),
Id.TestDecl => @fieldParentPtr(NodeTestDecl, "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.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(), Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "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.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(),
Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(),
Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "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.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(),
Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(), Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(),
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "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.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
Id.TestDecl => @fieldParentPtr(NodeTestDecl, "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.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(), Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "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.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(),
Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(),
Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "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.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(),
Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(), Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(),
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "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.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(),
Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(), Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(),
}; };
@ -493,20 +485,28 @@ pub const NodePrefixOp = struct {
var i = index; var i = index;
switch (self.op) { 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| { PrefixOp.AddrOf => |addr_of_info| {
if (addr_of_info.align_expr) |align_expr| { if (addr_of_info.align_expr) |align_expr| {
if (i < 1) return align_expr; if (i < 1) return align_expr;
i -= 1; i -= 1;
} }
}, },
PrefixOp.ArrayType => |size_expr| {
if (i < 1) return size_expr;
i -= 1;
},
PrefixOp.BitNot, PrefixOp.BitNot,
PrefixOp.BoolNot, PrefixOp.BoolNot,
PrefixOp.Deref, PrefixOp.Deref,
PrefixOp.Negation, PrefixOp.Negation,
PrefixOp.NegationWrap, PrefixOp.NegationWrap,
PrefixOp.Return, PrefixOp.Return,
PrefixOp.ArrayType,
PrefixOp.SliceType,
PrefixOp.Try, PrefixOp.Try,
PrefixOp.UnwrapMaybe => {}, 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 { pub const NodeIntegerLiteral = struct {
base: Node, base: Node,
token: Token, 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 { pub const NodeStringLiteral = struct {
base: Node, base: Node,
token: Token, token: Token,

View File

@ -87,7 +87,7 @@ pub const Parser = struct {
AfterOperand, AfterOperand,
InfixOp: &ast.NodeInfixOp, InfixOp: &ast.NodeInfixOp,
PrefixOp: &ast.NodePrefixOp, PrefixOp: &ast.NodePrefixOp,
SuffixOp: &ast.Node, SuffixOp: &ast.NodeSuffixOp,
SliceOrArrayAccess, SliceOrArrayAccess,
AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo, AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
TypeExpr: DestPtr, TypeExpr: DestPtr,
@ -602,20 +602,19 @@ pub const Parser = struct {
} else if (token.id == Token.Id.LParen) { } else if (token.id == Token.Id.LParen) {
self.putBackToken(token); self.putBackToken(token);
const node = try arena.create(ast.NodeCall); const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
*node = ast.NodeCall { .Call = ast.NodeSuffixOp.CallInfo {
.base = self.initNode(ast.Node.Id.Call), .params = ArrayList(&ast.Node).init(arena),
.callee = undefined, .is_async = false, // TODO: ASYNC
.params = ArrayList(&ast.Node).init(arena), }
.rparen_token = undefined, });
}; try stack.append(State { .SuffixOp = node });
try stack.append(State { .SuffixOp = &node.base });
try stack.append(State.AfterOperand); 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 { try stack.append(State {
.ExpectTokenSave = ExpectTokenSave { .ExpectTokenSave = ExpectTokenSave {
.id = Token.Id.LParen, .id = Token.Id.LParen,
.ptr = &node.rparen_token, .ptr = &node.rtoken,
}, },
}); });
continue; continue;
@ -643,16 +642,14 @@ pub const Parser = struct {
switch (rbracket_or_ellipsis2_token.id) { switch (rbracket_or_ellipsis2_token.id) {
Token.Id.Ellipsis2 => { Token.Id.Ellipsis2 => {
const node = try arena.create(ast.NodeSliceExpression); const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
*node = ast.NodeSliceExpression { .Slice = ast.NodeSuffixOp.SliceRange {
.base = self.initNode(ast.Node.Id.SliceExpression), .start = expression,
.expr = undefined, .end = null,
.start = expression, }
.end = null, });
.rbracket_token = undefined,
};
try stack.append(State { .SuffixOp = &node.base }); try stack.append(State { .SuffixOp = node });
try stack.append(State.AfterOperand); try stack.append(State.AfterOperand);
const rbracket_token = self.getNextToken(); const rbracket_token = self.getNextToken();
@ -661,24 +658,21 @@ pub const Parser = struct {
try stack.append(State { try stack.append(State {
.ExpectTokenSave = ExpectTokenSave { .ExpectTokenSave = ExpectTokenSave {
.id = Token.Id.RBracket, .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 { } else {
node.rbracket_token = rbracket_token; node.rtoken = rbracket_token;
} }
break; break;
}, },
Token.Id.RBracket => { Token.Id.RBracket => {
const node = try arena.create(ast.NodeArrayAccess); const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
*node = ast.NodeArrayAccess { .ArrayAccess = expression
.base = self.initNode(ast.Node.Id.ArrayAccess), });
.expr = undefined, node.rtoken = token;
.index = expression, try stack.append(State { .SuffixOp = node });
.rbracket_token = token,
};
try stack.append(State { .SuffixOp = &node.base });
try stack.append(State.AfterOperand); try stack.append(State.AfterOperand);
break; break;
}, },
@ -950,27 +944,8 @@ pub const Parser = struct {
while (true) { while (true) {
switch (stack.pop()) { switch (stack.pop()) {
State.SuffixOp => |suffix_op| { State.SuffixOp => |suffix_op| {
switch (suffix_op.id) { *left_leaf_ptr = &suffix_op.base;
ast.Node.Id.Call => { left_leaf_ptr = &suffix_op.lhs;
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,
}
}, },
State.Operand => |operand| { State.Operand => |operand| {
*left_leaf_ptr = operand; *left_leaf_ptr = operand;
@ -1172,6 +1147,18 @@ pub const Parser = struct {
return node; 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 { fn createIdentifier(self: &Parser, arena: &mem.Allocator, name_token: &const Token) !&ast.NodeIdentifier {
const node = try arena.create(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.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 => { ast.Node.Id.IntegerLiteral => {
const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base); const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base);
try stream.print("{}", self.tokenizer.getTokenSlice(integer_literal.token)); 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.FnProto => @panic("TODO fn proto in an expression"),
ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"), ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),