| ... | ... | @@ -86,6 +86,7 @@ pub const Parser = struct { |
| 86 | 86 | AfterOperand, |
| 87 | 87 | InfixOp: &ast.NodeInfixOp, |
| 88 | 88 | PrefixOp: &ast.NodePrefixOp, |
| 89 | SuffixOp: &ast.Node, |
| 89 | 90 | AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo, |
| 90 | 91 | TypeExpr: DestPtr, |
| 91 | 92 | VarDecl: &ast.NodeVarDecl, |
| ... | ... | @@ -434,13 +435,11 @@ pub const Parser = struct { |
| 434 | 435 | const node = try arena.create(ast.NodeCall); |
| 435 | 436 | *node = ast.NodeCall { |
| 436 | 437 | .base = self.initNode(ast.Node.Id.Call), |
| 437 | | .callee = stack.pop().Operand, |
| 438 | .callee = undefined, |
| 438 | 439 | .params = ArrayList(&ast.Node).init(arena), |
| 439 | 440 | .rparen_token = undefined, |
| 440 | 441 | }; |
| 441 | | try stack.append(State { |
| 442 | | .Operand = &node.base |
| 443 | | }); |
| 442 | try stack.append(State { .SuffixOp = &node.base }); |
| 444 | 443 | try stack.append(State.AfterOperand); |
| 445 | 444 | try stack.append(State {.ExprListItemOrEnd = &node.params }); |
| 446 | 445 | try stack.append(State { |
| ... | ... | @@ -455,8 +454,8 @@ pub const Parser = struct { |
| 455 | 454 | } else { |
| 456 | 455 | // no postfix/infix operator after this operand. |
| 457 | 456 | self.putBackToken(token); |
| 458 | | // reduce the stack |
| 459 | | var expression: &ast.Node = stack.pop().Operand; |
| 457 | |
| 458 | var expression = popSuffixOp(&stack); |
| 460 | 459 | while (true) { |
| 461 | 460 | switch (stack.pop()) { |
| 462 | 461 | State.Expression => |dest_ptr| { |
| ... | ... | @@ -466,7 +465,7 @@ pub const Parser = struct { |
| 466 | 465 | }, |
| 467 | 466 | State.InfixOp => |infix_op| { |
| 468 | 467 | infix_op.rhs = expression; |
| 469 | | infix_op.lhs = stack.pop().Operand; |
| 468 | infix_op.lhs = popSuffixOp(&stack); |
| 470 | 469 | expression = &infix_op.base; |
| 471 | 470 | continue; |
| 472 | 471 | }, |
| ... | ... | @@ -716,11 +715,39 @@ pub const Parser = struct { |
| 716 | 715 | // These are data, not control flow. |
| 717 | 716 | State.InfixOp => unreachable, |
| 718 | 717 | State.PrefixOp => unreachable, |
| 718 | State.SuffixOp => unreachable, |
| 719 | 719 | State.Operand => unreachable, |
| 720 | 720 | } |
| 721 | 721 | } |
| 722 | 722 | } |
| 723 | 723 | |
| 724 | fn popSuffixOp(stack: &ArrayList(State)) &ast.Node { |
| 725 | var expression: &ast.Node = undefined; |
| 726 | var left_leaf_ptr: &&ast.Node = &expression; |
| 727 | while (true) { |
| 728 | switch (stack.pop()) { |
| 729 | State.SuffixOp => |suffix_op| { |
| 730 | switch (suffix_op.id) { |
| 731 | ast.Node.Id.Call => { |
| 732 | const call = @fieldParentPtr(ast.NodeCall, "base", suffix_op); |
| 733 | *left_leaf_ptr = &call.base; |
| 734 | left_leaf_ptr = &call.callee; |
| 735 | continue; |
| 736 | }, |
| 737 | else => unreachable, |
| 738 | } |
| 739 | }, |
| 740 | State.Operand => |operand| { |
| 741 | *left_leaf_ptr = operand; |
| 742 | break; |
| 743 | }, |
| 744 | else => unreachable, |
| 745 | } |
| 746 | } |
| 747 | |
| 748 | return expression; |
| 749 | } |
| 750 | |
| 724 | 751 | fn tokenIdToInfixOp(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp { |
| 725 | 752 | return switch (*id) { |
| 726 | 753 | Token.Id.Ampersand => ast.NodeInfixOp.InfixOp.BitAnd, |