Skip to content

Commit

Permalink
std.zig.parser now treats call expr as a suffix operator
Browse files Browse the repository at this point in the history
  • Loading branch information
Hejsil committed Mar 30, 2018
1 parent f586aca commit 1dfa927
Showing 1 changed file with 34 additions and 7 deletions.
41 changes: 34 additions & 7 deletions std/zig/parser.zig
Expand Up @@ -86,6 +86,7 @@ pub const Parser = struct {
AfterOperand,
InfixOp: &ast.NodeInfixOp,
PrefixOp: &ast.NodePrefixOp,
SuffixOp: &ast.Node,
AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
TypeExpr: DestPtr,
VarDecl: &ast.NodeVarDecl,
Expand Down Expand Up @@ -434,13 +435,11 @@ pub const Parser = struct {
const node = try arena.create(ast.NodeCall);
*node = ast.NodeCall {
.base = self.initNode(ast.Node.Id.Call),
.callee = stack.pop().Operand,
.callee = undefined,
.params = ArrayList(&ast.Node).init(arena),
.rparen_token = undefined,
};
try stack.append(State {
.Operand = &node.base
});
try stack.append(State { .SuffixOp = &node.base });
try stack.append(State.AfterOperand);
try stack.append(State {.ExprListItemOrEnd = &node.params });
try stack.append(State {
Expand All @@ -455,8 +454,8 @@ pub const Parser = struct {
} else {
// no postfix/infix operator after this operand.
self.putBackToken(token);
// reduce the stack
var expression: &ast.Node = stack.pop().Operand;

var expression = popSuffixOp(&stack);
while (true) {
switch (stack.pop()) {
State.Expression => |dest_ptr| {
Expand All @@ -466,7 +465,7 @@ pub const Parser = struct {
},
State.InfixOp => |infix_op| {
infix_op.rhs = expression;
infix_op.lhs = stack.pop().Operand;
infix_op.lhs = popSuffixOp(&stack);
expression = &infix_op.base;
continue;
},
Expand Down Expand Up @@ -716,11 +715,39 @@ pub const Parser = struct {
// These are data, not control flow.
State.InfixOp => unreachable,
State.PrefixOp => unreachable,
State.SuffixOp => unreachable,
State.Operand => unreachable,
}
}
}

fn popSuffixOp(stack: &ArrayList(State)) &ast.Node {
var expression: &ast.Node = undefined;
var left_leaf_ptr: &&ast.Node = &expression;
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;
},
else => unreachable,
}
},
State.Operand => |operand| {
*left_leaf_ptr = operand;
break;
},
else => unreachable,
}
}

return expression;
}

fn tokenIdToInfixOp(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {
return switch (*id) {
Token.Id.Ampersand => ast.NodeInfixOp.InfixOp.BitAnd,
Expand Down

0 comments on commit 1dfa927

Please sign in to comment.