Appearance
| 1 | namespace Syntax.Parsers.Bodies is | |
| 2 | use IO.Std; | |
| 3 | ||
| 4 | ||
| 5 | class BODY( | |
| 6 | expression_parser: Parser[Trees.Expressions.Expression], | |
| 7 | statement_parser: Parser[Trees.Statements.Statement], | |
| 8 | statement_list_parser: Parser[Trees.Statements.LIST], | |
| 9 | identifier_qualified_parser: Parser[Trees.Identifiers.Identifier] | |
| 10 | ): Base[Trees.Bodies.Body] is | |
| 11 | description: string => "function body"; | |
| 12 | ||
| 13 | super(); | |
| 14 | ||
| 15 | init(..) is | |
| 16 | add_parsers(); | |
| 17 | si | |
| 18 | ||
| 19 | add_parsers() is | |
| 20 | add_parser( | |
| 21 | (context: CONTEXT) is | |
| 22 | context.next_token(Lexical.TOKEN.ARROW_FAT); | |
| 23 | ||
| 24 | // `=> throw E` stubs out a body that always diverges. | |
| 25 | // `throw` is a statement, not an expression, so wrap | |
| 26 | // it the way `if`/`case` bodies are wrapped; the body | |
| 27 | // takes its type from the declared return type (or | |
| 28 | // settles void when that is inferred). | |
| 29 | if context.current.token == Lexical.TOKEN.THROW then | |
| 30 | let statement = statement_parser.parse(context)!; | |
| 31 | return Trees.Bodies.EXPRESSION(statement.location, Trees.Expressions.STATEMENT(statement.location, statement)); | |
| 32 | fi | |
| 33 | ||
| 34 | let expression = expression_parser.parse(context)!; | |
| 35 | return Trees.Bodies.EXPRESSION(expression.location, expression); | |
| 36 | si, | |
| 37 | Lexical.TOKEN.ARROW_FAT | |
| 38 | ); | |
| 39 | ||
| 40 | add_parser( | |
| 41 | (context: CONTEXT) is | |
| 42 | let start = context.location; | |
| 43 | context.next_token(Lexical.TOKEN.IS); | |
| 44 | let statement_list = statement_list_parser.parse(context)!; | |
| 45 | let end = context.location; | |
| 46 | context.next_token(Lexical.TOKEN.SI); | |
| 47 | return Trees.Bodies.BLOCK(start::end, statement_list); | |
| 48 | si, | |
| 49 | Lexical.TOKEN.IS | |
| 50 | ); | |
| 51 | ||
| 52 | add_parser( | |
| 53 | (context: CONTEXT) is | |
| 54 | let start = context.location; | |
| 55 | context.next_token(Lexical.TOKEN.INNATE); | |
| 56 | let identifier = identifier_qualified_parser.parse(context)!; | |
| 57 | return Trees.Bodies.INNATE(start::identifier.location, identifier); | |
| 58 | si, | |
| 59 | Lexical.TOKEN.INNATE | |
| 60 | ); | |
| 61 | si | |
| 62 | ||
| 63 | other_token(context: CONTEXT) -> Trees.Bodies.Body => | |
| 64 | Trees.Bodies.NULL(context.location); | |
| 65 | si | |
| 66 | si |