(s: ITokenStream, left: Ast.Expression, minBp: number)
| 91 | } |
| 92 | |
| 93 | function parseInfix(s: ITokenStream, left: Ast.Expression, minBp: number): Ast.Expression { |
| 94 | const startPos = s.getPos(); |
| 95 | const op = s.getTokenKind(); |
| 96 | s.next(); |
| 97 | |
| 98 | // 改行のエスケープ |
| 99 | if (s.is(TokenKind.BackSlash)) { |
| 100 | s.next(); |
| 101 | s.expect(TokenKind.NewLine); |
| 102 | s.next(); |
| 103 | } |
| 104 | |
| 105 | if (op === TokenKind.Dot) { |
| 106 | const name = parseObjectKey(s); |
| 107 | s.next(); |
| 108 | |
| 109 | return NODE('prop', { |
| 110 | target: left, |
| 111 | name, |
| 112 | }, startPos, s.getPos()); |
| 113 | } else { |
| 114 | const right = parsePratt(s, minBp); |
| 115 | const endPos = s.getPos(); |
| 116 | |
| 117 | switch (op) { |
| 118 | case TokenKind.Hat: { |
| 119 | return NODE('pow', { left, right }, startPos, endPos); |
| 120 | } |
| 121 | case TokenKind.Asterisk: { |
| 122 | return NODE('mul', { left, right }, startPos, endPos); |
| 123 | } |
| 124 | case TokenKind.Slash: { |
| 125 | return NODE('div', { left, right }, startPos, endPos); |
| 126 | } |
| 127 | case TokenKind.Percent: { |
| 128 | return NODE('rem', { left, right }, startPos, endPos); |
| 129 | } |
| 130 | case TokenKind.Plus: { |
| 131 | return NODE('add', { left, right }, startPos, endPos); |
| 132 | } |
| 133 | case TokenKind.Minus: { |
| 134 | return NODE('sub', { left, right }, startPos, endPos); |
| 135 | } |
| 136 | case TokenKind.Lt: { |
| 137 | return NODE('lt', { left, right }, startPos, endPos); |
| 138 | } |
| 139 | case TokenKind.LtEq: { |
| 140 | return NODE('lteq', { left, right }, startPos, endPos); |
| 141 | } |
| 142 | case TokenKind.Gt: { |
| 143 | return NODE('gt', { left, right }, startPos, endPos); |
| 144 | } |
| 145 | case TokenKind.GtEq: { |
| 146 | return NODE('gteq', { left, right }, startPos, endPos); |
| 147 | } |
| 148 | case TokenKind.Eq2: { |
| 149 | return NODE('eq', { left, right }, startPos, endPos); |
| 150 | } |
no test coverage detected