| 5 | import type { ITokenStream } from '../streams/token-stream.js'; |
| 6 | |
| 7 | export function parseAiSonTopLevel(s: ITokenStream): Ast.Node { |
| 8 | let node: Ast.Node | null = null; |
| 9 | |
| 10 | while (s.is(TokenKind.NewLine)) { |
| 11 | s.next(); |
| 12 | } |
| 13 | |
| 14 | while (!s.is(TokenKind.EOF)) { |
| 15 | if (node == null) { |
| 16 | node = parseExpr(s, true); |
| 17 | } else { |
| 18 | throw new AiScriptSyntaxError('AiSON only supports one top-level expression.', s.getPos()); |
| 19 | } |
| 20 | |
| 21 | // terminator |
| 22 | switch (s.getTokenKind()) { |
| 23 | case TokenKind.NewLine: |
| 24 | case TokenKind.SemiColon: { |
| 25 | while (s.is(TokenKind.NewLine) || s.is(TokenKind.SemiColon)) { |
| 26 | s.next(); |
| 27 | } |
| 28 | break; |
| 29 | } |
| 30 | case TokenKind.EOF: { |
| 31 | break; |
| 32 | } |
| 33 | default: { |
| 34 | throw new AiScriptSyntaxError('Multiple statements cannot be placed on a single line.', s.getPos()); |
| 35 | } |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | if (node == null) { |
| 40 | throw new AiScriptSyntaxError('AiSON requires at least one top-level expression.', s.getPos()); |
| 41 | } |
| 42 | |
| 43 | return node; |
| 44 | } |