Appearance
| 1 | namespace Syntax.Parsers.Definitions is | |
| 2 | use System.Exception | |
| 3 | use IO.Std | |
| 4 | ||
| 5 | use Source | |
| 6 | ||
| 7 | class MEMBER_LIST(definition_parser: Parser[Trees.Definitions.Definition]): Base[Trees.Definitions.LIST] is | |
| 8 | description: string => "definition list" | |
| 9 | ||
| 10 | super() | |
| 11 | ||
| 12 | parse(context: CONTEXT) -> Trees.Definitions.LIST is | |
| 13 | let start = context.location | |
| 14 | let end mut = context.location | |
| 15 | let definitions = Collections.LIST[Trees.Definitions.Definition]() | |
| 16 | let resync = DEFINITION_RESYNC() | |
| 17 | ||
| 18 | while !context.is_end_of_file /\ context.current.token != Lexical.TOKEN.SI do | |
| 19 | // See GLOBAL_LIST: debris from a construct already reported | |
| 20 | // as unclosed. `si` closes the type here, so it is never | |
| 21 | // debris. | |
| 22 | if context.at_stray_construct_closer(false) then | |
| 23 | context.next_token() | |
| 24 | ||
| 25 | continue | |
| 26 | fi | |
| 27 | ||
| 28 | let errors_before = context.logger.error_count | |
| 29 | let attempt_start = context.location | |
| 30 | let progress_start = context.location.start | |
| 31 | ||
| 32 | try | |
| 33 | let definition = definition_parser.parse(context) | |
| 34 | ||
| 35 | if definition? then | |
| 36 | end = definition.location | |
| 37 | ||
| 38 | definitions.add(definition) | |
| 39 | fi | |
| 40 | catch ue: UNWIND_TO_MEMBER_EXCEPTION | |
| 41 | // carry on from here | |
| 42 | ||
| 43 | catch ubp: UNWIND_BAD_PROPERTY_EXCEPTION | |
| 44 | break | |
| 45 | ||
| 46 | catch e: Exception | |
| 47 | IoC.CONTAINER.instance.logger.exception(context.current.location, e, "parse exception: {e.message}") | |
| 48 | ||
| 49 | // TODO: better recovery here - can we use indentation? | |
| 50 | while | |
| 51 | !context.is_end_of_file /\ | |
| 52 | context.current.token != Lexical.TOKEN.SI /\ | |
| 53 | context.current.token != Lexical.TOKEN.SEMICOLON | |
| 54 | do | |
| 55 | context.next_token() | |
| 56 | od | |
| 57 | ||
| 58 | if context.is_end_of_file then | |
| 59 | break | |
| 60 | fi | |
| 61 | yrt | |
| 62 | ||
| 63 | resync.recover(context, attempt_start, errors_before) | |
| 64 | ||
| 65 | // An attempt that consumed nothing, left at a token some | |
| 66 | // enclosing construct awaits, would otherwise be repeated | |
| 67 | // at the same place. | |
| 68 | if context.location.start == progress_start /\ !context.is_end_of_file then | |
| 69 | context.next_token() | |
| 70 | fi | |
| 71 | od | |
| 72 | ||
| 73 | return Trees.Definitions.LIST(start::end, definitions) | |
| 74 | si | |
| 75 | si | |
| 76 | si |