UNPKG

tree-sitter-abl

Version:
2,042 lines (1,787 loc) 52.1 kB
const PREC = { UNARY: 8, EXP: 7, MULTI: 6, ADD: 5, COMPARE: 4, LOGICAL: 3, ASSIGN: 2, EXTRA: -1 }; module.exports = grammar({ name: "abl", externals: ($) => [ $._namedot, $._namecolon, $._namedoublecolon, $._or_operator, $._and_operator, $._augmented_assignment, $._escaped_string, $._input_keyword, $._output_keyword, $._new_keyword, $._old_keyword, $._for_keyword, $._def_keyword, $._var_keyword, $._index_keyword, $._field_keyword ], extras: ($) => [$.comment, /[\s\f\uFEFF\u2060\u200B]|\\\r?\n/], word: ($) => $.identifier, supertypes: ($) => [$._expression, $._statement], conflicts: ($) => [ [$.sort_clause], [$.string_literal], [$.if_statement] ], rules: { source_code: ($) => repeat(choice($._statement, $.class_statement, $._definition, $.do_block, $.interface_statement)), body: ($) => seq(":", repeat(choice($._statement, $._definition))), _statement_body: ($) => choice($.do_block, prec(2, $._statement)), dot_body: ($) => seq(choice(":", "."), repeat(choice($._statement, $._definition))), class_body: ($) => seq( ":", repeat( choice( $._definition, $.var_statement, seq( optional($.annotation), $.method_statement), $.constructor_statement, $.destructor_statement ) ) ), interface_body: ($) => seq( ":", repeat( choice( $._definition, $.method_statement ) ) ), case_body: ($) => seq(":", repeat1($.case_when_branch), optional($.case_otherwise_branch)), enum_body: ($) => seq(":", repeat1($.enum_definition)), label: ($) => seq($.identifier, ":"), _terminator: ($) => /\s*\./, _block_terminator: ($) => seq( kw("END"), optional( choice( kw("FUNCTION"), kw("PROCEDURE"), kw("CASE"), kw("CLASS"), kw("ENUM"), kw("INTERFACE"), kw("CONSTRUCTOR"), kw("DESTRUCTOR"), kw("CATCH"), kw("FINALLY") ) ), "." ), // OPERATORS _logical_operator: ($) => prec.left( choice(alias($._and_operator, "AND"), alias($._or_operator, "OR")) ), assignment_operator: ($) => choice("=", $._augmented_assignment), _additive_operator: ($) => choice("+", "-"), _multiplicative_operator: ($) => choice("*", "/", kw("MODULO"), kw("MOD")), _comparison_operator: ($) => choice( "<", "<=", "<>", "=", ">", ">=", kw("LT"), kw("LE"), kw("NE"), kw("EQ"), kw("GT"), kw("GE"), kw("BEGINS"), kw("MATCHES"), kw("CONTAINS") ), // LITERALS / KEYWORDS _name: ($) => choice($.identifier, $.qualified_name), file_name: ($) => /[A-z-_|0-9|\/]+\.[ip]/i, // TODO: FIX: Comments inside comments caused memory leak comment: ($) => choice(seq("//", /.*/), seq("/*", /[^*]*\*+([^/*][^*]*\*+)*/, "/")), annotation: ($) => seq( "@", choice( seq(kw("TEST"), optional($.annotation_argument)), seq(kw("TESTSUITE"), optional($.annotation_argument)), kw("BEFORE"), kw("BEFOREALL"), kw("BEFOREEACH"), kw("SETUP"), kw("AFTEREACH"), kw("TEARDOWN"), kw("AFTERALL"), kw("AFTER"), kw("IGNORE") ), $._terminator ), preprocessor_directive: ($) => seq( "&", token( choice( seq( /[^\n~]+/, repeat(seq("~", /\s*\n/, /[^\n~]*/)) ), seq( kw("IF"), /[^\n]*/, repeat(seq(/\n/, /[^\n]*/)), /\n\s*/, "&", kw("ENDIF") ) ), ) ), _literal: ($) => choice( $.number_literal, $.string_literal ), boolean_literal: ($) => choice(kw("TRUE"), kw("FALSE"), kw("YES"), kw("NO")), _integer_literal: ($) => /[0-9]+/, _decimal_literal: ($) => seq($._integer_literal, alias($._namedot, "."), $._integer_literal), number_literal: ($) => choice($._integer_literal, $._decimal_literal), string_literal: ($) => seq($._escaped_string, optional(seq(":", $.string_literal_attribute))), string_literal_attribute: ($) => choice( seq( choice( kw("R"), kw("L"), kw("C"), kw("T") ), $._integer_literal ), kw("U") ), date_literal: ($) => /\d{1,2}\/\d{1,2}\/\d{4}|\d{2}/, array_literal: ($) => seq( "[", optional($._array_literal_body), "]" ), _array_literal_body: ($) => choice( $.range_notation, _list($._array_literal_member, ",") ), _array_literal_member: ($) => choice( $.new_expression, $.number_literal, $.string_literal, $.boolean_literal, $.function_call, $.array_literal, $.array_access, $.identifier, $._binary_expression ), range_notation: ($) => seq( choice($.identifier, $._integer_literal), alias($._for_keyword, "FOR"), $._integer_literal ), _define: ($) => choice( kw("DEFINE"), alias($._def_keyword, "DEF"), ), // INCLUDES include_argument: ($) => choice( seq( "&", field("name", $.identifier), "=", field("value", $.string_literal) ), field("name", $.identifier), field("value", $.string_literal), $.constant ), include: ($) => seq( "{", $.file_name, repeat($.include_argument), "}" ), // IDENTIFIERS identifier: ($) => /[A-Z|a-z|\-|\\_]{1}[A-Z|a-z|\-|\\_|0-9]*/i, constant: ($) => seq("{", optional("&"), $._constant_value, "}"), _constant_value: ($) => choice($.identifier, $._integer_literal), qualified_name: ($) => seq( $.identifier, repeat1(seq(alias($._namedot, "."), choice($.identifier, "*"))) ), // TUNING _tuning: ($) => choice( $.access_tuning, $.scope_tuning, $.member_modifier ), // TODO: Fix! HACK: progress spaghetti allows to define tuning order before where clause // Leaving this here, just in case if it has to be reverted // _pre_tuning: ($) => prec.right(1, $.query_tuning), access_tuning: ($) => choice( kw("PRIVATE"), kw("PROTECTED"), kw("PUBLIC"), kw("PACKAGE-PRIVATE"), kw("PACKAGE-PROTECTED") ), accumulate_aggregate: ($) => choice( kw("AVERAGE"), kw("COUNT"), kw("MAXIMUM"), kw("MINIMUM"), kw("TOTAL"), kw("SUB-AVERAGE"), kw("SUB-COUNT"), kw("SUB-MAXIMUM"), kw("SUB-MINIMUM"), kw("SUB-TOTAL") ), // button_tuning: ($) => // choice( // seq(kw("AUTO-GO"), optional(kw("AUTO-ENDKEY"))), // kw("DEFAULT"), // $._bgcolor, // $._context_help_id, // $._dcolor, // kw("DROP-TARGET"), // $._fgcolor, // $._font, // $.image_phrase, // seq(kw("MOUSE-POINTER"), $.identifier), // $._label, // seq(kw("LIKE"), $.identifier), // $._pfcolor, // seq(kw("NO-FOCUS"), optional(kw("FLAT-BUTTON"))), // kw("NO-CONVERT-3D-COLORS"), // $._tooltip, // $.size_phrase // ), class_tuning: ($) => choice( $.inherits, $.implements, kw("USE-WIDGET-POOL"), kw("ABSTRACT"), kw("FINAL"), kw("SERIALIZABLE") ), field_option: ($) => choice( // $._bgcolor, $._column_label, // $._dcolor, $._label, $._format, $._value_tuning, $._font, // $._fgcolor, // $._pfcolor, kw("SERIALIZE-HIDDEN"), $._serialize_name, // seq(kw("XML-DATA-TYPE"), $.string_literal), // seq(kw("XML-NODE-TYPE"), $.string_literal), // seq(kw("XML-NODE-NAME"), $.string_literal), seq(kw("HELP"), $.string_literal), seq(optional(kw("NOT")), kw("CASE-SENSITIVE")), seq(kw("MOUSE-POINTER"), $.identifier), // kw("TTCODEPAGE"), // seq(kw("COLUMN-CODEPAGE"), $.string_literal) ), parameter_tuning: ($) => choice( kw("APPEND"), kw("BIND"), kw("BY-VALUE"), kw("BY-REFERENCE"), $._extent ), function_parameters: ($) => seq("(", optional(_list($.function_parameter, ",")), ")"), // image_tuning: ($) => // choice( // $._bgcolor, // $._fgcolor, // kw("CONVERT-3D-COLORS"), // $._tooltip, // seq(kw("STRETCH-TO-FIT"), optional(kw("RETAIN-SHAPE"))), // kw("TRANSPARENT") // ), index_tuning: ($) => seq( optional(choice(kw("IS"), kw("AS"))), choice( kw("PRIMARY"), kw("UNIQUE"), kw("WORD-INDEX") ) ), of: ($) => seq(kw("OF"), $._name), stream_tuning: ($) => choice( // seq(kw("LOB-DIR"), $.string_literal), seq(kw("NUM-COPIES"), $._integer_literal), seq(kw("MAP"), $.identifier), seq( kw("CONVERT"), optional(seq(kw("TARGET"), $.string_literal)), optional(seq(kw("SOURCE"), $.string_literal)) ), ), stream_flag: ($) => choice( kw("COLLATE"), kw("BINARY"), kw("LANDSCAPE"), kw("PORTRAIT"), kw("APPEND"), kw("ECHO"), kw("NO-ECHO"), kw("KEEP-MESSAGES"), kw("NO-MAP"), kw("PAGED"), kw("UNBUFFERED"), kw("NO-CONVERT") ), _value_tuning: ($) => choice( $._initial, seq(kw("DECIMALS"), $.number_literal), $._extent, kw("NO-UNDO") ), query_definition_tuning: ($) => choice( seq(kw("FIELDS"), $.query_fields), seq(kw("EXCEPT"), $.query_fields), seq(kw("CACHE"), $.number_literal), kw("SCROLLING"), kw("RCODE-INFORMATION") ), query_tuning: ($) => choice( kw("NO-LOCK"), kw("SHARE-LOCK"), kw("EXCLUSIVE-LOCK"), kw("NO-WAIT"), kw("NO-ERROR"), kw("NO-PREFETCH"), seq(kw("USE-INDEX"), $.identifier), $.using ), workfile_tuning: ($) => choice( $.type_tuning, $.field_clause ), repeat_tuning: ($) => seq(kw("WITH"), $._frame), run_tuning: ($) => choice( kw("PERSISTENT"), kw("SINGLE-RUN"), kw("SINGLETON"), kw("ASYNCHRONOUS"), seq(kw("SET"), $.identifier), seq(kw("ON"), kw("SERVER"), $.identifier), seq(kw("IN"), choice(kw("THIS-PROCEDURE"), $.identifier)), seq(kw("EVENT-PROCEDURE"), $.string_literal) ), scope_tuning: ($) => choice(alias($._new_keyword, "NEW"), kw("GLOBAL"), kw("SHARED"), kw("STATIC")), serialization_tuning: ($) => choice(kw("SERIALIZABLE"), kw("NON-SERIALIZABLE")), sort_order: ($) => choice(kw("ASCENDING"), kw("DESCENDING"), kw("DESC"), kw("ASC")), temp_table_tuning: ($) => choice( kw("NO-UNDO"), // seq(kw("NAMESPACE-URI"), $.string_literal), // seq(kw("NAMESPACE-PREFIX"), $.string_literal), // seq(kw("XML-NODE-NAME"), $.string_literal), $._serialize_name, kw("REFERENCE-ONLY"), $.like_phrase, kw("RCODE-INFORMATION"), seq(kw("BEFORE-TABLE"), $.identifier), $.constant ), type_tuning: ($) => choice( seq(kw("AS"), field("type", $._type)), seq(kw("LIKE"), field("type", $._type)) ), using: ($) => seq( kw("USING"), seq($.using_field, repeat(seq(kw("AND"), $.using_field))) ), variable_tuning: ($) => seq( choice( $._serialize_name, // $._bgcolor, // $._fgcolor, // $._pfcolor, // $._dcolor, // $._context_help_id, $._value_tuning, $._format, $._font, $._label, seq(kw("MOUSE-POINTER"), $.identifier), $._column_label, // kw("DROP-TARGET"), seq(optional(kw("NOT")), kw("CASE-SENSITIVE")), ) ), // TYPES _type: ($) => choice( $.primitive_type, $.identifier, $.qualified_name, $.class_type, $.generic_type ), primitive_type: ($) => choice( kw("VOID"), kw("LOGICAL"), kw("INTEGER"), kw("INT"), kw("CHARACTER"), kw("CHAR"), kw("DECIMAL"), kw("DATE"), kw("DATETIME"), kw("DATETIME-TZ"), kw("INT64"), kw("LONGCHAR"), kw("MEMPTR"), kw("RAW"), kw("RECID"), kw("ROWID"), kw("HANDLE"), kw("COM-HANDLE") ), class_type: ($) => seq(kw("CLASS"), $._name), generic_type: ($) => seq($._name, $.generic_expression), return_type: ($) => seq(choice(kw("RETURNS"), kw("RETURN")), field("type", $._type)), member_modifier: ($) => choice(kw("ABSTRACT"), kw("OVERRIDE"), kw("FINAL")), _find_type: ($) => choice(kw("FIRST"), kw("LAST"), kw("NEXT"), kw("PREV"), kw("CURRENT")), // PARAMETERS and others array_access: ($) => prec.right( 1, seq( field("array", choice($.identifier, $.object_access)), $.array_literal, ) ), generic_parameter: ($) => seq($.identifier, $.type_tuning), query_fields: ($) => seq("(", repeat1($.identifier), ")"), argument_mode: ($) => prec.right( choice( alias($._input_keyword, "INPUT"), alias($._output_keyword, "OUTPUT"), kw("INPUT-OUTPUT"), kw("DATA-SOURCE")) ), // TODO: Refactor function_call_argument: ($) => prec.right( 1, seq( optional($.argument_mode), choice( $.ternary_expression, seq( choice($._name, $.object_access), optional($.type_tuning) ), seq( optional( choice( seq(kw("TABLE"), optional(token.immediate(kw("-HANDLE")))), seq(kw("DATASET"), optional(token.immediate(kw("-HANDLE")))) ) ), $._name ), $.input_expression, $.array_access, $.string_literal, $.number_literal, $.null_expression, $._binary_expression, ), optional($.parameter_tuning) ) ), function_parameter: ($) => choice( seq( repeat( choice( $.argument_mode, $._table_option ) ), field("name", $.identifier), optional($.type_tuning), repeat($.parameter_tuning) ), seq( kw("BUFFER"), field("buffer", $.identifier), alias($._for_keyword, "FOR"), field("table", $._name), optional(kw("PRESELECT")) ) ), function_arguments: ($) => seq( "(", optional(_list(alias($.function_call_argument, $.argument), ",")), ")" ), annotation_argument: ($) => seq( "(", $.identifier, "=", $.string_literal, ")" ), inherits: ($) => seq( kw("INHERITS"), _list(choice($.string_literal, $._name), ",") ), implements: ($) => seq( kw("IMPLEMENTS"), _list(choice($.string_literal, $._name), ",") ), // function_parameter_mode: ($) => // choice(alias($._input_keyword, "INPUT"), alias($._output_keyword, "OUTPUT"), kw("INPUT-OUTPUT")), data_relation: ($) => seq( kw("DATA-RELATION"), optional($.identifier), alias($._for_keyword, "FOR"), _list($._name, ","), kw("RELATION-FIELDS"), seq( "(", _list($._name, ","), ")" ) ), object_access: ($) => seq( field( "object", choice($.identifier, $.new_expression, $.function_call) ), repeat1(seq(alias($._namecolon, ":"), field("property", $.identifier))) ), member_access: ($) => seq( field("object", $.identifier), repeat1( seq(alias($._namedoublecolon, "::"), field("property", $.identifier)) ) ), case_condition: ($) => seq(optional(seq(kw("OR"), kw("WHEN"))), choice($._literal, $.boolean_literal)), case_when_branch: ($) => seq(kw("WHEN"), repeat1($.case_condition), kw("THEN"), $._statement_body), case_otherwise_branch: ($) => seq(kw("OTHERWISE"), $._statement_body), where_clause: ($) => seq(kw("WHERE"), field("condition", $._expression)), sort_column: ($) => seq(field("column", choice($._name, $.function_call, $.ternary_expression)), optional($.sort_order)), sort_clause: ($) => seq(optional(kw("BREAK")), seq(kw("BY"), repeat1($.sort_column))), using_field: ($) => seq( optional($._frame), field("field", $._name) ), field_clause: ($) => seq(alias($._field_keyword, "FIELD"), $.identifier, $.type_tuning, repeat($.field_option)), index_clause: ($) => seq( alias($._index_keyword, "INDEX"), $.identifier, repeat($.index_tuning), repeat(seq(field("field", $.identifier), optional($.sort_order))) ), variable: ($) => choice(field("name", $.identifier), $.assignment), enum_member: ($) => seq( field("name", $.identifier), field( "value", optional( seq( kw("="), _list(choice($.identifier, $._literal),",") ) ) ) ), function_call: ($) => prec.right( 1, seq( field( "function", choice($.identifier, prec.right(2, $.object_access)) ), alias($.function_arguments, $.arguments), optional(kw("NO-ERROR")) ) ), getter: ($) => seq( optional($.access_tuning), kw("GET"), optional($._getter_body), $._terminator ), _getter_body: ($) => seq( optional(alias($.function_parameters, $.parameters)), $.body, kw("END"), optional(kw("GET")) ), setter: ($) => seq( optional($.access_tuning), kw("SET"), optional($._setter_body), $._terminator ), _setter_body: ($) => seq( optional(alias($.function_parameters, $.parameters)), $.body, kw("END"), optional(kw("SET")) ), _on_phrase: ($) => choice( $.on_error_phrase, $.on_quit_phrase, $.on_stop_phrase, $.on_endkey_phrase ), action_phrase: ($) => choice( seq(kw("LEAVE"), optional(field("label", $.identifier))), seq(kw("NEXT"), optional(field("label", $.identifier))), seq(kw("RETRY"), optional(field("label", $.identifier))), seq( kw("RETURN"), $._return_action ) ), _return_action: ($) => choice( seq(kw("ERROR"), optional($.identifier)), kw("NO-APPLY"), $._expression ), // PHRASES while_phrase: ($) => seq(kw("WHILE"), field("condition", $._expression)), to_phrase: ($) => seq( $.assignment, kw("TO"), choice($.function_call, $._integer_literal, $.identifier), optional(seq(kw("BY"), $._integer_literal)) ), // combo_box_phrase: ($) => // seq( // kw("COMBO-BOX"), // repeat( // choice( // $._list_items, // $._inner_lines, // $.size_phrase, // kw("SORT"), // $._tooltip, // kw("SIMPLE"), // kw("DROP-DOWN"), // kw("DROP-DOWN-LIST"), // $._max_chars, // seq(kw("AUTO-COMPLETION"), optional(kw("UNIQUE-MATCH"))) // ) // ) // ), // editor_phrase: ($) => // seq( // choice($.size_phrase, // // seq($._inner_chars, $._inner_lines) // ), // repeat( // choice( // seq(kw("BUFFER-CHARS"), $.number_literal), // seq(kw("BUFFER-LINES"), $.number_literal), // kw("LARGE"), // // $._max_chars, // kw("NO-BOX"), // kw("NO-WORD-WRAP"), // kw("SCROLLBAR-HORIZONTAL"), // kw("SCROLLBAR-VERTICAL"), // // $._tooltip // ) // ) // ), // radio_set_phrase: ($) => // seq( // kw("RADIO-SET"), // optional(choice(seq(kw("HORIZONTAL"), optional(kw("EXPAND"))), kw("VERTICAL"))), // seq( // kw("RADIO-BUTTONS"), // field("label", $.identifier), ",", field("value", $.identifier), // repeat(seq(",", field("label", $.identifier), ",", field("value", $.identifier))) // ), // optional($._tooltip) // ), // selection_list_phrase: ($) => // seq( // kw("SELECTION-LIST"), // repeat1( // choice( // kw("SINGLE"), // kw("MULTIPLE"), // kw("NO-DRAG"), // $._list_items, // kw("SCROLLBAR-HORIZONTAL"), // kw("SCROLLBAR-VERTICAL"), // $.size_phrase, // // seq($._inner_chars, $._inner_lines), // kw("SORT"), // $._tooltip // ) // ), // ), // slider_phrase: ($) => // seq( // kw("SLIDER"), // seq(kw("MAX-VALUE"), $.number_literal, kw("MIN-VALUE"), $.number_literal), // repeat( // choice( // kw("HORIZONTAL"), // kw("VERTICAL"), // kw("NO-CURRENT-VALUE"), // kw("LARGE-TO-SMALL"), // seq( // kw("TIC-MARKS"), // choice(kw("NONE"), kw("TOP"), kw("BOTTOM"), kw("LEFT"), kw("RIGHT"), kw("BOTH")), // optional(seq(kw("FREQUENCY"), $.number_literal)) // ), // $._tooltip, // $.size_phrase // ) // ) // ), view_as_phrase: ($) => seq( kw("VIEW-AS"), choice( // $.combo_box_phrase, // $.editor_phrase, // $.radio_set_phrase, // $.selection_list_phrase, // $.slider_phrase, // seq( // kw("FILL-IN"), // repeat( // choice( // kw("NATIVE"), // $.size_phrase, // $._tooltip // ) // ) // ), seq( kw("TEXT"), // repeat(choice(kw("NATIVE"), $.size_phrase, $._tooltip)) ), // seq(kw("TOGGLE-BOX"), repeat(choice(kw("NATIVE"), $.size_phrase, $._tooltip))), ) ), on_error_phrase: ($) => seq( kw("ON"), kw("ERROR"), kw("UNDO"), optional(field("label", $.identifier)), ",", choice( $.action_phrase, kw("THROW") ) ), on_stop_phrase: ($) => seq( kw("ON"), kw("STOP"), kw("UNDO"), optional(field("label", $.identifier)), ",", $.action_phrase ), on_quit_phrase: ($) => seq( kw("ON"), kw("QUIT"), optional(seq(kw("UNDO"), optional($.identifier))), ",", $.action_phrase ), on_endkey_phrase: ($) => seq( kw("ON"), kw("ENDKEY"), optional(seq(kw("UNDO"), optional($.identifier))), ",", $.action_phrase ), frame_phrase: ($) => seq( kw("WITH"), repeat1( choice( seq(kw("ACCUM"), optional($._integer_literal)), // $.at_phrase, // TODO seq(kw("CANCEL-BUTTON"), $.identifier), kw("CENTERED"), // color specification $._position, seq($.number_literal, kw("COLUMNS")), kw("CONTEXT-HELP"), // seq(kw("CONTEXT-HELP-FILE"), $.identifier), seq(kw("DEFAULT-BUTTON"), $.identifier), // kw("DROP-TARGET"), seq(optional($._expression), kw("DOWN")), // kw("EXPORT"), seq(kw("WIDGET-ID"), $.number_literal), $._font, $._frame, // kw("INHERIT-BGCOLOR"), // kw("NO-INHERIT-BGCOLOR"), // kw("INHERIT-FGCOLOR"), // kw("NO-INHERIT-FGCOLOR"), // kw("KEEP-TAB-ORDER"), kw("NO-BOX"), kw("NO-HIDE"), kw("NO-LABELS"), // kw("USE-DICT-EXPS"), kw("NO-VALIDATE"), // kw("NO-AUTO-VALIDATE"), // kw("NO-HELP"), // kw("NO-UNDERLINE"), // kw("OVERLAY"), // kw("PAGE-BOTTOM"), // kw("PAGE-TOP"), // seq(kw("RETAIN"), $.number_literal), // kw("SCREEN-IO"), kw("STREAM-IO"), seq(kw("SCROLL"), $.number_literal), kw("SCROLLABLE"), kw("SIDE-LABELS"), $.size_phrase, seq(kw("STREAM"), field("stream", $.identifier)), seq(kw("STREAM-HANDLE"), field("stream_handle", $.identifier)), // kw("THREE-D"), // title phrase kw("TOP-ONLY"), kw("USE-TEXT"), // seq(kw("V6FRAME"), optional(choice(kw("USE-REVVIDEO"), kw("USE-UNDERLINE")))), seq(kw("VIEW-AS"), kw("DIALOG-BOX")), seq(kw("WIDTH"), $.number_literal), seq(kw("IN-WINDOW"), $.identifier), // $._option_with_number, // $._color_option ) ) ), // _option_with_number: ($) => // seq( // choice( // kw("WIDTH"), // kw("SCROLL"), // kw("RETAIN"), // kw("WIDGET-ID") // ), // $.number_literal // ), // _color_option: ($) => // choice( // kw("INHERIT-BGCOLOR"), // kw("NO-INHERIT-BGCOLOR"), // kw("INHERIT-FGCOLOR"), // kw("NO-INHERIT-FGCOLOR"), // ), stop_after_phrase: ($) => seq(kw("STOP-AFTER"), $._integer_literal), do_for_phrase: ($) => seq( kw("FOR"), _list($._name, ",") ), // widget_phrase: ($) => // choice( // $._frame, // seq( // optional(alias($._field_keyword, "FIELD")), // $.identifier, // optional(seq(kw("IN"), $._frame)) // ), // seq( // $.identifier, // optional(seq(kw("IN"), kw("BROWSE"), $.identifier)) // ), // seq(choice(kw("MENU"), kw("SUB-MENU")), $.identifier), // seq(kw("MENU-ITEM"), $.identifier, optional(seq(kw("IN"), kw("MENU"), $.identifier))), // _list($.identifier, ",") // ), referencing_phrase: ($) => seq( alias($._new_keyword, "NEW"), optional(kw("BUFFER")), $.identifier, alias($._old_keyword, "OLD"), optional(kw("BUFFER")), $.identifier, ), // of_phrase: ($) => // seq( // kw("OF"), // $.widget_phrase, // ), _on_statement_database_phrase: ($) => prec(2, seq( choice( kw("CREATE"), kw("DELETE"), kw("FIND"), kw("WRITE"), kw("ASSIGN"), ), kw("OF"), _list($._name, ","), optional($.referencing_phrase), optional(kw("OVERRIDE")), choice($.do_block, kw("REVERT")) )), // _on_statement_widget_phrase: ($) => // prec(2, seq( // _list(choice($.identifier, $.constant), ","), // $.of_phrase, // repeat( // seq( // kw("OR"), // _list(choice($.identifier, $.constant), ","), // $.of_phrase // ) // ), // optional(kw("ANYWHERE")), // choice($.do_block, prec(2, $._statement), kw("REVERT"), seq(kw("PERSISTENT"), $.run_statement)) // )), // TODO: Refactor // image_phrase: ($) => // seq( // choice(kw("IMAGE"), kw("IMAGE-UP"), kw("IMAGE-DOWN"), kw("IMAGE-INSENSITIVE")), // seq(kw("FILE"), $.string_literal), // optional( // $.size_phrase // ), // optional( // seq( // kw("FROM"), // repeat1($._position) // ) // ) // ), _position: ($) => seq( choice( kw("X"), kw("Y"), kw("ROW"), kw("COLUMN") ), $.number_literal ), size_phrase: ($) => seq( choice( kw("SIZE"), kw("SIZE-CHARS"), kw("SIZE-PIXELS"), kw("IMAGE-SIZE"), kw("IMAGE-SIZE-CHARS"), kw("IMAGE-SIZE-PIXELS") ), field("width", $.number_literal), kw("BY"), field("height", $.number_literal) ), preselect_phrase: ($) => seq( kw("PRESELECT"), _list($._for_phrase, ","), ), _for_phrase: ($) => seq( optional(field("type", choice(kw("EACH"), kw("FIRST"), kw("LAST")))), field("table", $._name), repeat( choice( $.of, $.query_tuning, $.where_clause, $.sort_clause ) ) ), like_phrase: ($) => seq( choice(kw("LIKE"), kw("LIKE-SEQUENTIAL")), $.identifier, optional(kw("VALIDATE")), optional(seq(kw("USE-INDEX"), $.identifier, optional(seq(kw("AS"), kw("PRIMARY"))))) ), // OPTIONAL SEQUENCES // _bgcolor: ($) => seq(kw("BGCOLOR"), $._integer_literal), _column_label: ($) => seq(kw("COLUMN-LABEL"), $.string_literal), // _context_help_id: ($) => seq(kw("CONTEXT-HELP-ID"), $._integer_literal), // _dcolor: ($) => seq(kw("DCOLOR"), $._integer_literal), // _decimals: ($) => seq(kw("DECIMALS"), $.number_literal), _extent: ($) => seq(kw("EXTENT"), $.number_literal), // _fgcolor: ($) => seq(kw("FGCOLOR"), $._integer_literal), _font: ($) => seq(kw("FONT"), $._integer_literal), _format: ($) => seq(kw("FORMAT"), $.string_literal), _frame: ($) => seq(kw("FRAME"), field("frame", choice($.identifier, $.constant))), _initial: ($) => seq( choice(kw("INITIAL"), kw("INIT")), choice( $._literal, $.array_literal, $.boolean_literal, $.null_expression, $.identifier, $.object_access )), // _inner_chars: ($) => seq(kw("INNER-CHARS"), $.number_literal), // _inner_lines: ($) => seq(kw("INNER-LINES"), $.number_literal), _label: ($) => seq(kw("LABEL"), _list($.string_literal, ",")), // _list_items: ($) => // seq( // choice( // kw("LIST-ITEMS"), // kw("LIST-ITEM-PAIRS")), // _list($.string_literal,",") // ), // _max_chars: ($) => seq(kw("MAX-CHARS"), $.number_literal), // _pfcolor: ($) => seq(kw("PFCOLOR"), $._integer_literal), _serialize_name: ($) => seq(kw("SERIALIZE-NAME"), $.string_literal), // _tooltip: ($) => seq(kw("TOOLTIP"), $.string_literal), // DEFINITIONS _definition: ($) => choice( $.variable_definition, $.buffer_definition, // $.button_definition, $.query_definition, $.temp_table_definition, $.workfile_definition, $.property_definition, $.data_source_definition, $.event_definition, $.dataset_definition, $.stream_definition, // $.image_definition, // $.frame_definition, $.parameter_definition ), buffer_definition: ($) => seq( $._define, repeat($._tuning), kw("BUFFER"), field("name", $.identifier), alias($._for_keyword, "FOR"), optional(kw("TEMP-TABLE")), field("table", $._name), $._terminator ), // button_definition: ($) => // seq( // $._define, // repeat($._tuning), // kw("BUTTON"), // field("name", $.identifier), // repeat($.button_tuning), // ), dataset_definition: ($) => seq( $._define, repeat($._tuning), kw("DATASET"), field("name", $.identifier), alias($._for_keyword, "FOR"), _list($._name, ","), optional($.data_relation), $._terminator ), data_source_definition: ($) => seq( $._define, repeat($._tuning), kw("DATA-SOURCE"), $.identifier, alias($._for_keyword, "FOR"), repeat($._data_source_definition_option), $._terminator ), _data_source_definition_option: ($) => choice( seq(kw("QUERY"), $.identifier), _list($._name, ",") ), enum_definition: ($) => seq( $._define, kw("ENUM"), repeat($.enum_member), $._terminator ), event_definition: ($) => seq( $._define, repeat($._tuning), kw("EVENT"), $.identifier, optional(kw("SIGNATURE")), kw("VOID"), alias($.function_parameters, $.parameters), $._terminator ), // frame_definition: ($) => // seq( // $._define, // repeat($._tuning), // kw("FRAME"), // field("name", $.identifier), // // form item // seq(optional(choice(kw("HEADER"), kw("BACKGROUND")))), // head item // optional($.frame_phrase) // ), // image_definition: ($) => // seq( // $._define, // repeat($._tuning), // kw("IMAGE"), // field("name", $.identifier), // $._image_definition_option, // // repeat($.image_tuning), // $._terminator // ), // _image_definition_option: ($) => // choice( // $.size_phrase, // $.image_phrase, // seq(kw("LIKE"), $.identifier) // ), parameter_definition: ($) => seq( $._define, optional( choice(alias($._input_keyword, "INPUT"), alias($._output_keyword, "OUTPUT"), kw("INPUT-OUTPUT"), kw("RETURN")) ), $._parameter_definition_option, field("name", $.identifier), choice( seq($.type_tuning, repeat($.variable_tuning)), repeat($.parameter_tuning) ), $._terminator ), _table_option: ($) => choice( kw("TABLE "), kw("TABLE-HANDLE"), kw("DATASET-HANDLE"), kw("DATASET ") ), _parameter_definition_option: ($) => seq( choice(kw("PARAMETER"), kw("PARAM")), optional( choice( seq(kw("BUFFER"), field("buffer", $.identifier)), kw("TABLE"), kw("TABLE-HANDLE"), seq(kw("DATASET"), optional(token.immediate(kw("-HANDLE")))) ) ), optional(alias($._for_keyword, "FOR")), ), property_definition: ($) => seq( $._define, repeat($._tuning), kw("PROPERTY"), field("name", $.identifier), $.type_tuning, repeat($._value_tuning), choice(seq($.getter, $.setter), $._terminator) ), query_definition: ($) => seq( $._define, repeat($._tuning), kw("QUERY"), field("name", $.identifier), alias($._for_keyword, "FOR"), $.identifier, repeat($.query_definition_tuning), $._terminator ), stream_definition: ($) => seq( $._define, repeat($._tuning), kw("STREAM"), field("name", $.identifier), $._terminator ), temp_table_definition: ($) => seq( $._define, repeat($._tuning), optional($.serialization_tuning), kw("TEMP-TABLE"), field("name", $.identifier), repeat($.temp_table_tuning), repeat($._temp_table_member), $._terminator ), _temp_table_member: ($) => choice( $.field_clause, $.index_clause, $.include ), variable_definition: ($) => seq( $._define, repeat($._tuning), choice(kw("VARIABLE"), alias($._var_keyword, "VAR")), field("name", $.identifier), $.type_tuning, repeat( choice( $.variable_tuning, $.view_as_phrase )), $._terminator ), workfile_definition: ($) => seq( $._define, repeat($._tuning), choice(kw("WORKFILE"), kw("WORK-TABLE")), field("name", $.identifier), repeat($.workfile_tuning), $._terminator ), // STATEMENTS null_statement: ($) => seq($.object_access, $._terminator), using_statement: ($) => seq( kw("USING"), $._name, optional(seq(kw("FROM"), choice(kw("ASSEMBLY"), kw("PROPATH")))), $._terminator ), interface_statement: ($) => seq( kw("INTERFACE"), field("name", choice($.string_literal, $._name)), optional($.inherits), alias($.interface_body, $.body), $._block_terminator ), class_statement: ($) => seq( kw("CLASS"), field("name", choice($.string_literal, $._name)), repeat($.class_tuning), alias($.class_body, $.body), $._block_terminator ), constructor_statement: ($) => seq( kw("CONSTRUCTOR"), repeat(choice($.scope_tuning, $.access_tuning)), $.identifier, alias($.function_parameters, $.parameters), $.body, $._block_terminator ), destructor_statement: ($) => seq( kw("DESTRUCTOR"), optional(kw("PUBLIC")), $.identifier, seq("(", ")"), $.body, $._block_terminator ), method_statement: ($) => seq( kw("METHOD"), repeat($._tuning), alias($._type, $.return_type), optional($._extent), field("name", $.identifier), alias($.function_parameters, $.parameters), optional(seq($.body, kw("END"), optional(kw("METHOD")))), $._terminator ), procedure_statement: ($) => seq( kw("PROCEDURE"), $.identifier, optional(kw("PRIVATE")), optional($.body), $._block_terminator ), case_statement: ($) => seq( kw("CASE"), $._expression, alias($.case_body, $.body), $._block_terminator ), variable_assignment: ($) => seq($.assignment, $._terminator), assignment: ($) => prec.right( PREC.ASSIGN, seq( prec.left( field( "name", choice( $.identifier, $.qualified_name, $.object_access, $.member_access, $.function_call, $.array_access ) ) ), $.assignment_operator, prec.right(choice($._expression, $.include)), optional($.when_expression) ) ), function_call_statement: ($) => seq($.function_call, $._terminator), function_statement: ($) => seq( kw("FUNCTION"), field("name", $.identifier), $.return_type, optional($._extent), optional(alias($.function_parameters, $.parameters)), optional(alias($.dot_body, $.body)), $._block_terminator ), repeat_statement: ($) => seq( optional($.label), kw("REPEAT"), repeat($._repeat_phrase), optional($.preselect_phrase), optional($.while_phrase), optional($._on_phrase), $.body, $._block_terminator ), _repeat_phrase: ($) => choice( $.to_phrase, $.repeat_tuning ), return_statement: ($) => seq( kw("RETURN"), optional($._return_action), $._terminator ), input_output_statement: ($) => seq( choice(alias($._input_keyword, "INPUT"), alias($._output_keyword, "OUTPUT")), optional( seq( choice(kw("STREAM"), kw("STREAM-HANDLE")), field("name", $.identifier) ), ), $._input_output_option, repeat($.stream_tuning), repeat($.stream_flag), $._terminator ), _input_output_option: ($) => choice( kw("CLOSE"), seq( choice(kw("FROM"), kw("TO")), choice($.string_literal, $.function_call) ) ), for_statement: ($) => seq( optional($.label), alias($._for_keyword, "FOR"), _list($._for_phrase, ","), repeat(choice($._on_phrase, $.frame_phrase)), $.body, $._block_terminator ), find_statement: ($) => seq( kw("FIND"), field("type", optional($._find_type)), field("table", $._name), repeat( choice( $.of, $.query_tuning, $.where_clause ) ), $._terminator ), abl_statement: ($) => seq( field("statement", $.identifier), repeat(prec(-1, $._expression)), $._terminator ), assign_statement: ($) => seq( kw("ASSIGN"), repeat1($.assignment), optional(kw("NO-ERROR")), $._terminator ), catch_statement: ($) => seq( kw("CATCH"), field("variable", $.identifier), kw("AS"), field( "type", seq(optional(kw("CLASS")), $._name) ), $.body, $._block_terminator ), finally_statement: ($) => seq( kw("FINALLY"), $.body, $._block_terminator ), accumulate_statement: ($) => seq( kw("ACCUMULATE"), choice($._name, $._binary_expression), seq( "(", repeat1($.accumulate_aggregate), ")" ), $._terminator ), undo_statement: ($) => seq( kw("UNDO"), optional(field("label", $.identifier)), ",", choice( $.action_phrase, seq(kw("THROW"), choice($.new_expression, $.identifier)) ), $._terminator ), error_scope_statement: ($) => seq( choice(kw("ROUTINE-LEVEL"), kw("BLOCK-LEVEL")), $.on_error_phrase, $._terminator ), on_statement: ($) => seq( kw("ON"), choice( // $._on_statement_widget_phrase, $._on_statement_database_phrase, seq(field("label", $.identifier), field("function", $.identifier), $._terminator), // seq(alias("\"WEB-NOTIFY\"", $.string_literal), kw("ANYWHERE"), $._statement_body) ) ), prompt_for_statement: ($) => seq( kw("PROMPT-FOR"), $._name, optional($._frame), choice(seq(kw("EDITING"), $.body, $._block_terminator), $._terminator) ), var_statement: ($) => seq( alias($._var_keyword, "VAR"), optional( choice($.scope_tuning, $.access_tuning, $.serialization_tuning) ), alias(choice($._type, $.string_literal), $.type_tuning), optional(field("size", $.array_literal)), _list($.variable, ","), $._terminator ), run_statement: ($) => seq( kw("RUN"), field( "procedure", choice($._name, $.function_call, $.file_name) ), repeat($.run_tuning), optional(alias($.function_arguments, $.arguments)), optional(kw("NO-ERROR")), $._terminator ), enum_statement: ($) => seq( kw("ENUM"), field("name", $.identifier), optional(kw("FLAGS")), alias($.enum_body, $.body), $._block_terminator ), do_block: ($) => seq( optional($.label), kw("DO"), repeat($._do_tuning), optional($._on_phrase), optional($.frame_phrase), $.body, $._block_terminator ), _do_tuning: ($) => choice( $.do_for_phrase, $.preselect_phrase, $.to_phrase, $.while_phrase, $.stop_after_phrase, kw("TRANSACTION") ), if_statement: ($) => seq( $._if_phrase, $._statement_body, repeat($.else_statement) ), _if_phrase: ($) => seq( kw("IF"), field("condition", $._expression), kw("THEN") ), else_statement: ($) => prec( 1, seq( kw("ELSE"), optional($._if_phrase), $._statement_body ) ), // EXPRESSIONS null_expression: ($) => /\?/, parenthesized_expression: ($) => seq("(", $._expression, ")"), generic_expression: ($) => seq( "<", _list(choice($._name, $.generic_parameter), ","), ">" ), logical_expression: ($) => prec.right( PREC.LOGICAL, seq($._expression, $._logical_operator, $._expression) ), _unary_minus_expression: ($) => choice( $.identifier, $.number_literal, $.function_call, $.qualified_name, $.object_access, $.member_access, $.parenthesized_expression ), unary_expression: ($) => choice( prec.left( PREC.UNARY, seq(kw("-"), prec.left($._unary_minus_expression)) ), prec.left( PREC.LOGICAL, seq(kw("NOT"), prec.left(PREC.LOGICAL, $._expression)) ) ), ambiguous_expression: ($) => seq(kw("AMBIGUOUS"), $._name), temp_table_expression: ($) => seq(kw("TEMP-TABLE"), field("table", $.identifier)), current_changed_expression: ($) => seq(kw("CURRENT-CHANGED"), $._name), locked_expression: ($) => seq(kw("LOCKED"), $._name), // dataset_expression: ($) => seq(prec.left(kw("DATASET")), $._name), when_expression: ($) => seq(kw("WHEN"), $._expression), input_expression: ($) => seq( alias($._input_keyword, "INPUT"), optional($._frame), field("field", $._name) ), additive_expression: ($) => prec.left( PREC.ADD, seq($._expression, $._additive_operator, $._expression) ), multiplicative_expression: ($) => prec.left( PREC.MULTI, seq($._expression, $._multiplicative_operator, $._expression) ), comparison_expression: ($) => prec.right( PREC.COMPARE, seq($._expression, $._comparison_operator, $._expression) ), _binary_expression: ($) => choice( $.additive_expression, $.multiplicative_expression, $.comparison_expression, $.logical_expression ), can_find_expression: ($) => seq( kw("CAN-FIND"), "(", $._can_find_body, ")" ), _can_find_body: ($) => seq( optional(choice(kw("FIRST"), kw("LAST"))), field("table", $._name), optional(field("constant", $._literal)), repeat(choice($.query_tuning, $.of, $.where_clause)), ), accumulate_expression: ($) => seq(kw("ACCUM"), $.accumulate_aggregate, $._expression), available_expression: ($) => seq( choice(kw("AVAIL"), kw("AVAILABLE")), $.identifier ), new_expression: ($) => prec.right( seq( choice(alias($._new_keyword, "NEW"), kw("DYNAMIC-NEW")), $._name, alias($.function_arguments, $.arguments), optional(kw("NO-ERROR")) ) ), ternary_expression: ($) => prec.right( seq( kw("IF"), field("condition", $._expression), kw("THEN"), field("then", $._expression), kw("ELSE"), field("else", $._expression) ) ), // SUPERTYPES _expression: ($) => choice( $.parenthesized_expression, $.unary_expression, $.null_expression, $._binary_expression, $.ternary_expression, $.available