(s: ITokenStream, minBp: number)
| 53 | ]; |
| 54 | |
| 55 | function parsePrefix(s: ITokenStream, minBp: number): Ast.Expression { |
| 56 | const startPos = s.getPos(); |
| 57 | const op = s.getTokenKind(); |
| 58 | s.next(); |
| 59 | |
| 60 | // 改行のエスケープ |
| 61 | if (s.is(TokenKind.BackSlash)) { |
| 62 | s.next(); |
| 63 | s.expect(TokenKind.NewLine); |
| 64 | s.next(); |
| 65 | } |
| 66 | |
| 67 | const expr = parsePratt(s, minBp); |
| 68 | |
| 69 | const endPos = expr.loc.end; |
| 70 | |
| 71 | switch (op) { |
| 72 | case TokenKind.Plus: { |
| 73 | if (expr.type === 'num') { |
| 74 | return NODE('num', { value: expr.value }, startPos, endPos); |
| 75 | } |
| 76 | return NODE('plus', { expr }, startPos, endPos); |
| 77 | } |
| 78 | case TokenKind.Minus: { |
| 79 | if (expr.type === 'num') { |
| 80 | return NODE('num', { value: -1 * expr.value }, startPos, endPos); |
| 81 | } |
| 82 | return NODE('minus', { expr }, startPos, endPos); |
| 83 | } |
| 84 | case TokenKind.Not: { |
| 85 | return NODE('not', { expr }, startPos, endPos); |
| 86 | } |
| 87 | default: { |
| 88 | throw unexpectedTokenError(op, startPos); |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | function parseInfix(s: ITokenStream, left: Ast.Expression, minBp: number): Ast.Expression { |
| 94 | const startPos = s.getPos(); |
no test coverage detected