// Using the informal draft spec to support the newest features of dart // https://spec.dart.dev/DartLangSpecDraft.pdf const DIGITS = token(sep1(/[0-9]+/, /_+/)) const HEX_DIGITS = token(sep1(/[A-Fa-f0-9]+/, '_')) //Everything above RelationalTypeCast was incremented from its original value //This was to get type casting issues finally fixed. const DART_PREC = { IMPORT_EXPORT: 19, TYPE_IDENTIFIER: 18, //was: 17 DOT_IDENTIFIER: 19, //was: 18 UNARY_POSTFIX: 17, UNARY_PREFIX: 16, Multiplicative: 15, // *, /, ˜/, % Left Additive: 14, // +, - Left Shift: 13, // <<, >>, >>> Left TYPE_ARGUMENTS: 13, Bitwise_AND: 12, // & Left Bitwise_XOR: 11, // ˆ Left Bitwise_Or: 10, // | Left RelationalTypeCast: 9, // <, >, <=, >=, as, is, is! None 8 RelationalTypeTest: 9, Relational: 8, // <, >, <=, >=, as, is, is! None 8 Equality: 7, // ==, != None 7 Logical_AND: 6, // AND && Left Logical_OR: 5, // Or || Left If: 4, //-null ?? Left Conditional: 3, // e1?e2:e3 Right 3 Cascade: 2, // .. Left Assignment: 1, // =, *=, /=, +=, -=, &=, ˆ=, etc. Right BUILTIN: 0, TRY: 0, // Added by Ben for experimentation. SELECTOR_IN_PRIMARY: 1, SELECTOR_IN_ASSIGNMENT: 0, TYPE_ARGS: 1 }; // TODO: general things to add // both string types //get protocols in classes? // todo: type test operators: as, is, and is! //todo: assignment operators: ??=, and ~/= //todo: ?? operator // todo: cascade notation: dot dot accesses each object //todo: conditional member access: blah?.foo //todo: rethrow keyword //todo: override operator notations //todo: correct import statements to be strings //todo: sync* and async* functions, plus yields //DONE: override shorter constructor notations? module.exports = grammar({ name: 'dart', externals: $ => [ $._template_chars_double, $._template_chars_single, $._template_chars_double_single, $._template_chars_single_single, $._template_chars_raw_slash, $._block_comment, $._documentation_block_comment, ], extras: $ => [ $.comment, $.documentation_comment, /\s/ ], supertypes: $ => [ // $._expression, $._declaration, $._statement, $._literal, // $._element // $._primary_pattern // $._primary, // $._type, ], inline: $ => [ $._ambiguous_name, $._class_member_definition, $._if_null_expression, ], conflicts: $ => [ [$._record_literal_no_const, $.record_field], [$.block, $.set_or_map_literal], [$._primary, $.function_signature], [$._type_name, $._primary, $.function_signature], [$._primary, $._type_name], [$.variable_declaration, $.initialized_variable_definition,], [$._final_const_var_or_type, $.function_signature,], [$._primary, $._function_formal_parameter], [$._primary, $._simple_formal_parameter], [$._primary, $.labeled_statement], [$._primary, $._type_name, $._function_formal_parameter], [$._final_const_var_or_type, $._function_formal_parameter], [$._primary, $.constructor_param], [$._normal_formal_parameters], [$._declared_identifier], [$.equality_expression], [$.annotation, $.marker_annotation], [$._primary, $._type_name, $._simple_formal_parameter], [$.record_type_field, $._function_formal_parameter, $._var_or_type], [$.typed_identifier, $._var_or_type, $._function_formal_parameter], [$._type_name, $._simple_formal_parameter], [$._type_not_function, $._type_not_void], [$.switch_statement_case], // [$._argument_list], [$.variable_declaration, $.initialized_identifier,], [$.declaration, $._external_and_static], [$.method_signature, $._static_or_covariant], [$.constructor_signature, $._formal_parameter_part], // [$._type_not_function, $._type_not_void], [$._cascade_subsection], [$._expression], // [$._real_expression, $._below_relational_expression], [$._postfix_expression], [$.pattern_variable_declaration, $._var_or_type], [$._final_const_var_or_type, $.pattern_variable_declaration], [$.type_arguments, $.relational_operator], [$.prefix_operator, $.constant_pattern], [$._primary, $.constant_pattern, $._type_name], [$.parenthesized_expression, $.if_statement], [$._top_level_definition, $.lambda_expression], [$._literal, $.constant_pattern], [$._primary, $.constant_pattern], [$._type_not_void_not_function, $.qualified], [$._final_var_or_type], [$._primary, $.constant_pattern, $._type_name, $._simple_formal_parameter], [$._parenthesized_pattern, $._pattern_field], [$.record_type_field, $._var_or_type, $._final_var_or_type, $._function_formal_parameter], [$._var_or_type, $._final_var_or_type], [$._final_const_var_or_type, $._final_var_or_type], [$._var_or_type, $._for_loop_parts, $.pattern_variable_declaration], [$.pattern_variable_declaration, $._for_loop_parts, $._final_const_var_or_type], [$._var_or_type, $._final_var_or_type, $._function_formal_parameter], [$.set_or_map_literal, $.map_pattern], [$.list_literal, $.list_pattern], [$._real_expression, $._pattern], [$.constant_pattern, $._type_name], [$._pattern_field, $.label], [$._pattern], [$.constructor_tearoff, $._identifier_or_new], [$._primary, $.constant_pattern, $._simple_formal_parameter], [$.record_type_field, $._final_var_or_type], [$._var_or_type, $._final_var_or_type, $.function_signature], [$._top_level_definition, $._var_or_type, $.function_signature], [$.set_or_map_literal, $.constant_pattern], [$.list_literal, $.constant_pattern], [$.set_or_map_literal, $.block, $.map_pattern], [$._var_or_type, $.function_signature], [$._var_or_type, $._function_formal_parameter], [$.relational_operator, $.type_arguments, $.type_parameters], [$._var_or_type], [$._top_level_definition, $._var_or_type], [$._top_level_definition, $._final_const_var_or_type], [$._top_level_definition, $.const_object_expression, $._final_const_var_or_type], [$._final_const_var_or_type, $.const_object_expression], [$._final_const_var_or_type], [$.type_parameter, $._type_name], [$._normal_formal_parameter], [$.library_name, $.dotted_identifier_list], [$._top_level_definition, $.inferred_type], [$._final_const_var_or_type, $._top_level_definition, $.function_signature], [$._assignable_selector_part, $.selector], [$._assignable_selector_part, $._postfix_expression], [$._assignable_selector_part, $.postfix_expression], [$._primary, $.assignable_expression], [$._simple_formal_parameter, $.assignable_expression], // [$._type_name, $._primary, $.assignable_expression], [$.assignable_expression, $.postfix_expression], [$.assignable_expression, $._postfix_expression], // [$._type_name, $.assignable_expression], // [$._type_name, $.function_signature], [$._type_name, $._function_formal_parameter], [$._type_name], // [$.assignment_expression, $._expression], [$.assignable_expression], [$.method_signature, $.declaration, $._static_or_covariant], [$.type_arguments], [$._primary, $._type_name, $.assignable_expression], [$._primary, $._type_name, $.assignable_expression, $.function_signature], [$._primary, $._type_name, $.assignable_expression, $._function_formal_parameter], [$._type_name, $.function_signature], // [$.relational_operator, $._shift_operator], [$.declaration, $._external], [$.relational_expression], [$.factory_constructor_signature, $.redirecting_factory_constructor_signature], [$._function_type_tail], [$._type_not_void_not_function, $._function_type_tail], [$._type_not_void], [$._type_not_void_not_function], [$.super_formal_parameter, $.unconditional_assignable_selector], [$.function_signature], ], word: $ => $.identifier, rules: { // Page 188 libraryDeclaration program: $ => seq( optional($.script_tag), optional($.library_name), repeat($.import_or_export), repeat($.part_directive), repeat($.part_of_directive), repeat($._top_level_definition), ), // Page 187 topLevelDefinition _top_level_definition: $ => choice( $.class_definition, $.mixin_declaration, $.extension_declaration, $.enum_declaration, $.type_alias, seq( optional($._metadata), optional($._external_builtin), $.function_signature, $._semicolon ), seq( optional($._metadata), optional($._external_builtin), $.getter_signature, $._semicolon ), seq( optional($._metadata), optional($._external_builtin), $.setter_signature, $._semicolon ), seq( optional($._metadata), $.getter_signature, $.function_body ), seq( optional($._metadata), $.setter_signature, $.function_body ), seq( optional($._metadata), $.function_signature, $.function_body ), // final or const static final declaration list seq( optional($._metadata), choice( $.final_builtin, $.const_builtin ), optional($._type), $.static_final_declaration_list, $._semicolon ), seq( optional($._metadata), $._late_builtin, $.final_builtin, optional($._type), $.initialized_identifier_list, $._semicolon ), seq( optional($._metadata), optional($._late_builtin), choice($._type, $.inferred_type), $.initialized_identifier_list, $._semicolon ) ), /************************************************************************************************** *********************************Literals********************************************************** *************************************************************************************************** ****These are the Literals from section 16.4-9 (Page 84-110) of the dart specification************* *************************************************************************************************** ***************************************************************************************************/ _bool_literal: $ => choice($.true, $.false), _numeric_literal: $ => choice( $.decimal_integer_literal, $.decimal_floating_point_literal, $.hex_integer_literal, ), _literal: $ => choice( $.null_literal, $._bool_literal, $._numeric_literal, $.string_literal, $.symbol_literal, $.set_or_map_literal, $.list_literal, $.record_literal, ), /****This is the symbol literals from section 16.8 (Page 99) of the dart specification****************/ symbol_literal: $ => seq('#', $.identifier), //symbol literal can also be an operator? /************************************************************************************************** *********************************Numeric Literals************************************************** *************************************************************************************************** ****These are the Numeric Literals from section 16.5 (Page 84-85) of the dart specification******** *************************************************************************************************** ***************************************************************************************************/ decimal_integer_literal: $ => token(DIGITS), hex_integer_literal: $ => token(seq( choice('0x', '0X'), HEX_DIGITS )), decimal_floating_point_literal: $ => token(choice( seq(DIGITS, '.', DIGITS, optional(seq((/[eE]/), optional(choice('-', '+')), DIGITS))), seq('.', DIGITS, optional(seq((/[eE]/), optional(choice('-', '+')), DIGITS))), seq(DIGITS, /[eE]/, optional(choice('-', '+')), DIGITS), seq(DIGITS, optional(seq((/[eE]/), optional(choice('-', '+')), DIGITS))) )), /************************************************************************************************** *********************************Boolean Literals************************************************** *************************************************************************************************** ****These are the boolean from section 16.6 (Page 86) of the dart specification******************** *************************************************************************************************** ***************************************************************************************************/ true: $ => prec( DART_PREC.BUILTIN, 'true', ), false: $ => prec( DART_PREC.BUILTIN, 'false', ), /************************************************************************************************** *********************************String Parts****************************************************** *************************************************************************************************** ****These are the parts of String from section 16.7 (Page 86-92) of the dart specification********* *************************************************************************************************** ***************************************************************************************************/ string_literal: $ => repeat1( choice( $._string_literal_double_quotes, $._string_literal_single_quotes, $._string_literal_double_quotes_multiple, $._string_literal_single_quotes_multiple, //raw, separate later $._raw_string_literal_double_quotes, $._raw_string_literal_single_quotes, $._raw_string_literal_double_quotes_multiple, $._raw_string_literal_single_quotes_multiple, ), ), _string_literal_double_quotes: $ => seq( '"', repeat( choice( $._template_chars_double_single, '\'', $.escape_sequence, $._sub_string_test, $.template_substitution ) ), '"' ), _string_literal_single_quotes: $ => seq( '\'', repeat(choice( $._template_chars_single_single, '"', $.escape_sequence, $._sub_string_test, $.template_substitution )), '\'' ), _string_literal_double_quotes_multiple: $ => prec.left( seq( '"""', repeat(choice( $._template_chars_double, '\'', '\"', $.escape_sequence, $._sub_string_test, $.template_substitution )), '"""' ), ), _string_literal_single_quotes_multiple: $ => prec.left( seq( '\'\'\'', repeat(choice( $._template_chars_single, '"', '\'', $.escape_sequence, $._sub_string_test, $.template_substitution )), '\'\'\'' ), ), _raw_string_literal_double_quotes: $ => seq( 'r"', repeat(choice( $._template_chars_double_single, // /[^\n"]*/, '\'', $._template_chars_raw_slash, // '\\', $._unused_escape_sequence, $._sub_string_test, '$' )), '"' ), _raw_string_literal_single_quotes: $ => seq( 'r\'', repeat(choice( $._template_chars_single_single, // /[^\n']/, '"', $._template_chars_raw_slash, // '\\', $._unused_escape_sequence, $._sub_string_test, '$' )), '\'' ), _raw_string_literal_double_quotes_multiple: $ => prec.left( seq( 'r"""', // $._triple_double_quote_end, repeat(choice( $._template_chars_double, '\'', // '\\', $._template_chars_raw_slash, '"', $._unused_escape_sequence, $._sub_string_test, '$' )), '"""' // $._triple_double_quote_end ), ), _raw_string_literal_single_quotes_multiple: $ => prec.left( seq( 'r\'\'\'', // $._triple_quote_end, repeat(choice( $._template_chars_single, '"', '\'', // '\\', $._template_chars_raw_slash, $._unused_escape_sequence, $._sub_string_test, '$' )), '\'\'\'' // $._triple_quote_end ), ), _triple_quote_end: $ => token('\'\'\''), _triple_double_quote_end: $ => token('"""'), template_substitution: $ => seq( '$', choice( seq('{', $._expression, '}'), $.identifier_dollar_escaped ) ), _sub_string_test: $ => seq('$', /[^a-zA-Z_{]/), _string_interp: $ => /\$((\w+)|\{([^{}]+)\})/, // represents $word or ${word} for now _unused_escape_sequence: $ => token.immediate(seq( '\\', choice( /[^xu0-7]/, /[0-7]{1,3}/, /x[0-9a-fA-F]{2}/, /u[0-9a-fA-F]{4}/, /u{[0-9a-fA-F]+}/ ) )), escape_sequence: $ => $._unused_escape_sequence, /************************************************************************************************** *********************************Collection Literals*********************************************** *************************************************************************************************** ****These are the collection literals from section 16.9 (Page 92-108) of the dart specification**** *************************************************************************************************** ***************************************************************************************************/ list_literal: $ => seq( optional($.const_builtin), optional($.type_arguments), '[', commaSepTrailingComma($._element), ']' ), set_or_map_literal: $ => seq( optional($.const_builtin), optional($.type_arguments), '{', commaSepTrailingComma( $._element ), '}' ), pair: $ => seq( field('key', $._expression), ':', field('value', $._expression) ), // pair_or_element: $ => seq( // field('key', $._expression), // optional( // seq( // ':', // field('value', $._expression) // ) // ) // ), _element: $ => choice( $._expression, $.pair, $.spread_element, $.if_element, $.for_element ), /****This is the null literal from section 16.4 (Page 84) of the dart specification****/ null_literal: $ => prec( DART_PREC.BUILTIN, 'null', ), /// Record literal (from Dart.g) record_literal: $ => seq( optional($.const_builtin), $._record_literal_no_const, ), _record_literal_no_const: $ => seq( '(', choice( seq($.label, $._expression), seq($._expression, ','), commaSep2TrailingComma($.record_field), ), ')' ), record_field: $ => seq(optional($.label), $._expression), /************************************************************************************************** *********************************Expressions******************************************************* *************************************************************************************************** ****These are the expressions from section 16.9 (Page 110-166) of the dart specification*********** *************************************************************************************************** ***************************************************************************************************/ _expression: $ => choice( $.pattern_assignment, $.assignment_expression, $.throw_expression, seq( $._real_expression, repeat($.cascade_section) ) ), _expression_without_cascade: $ => choice( $.assignment_expression_without_cascade, $._real_expression, $.throw_expression_without_cascade ), _real_expression: $ => choice( $.conditional_expression, $.logical_or_expression, $.if_null_expression, $.additive_expression, $.multiplicative_expression, $.relational_expression, $.equality_expression, $.logical_and_expression, $.bitwise_and_expression, $.bitwise_or_expression, $.bitwise_xor_expression, $.shift_expression, $.type_cast_expression, $.type_test_expression, $._unary_expression ), // _below_relational_expression: $ => choice( // // UNARY_POSTFIX: 16, // // UNARY_PREFIX: 15, // // Multiplicative: 14, // *, /, ˜/, % Left // // Additive: 13, // +, - Left // // Shift: 12, // <<, >>, >>> Left // // Bitwise_AND: 11, // & Left // // Bitwise_XOR: 10, // ˆ Left // // Bitwise_Or: 9 , // | Left // // $.type_cast_expression, // $._unary_expression, // $.multiplicative_expression, // $.additive_expression, // $.shift_expression, // $.bitwise_and_expression, // $.bitwise_or_expression, // $.bitwise_xor_expression, // // ), // // _below_relational_type_cast_expression: $ => prec( // DART_PREC.RelationalTypeCast, // choice( // // UNARY_POSTFIX: 16, // // UNARY_PREFIX: 15, // // Multiplicative: 14, // *, /, ˜/, % Left // // Additive: 13, // +, - Left // // Shift: 12, // <<, >>, >>> Left // // Bitwise_AND: 11, // & Left // // Bitwise_XOR: 10, // ˆ Left // // Bitwise_Or: 9 , // | Left // $._unary_expression, // $.multiplicative_expression, // $.additive_expression, // $.shift_expression, // $.bitwise_and_expression, // $.bitwise_or_expression, // $.bitwise_xor_expression, // // ) // ), throw_expression: $ => seq( 'throw', $._expression ), throw_expression_without_cascade: $ => seq( 'throw', $._expression_without_cascade ), /************************************************************************************************** ***********************Assignment Expressions***************************************************** *************************************************************************************************** ****These are the assignment expressions from section 16.34 (Page 159) of the dart DRAFT********** * specification. (Very different from the formal spec in this instance)**************************** *************************************************************************************************** ***************************************************************************************************/ assignment_expression: $ => prec.right(DART_PREC.Assignment, seq( //right field('left', $.assignable_expression), field('operator', $._assignment_operator), field('right', $._expression) )), assignment_expression_without_cascade: $ => prec.right(DART_PREC.Assignment, seq( //right field('left', $.assignable_expression), field('operator', $._assignment_operator), field('right', $._expression_without_cascade) )), assignable_expression: $ => choice( seq($._primary, $._assignable_selector_part), // dart issue? seq($.super, $.unconditional_assignable_selector), seq($.constructor_invocation, $._assignable_selector_part), $.identifier ), _assignable_selector_part: $ => seq( repeat($.selector), $._assignable_selector ), //'+=', '-=', '*=', '/=', '&=', '|=', '^=', '%=', '<<=', '>>=', '>>>=', '??=' //todo: use the op names in place of these. _assignment_operator: $ => choice( '=', // additive operator '+=', '-=', // multiplicative operator '*=', '/=', '%=', '~/=', // shift operator '<<=', '>>=', '>>>=', '&=', '^=', '|=', '??=', ), // binary_expression: $ => choice( // ...[ // ['>', PREC.REL], // ['<', PREC.REL], // ['==', PREC.REL], // ['>=', PREC.REL], // ['<=', PREC.REL], // ['!=', PREC.REL], // ['&&', PREC.AND], // ['||', PREC.OR], // ['+', PREC.PLUS], // ['-', PREC.PLUS], // ['*', PREC.TIMES], // ['/', PREC.TIMES], // ['&', PREC.AND], // ['|', PREC.OR], // ['^', PREC.OR], // ['%', PREC.TIMES], // ['<<', PREC.TIMES], // ['>>', PREC.TIMES], // ['>>>', PREC.TIMES], // ].map(([operator, precedence]) => // prec.left(precedence, seq( // field('left', $._expression), // field('operator', operator), // field('right', $._expression) // )) // )), // instanceof_expression: $ => prec(PREC.REL, seq( // field('left', $._expression), // 'instanceof', // field('right', $._type) // )), lambda_expression: $ => seq( field('parameters', $.function_signature), field( 'body', $.function_body ) ), function_expression: $ => seq( field('parameters', $._formal_parameter_part), field( 'body', $.function_expression_body ) ), inferred_parameters: $ => seq( '(', commaSep1($.identifier), ')' ), if_null_expression: $ => prec.left( //left DART_PREC.If, seq( field('first', $._real_expression // logical_or_expression ), $._if_null_expression // optional( // $._if_null_expression // ) ) ), _if_null_expression: $ => repeat1( seq( '??', field('second', $._real_expression) ) ), conditional_expression: $ => prec.left( //left DART_PREC.Conditional, seq( // $.if_null_expression, $._real_expression, seq( '?', field('consequence', $._expression_without_cascade), ':', field('alternative', $._expression_without_cascade) ) ) ), logical_or_expression: $ => prec.left( //left DART_PREC.Logical_OR, sep2($._real_expression, $.logical_or_operator) ), logical_and_expression: $ => prec.left( //left DART_PREC.Logical_AND, sep2($._real_expression, $.logical_and_operator) ), equality_expression: $ => prec( //neither DART_PREC.Equality, choice( seq( // $.relational_expression, $._real_expression, // optional( // // ) $.equality_operator, $._real_expression // $.relational_expression ), seq( $.super, $.equality_operator, // $.relational_expression $._real_expression ) ) ), equality_operator: $ => token( choice( '==', '!=' ) ), type_cast_expression: $ => prec.left( DART_PREC.RelationalTypeCast, seq( // $._below_relational_type_cast_expression, $._real_expression, $.type_cast, ) ), type_test_expression: $ => prec( DART_PREC.RelationalTypeTest, seq( // $._below_relational_type_cast_expression, $._real_expression, $.type_test, ) ), // _raw_type_cast: $ => prec.right( // seq( // $._below_relational_type_cast_expression, // $.type_cast, // ) // ), relational_expression: $ => prec( // neither DART_PREC.Relational, choice( // $._raw_type_cast, seq( // $.bitwise_or_expression, // $._below_relational_type_cast_expression, // TODO: The spec says optional but it breaks tests, and I'm not sure in a good way. // Modified to account for type casts being compared relationally! // I am not certain this is what designers intended. (see other comments on github) // optional( $._real_expression, $.relational_operator, $._real_expression // choice( // $.type_test, // $.type_cast, // seq( // $.relational_operator, // $._real_expression // ) // ) // ), ), // seq( // // $.bitwise_or_expression, // choice( // $._raw_type_cast, // $._below_relational_type_cast_expression // ), // $.relational_operator, // choice( // $._raw_type_cast, // $._below_relational_type_cast_expression // ) // ), seq( $.super, $.relational_operator, $._real_expression ), ) ), relational_operator: $ => choice( '<', '>', '<=', '>=' ), //BITWISE EXPRESSIONS bitwise_or_expression: $ => binaryRunLeft($._real_expression, '|', $.super, DART_PREC.Bitwise_Or), bitwise_xor_expression: $ => binaryRunLeft($._real_expression, '^', $.super, DART_PREC.Bitwise_XOR), bitwise_and_expression: $ => binaryRunLeft($._real_expression, '&', $.super, DART_PREC.Bitwise_AND), shift_expression: $ => binaryRunLeft($._real_expression, $.shift_operator, $.super, DART_PREC.Shift), additive_expression: $ => binaryRunLeft($._real_expression, $.additive_operator, $.super, DART_PREC.Additive), multiplicative_expression: $ => binaryRunLeft($._unary_expression, $.multiplicative_operator, $.super, DART_PREC.Multiplicative), bitwise_operator: $ => $._bitwise_operator, _bitwise_operator: $ => choice( '&', '^', '|' ), shift_operator: $ => $._shift_operator, _shift_operator: $ => choice( '<<', '>>', '>>>' ), additive_operator: $ => $._additive_operator, _additive_operator: $ => token( choice( '+', '-' ) ), multiplicative_operator: $ => $._multiplicative_operator, _multiplicative_operator: $ => choice( '*', '/', '%', '~/' ), _unary_expression: $ => prec( DART_PREC.UNARY_PREFIX, choice( $._postfix_expression, $.unary_expression, ) ), unary_expression: $ => prec( //neither DART_PREC.UNARY_PREFIX, choice( seq($.prefix_operator, $._unary_expression), $.await_expression, // prec(DART_PREC.UNARY_POSTFIX, $._postfix_expression), seq( choice( $.minus_operator, $.tilde_operator ), $.super ), seq( $.increment_operator, $.assignable_expression ) ) ), _postfix_expression: $ => choice( seq( $._primary, repeat( $.selector ) ), $.postfix_expression ), postfix_expression: $ => prec.right(choice( seq( $.assignable_expression, $.postfix_operator ), seq( $.constructor_invocation, repeat( $.selector ) ) )), postfix_operator: $ => $.increment_operator, increment_operator: $ => token(choice( '++', '--' )), spread_element: $ => seq( '...', optional('?'), $._expression ), selector: $ => prec.right(choice( // '!', $._exclamation_operator, $._assignable_selector, $.argument_part, $.type_arguments, )), prefix_operator: $ => choice( $.minus_operator, $.negation_operator, $.tilde_operator ), minus_operator: $ => '-', negation_operator: $ => $._exclamation_operator, _exclamation_operator: $ => '!', tilde_operator: $ => '~', await_expression: $ => seq( 'await', $._unary_expression ), type_test: $ => seq( $.is_operator, $._type_not_void ), is_operator: $ => seq( token('is'), optional( $._exclamation_operator ) ), type_cast: $ => seq( $.as_operator, $._type_not_void ), as_operator: $ => token('as'), new_expression: $ => seq( $._new_builtin, $._type_not_void, optional( $._dot_identifier ), $.arguments ), _dot_identifier: $ => prec.dynamic( DART_PREC.DOT_IDENTIFIER, seq( '.', $.identifier ) ), const_object_expression: $ => seq( $.const_builtin, $._type_not_void, optional( $._dot_identifier ), $.arguments ), _primary: $ => choice( $._literal, $.identifier, $.function_expression, $.new_expression, $.const_object_expression, $.parenthesized_expression, // $.class_literal, $.this, seq( $.super, $.unconditional_assignable_selector ), $.constructor_tearoff, $.switch_expression, // $.object_creation_expression, // $.field_access, // $.array_access, // $.method_invocation, // $.method_reference, ), parenthesized_expression: $ => seq('(', $._expression, ')'), _compound_access: $ => choice('.', '?.'), constructor_invocation: $ => prec.right(choice( seq($._type_name, $.type_arguments, '.', $.identifier, $.arguments), seq($._type_name, '.', $._new_builtin, $.arguments), )), constructor_tearoff: $ => prec.right(seq( $._type_name, optional($.type_arguments), '.', $._new_builtin, )), arguments: $ => seq('(', optional($._argument_list), ')'), _argument_list: $ => prec.right(commaSep1TrailingComma($._any_argument)), _any_argument: $ => choice($.argument, $.named_argument), argument: $ => $._expression, named_argument: $ => seq($.label, $._expression), cascade_section: $ => prec.left( DART_PREC.Cascade, seq( choice('..', '?..'), $.cascade_selector, repeat($.argument_part), repeat( $._cascade_subsection ), optional( $._cascade_assignment_section ) ) ), // prec.left( // DART_PREC.Cascade, // ), _cascade_subsection: $ => seq( $._assignable_selector, repeat($.argument_part) ), _cascade_assignment_section: $ => seq( $._assignment_operator, $._expression_without_cascade ), index_selector: $ => seq('[', $._expression, ']'), cascade_selector: $ => choice( seq( optional($.nullable_selector), $.index_selector, ), $.identifier ), argument_part: $ => seq( optional( $.type_arguments ), // seq( // $.type_arguments, // $.arguments // ), $.arguments ), unconditional_assignable_selector: $ => choice( $.index_selector, seq('.', $.identifier) ), conditional_assignable_selector: $ => choice( seq('?.', $.identifier), seq('?', $.index_selector) ), _assignable_selector: $ => choice( $.unconditional_assignable_selector, $.conditional_assignable_selector ), type_arguments: $ => choice( // was prec.right // seq( // '<', // '>', // optional($.nullable_type) // ), seq( '<', commaSep($._type), '>', // optional($.nullable_type) ) ), wildcard: $ => seq( optional($._metadata), '?', optional($._wildcard_bounds) ), _wildcard_bounds: $ => choice( seq('extends', $._type), seq($.super, $._type) ), dimensions: $ => prec.right(repeat1( seq(optional($._metadata), '[', ']') )), // Statements _statement: $ => choice( $.block, prec.dynamic(1, $.local_function_declaration), prec.dynamic(2, $.local_variable_declaration), $.for_statement, $.while_statement, $.do_statement, $.switch_statement, $.if_statement, //TODO: add rethrow statement. // $._declaration, $.try_statement, $.break_statement, $.continue_statement, $.return_statement, $.yield_statement, $.yield_each_statement, $.expression_statement, $.assert_statement, // $.labeled_statement, ), local_function_declaration: $ => seq( optional($._metadata), $.lambda_expression ), block: $ => seq( '{', repeat($._statement), '}' ), expression_statement: $ => seq( $._expression, $._semicolon ), labeled_statement: $ => seq( $.identifier, ':', $._statement ), assert_statement: $ => seq($.assertion, ';'), assertion: $ => seq( $._assert_builtin, $.assertion_arguments, ), assertion_arguments: $ => seq( '(', $._expression, optional( seq( ',', $._expression ), ), optional(','), ')', ), switch_statement: $ => seq( 'switch', field('condition', $.parenthesized_expression), field('body', $.switch_block) ), switch_expression: $ => seq( 'switch', field('condition', $.parenthesized_expression), field('body', seq('{', commaSep1TrailingComma($.switch_expression_case), '}' )) ), switch_expression_case: $ => seq($._guarded_pattern, '=>', $._expression), _guarded_pattern: $ => seq( $._pattern, optional(seq('when', $._expression)) ), _pattern: $ => choice( $._logical_or_pattern, ), _logical_or_pattern: $ => seq($._logical_and_pattern, repeat(seq($.logical_or_operator, $._logical_and_pattern))), _logical_and_pattern: $ => seq($._relational_pattern, repeat(seq($.logical_and_operator, $._relational_pattern))), _relational_pattern: $ => prec(DART_PREC.Relational, choice( seq(choice($.relational_operator, $.equality_operator), $._real_expression), $._unary_pattern, ) ), _unary_pattern: $ => choice( $.cast_pattern, $.null_check_pattern, $.null_assert_pattern, $._primary_pattern, ), _primary_pattern: $ => choice( $.constant_pattern, $.variable_pattern, $._parenthesized_pattern, $.list_pattern, $.map_pattern, $.record_pattern, $.object_pattern, ), cast_pattern: $ => seq($._primary_pattern, 'as', $._type), null_check_pattern: $ => seq($._primary_pattern, '?'), null_assert_pattern: $ => seq($._primary_pattern, '!'), constant_pattern: $ => choice( $._bool_literal, $.null_literal, seq(optional($.minus_operator), $._numeric_literal), $.string_literal, $.symbol_literal, $.identifier, $.qualified, $.const_object_expression, seq($.const_builtin, optional($.type_arguments), '[', commaSep1TrailingComma($._element), ']'), seq($.const_builtin, optional($.type_arguments), '{', commaSep1TrailingComma($._element), '}'), seq($.const_builtin, '(', $._expression, ')'), ), variable_pattern: $ => seq($._final_var_or_type, $.identifier), _parenthesized_pattern: $ => seq('(', $._pattern, ')'), list_pattern: $ => seq(optional($.type_arguments), '[', commaSepTrailingComma($._list_pattern_element), ']'), _list_pattern_element: $ => choice($._pattern, $.rest_pattern), rest_pattern: $ => seq('...', optional($._pattern)), map_pattern: $ => seq(optional($.type_arguments), '{', commaSepTrailingComma($._map_pattern_entry), '}'), _map_pattern_entry: $ => choice(seq($._expression, ':', $._pattern), '...'), record_pattern: $ => seq('(', commaSep1TrailingComma($._pattern_field), ')'), _pattern_field: $ => seq(optional(seq(optional($.identifier), ':')), $._pattern), object_pattern: $ => seq($._type_name, optional($.type_arguments), '(', commaSep1TrailingComma($._pattern_field), ')'), pattern_variable_declaration: $ => seq(choice($.final_builtin, $.inferred_type), $._outer_pattern, '=', $._expression), _outer_pattern: $ => choice($._parenthesized_pattern, $.list_pattern, $.map_pattern, $.record_pattern, $.object_pattern), pattern_assignment: $ => seq($._outer_pattern, '=', $._expression), switch_block: $ => seq( '{', repeat($.switch_statement_case), optional($.switch_statement_default), '}' ), switch_statement_case: $ => seq( repeat($.label), $.case_builtin, $._guarded_pattern, ':', repeat($._statement), ), switch_statement_default: $ => seq( repeat($.label), 'default', ':', repeat($._statement), ), switch_case: $ => choice( seq(repeat($.label), $.case_builtin, $._guarded_pattern, ':', repeat1($._statement)), ), default_case: $ => choice( seq(repeat($.label), 'default', ':', repeat1($._statement)), ), switch_label: $ => seq( repeat($.label), choice( seq($.case_builtin, $._expression, ':'), seq('default', ':') )), do_statement: $ => seq( 'do', field('body', $._statement), 'while', field('condition', $.parenthesized_expression), $._semicolon ), break_statement: $ => seq($._break_builtin, optional($.identifier), $._semicolon), continue_statement: $ => seq('continue', optional($.identifier), $._semicolon), yield_statement: $ => seq('yield', $._expression, $._semicolon), yield_each_statement: $ => seq('yield', '*', $._expression, $._semicolon), return_statement: $ => seq( 'return', optional($._expression), $._semicolon ), throw_statement: $ => seq('throw', $._expression, $._semicolon), try_statement: $ => seq( $._try_head, optional(choice( $.finally_clause, seq(repeat1($._on_part), optional($.finally_clause)) )) ), _on_part: $ => choice( seq( $.catch_clause, $.block ), seq( 'on', $._type_not_void, optional($.catch_clause), $.block ) ), _try_head: $ => seq( 'try', field('body', $.block), ), catch_clause: $ => seq( 'catch', $.catch_parameters, // field('body', $.block) ), catch_parameters: $ => seq( '(', $.identifier, optional( seq( ',', $.identifier ), ), ')', ), catch_type: $ => sep1($._type, '|'), finally_clause: $ => seq('finally', $.block), if_element: $ => prec.right(seq( 'if', '(', $._expression, optional(seq('case', $._guarded_pattern)) , ')', field('consequence', $._element), optional(seq('else', field('alternative', $._element))) )), if_statement: $ => prec.right(seq( 'if', '(', $._expression, optional(seq('case', $._guarded_pattern)) , ')', field('consequence', $._statement), optional(seq('else', field('alternative', $._statement))) )), while_statement: $ => seq( 'while', field('condition', $.parenthesized_expression), field('body', $._statement) ), for_statement: $ => seq( optional('await'), 'for', $.for_loop_parts, field('body', $._statement) ), for_loop_parts: $ => seq('(', $._for_loop_parts, ')'), _for_loop_parts: $ => choice( seq( choice( $._declared_identifier, $.identifier ), 'in', field('value', $._expression), ), seq( optional(choice( field('init', $.local_variable_declaration), seq( commaSep(field('init', $._expression)), $._semicolon ) ),), field('condition', optional($._expression)), $._semicolon, commaSep(field('update', $._expression)), ), seq( choice($.final_builtin, $.inferred_type), $._outer_pattern, 'in', field('value', $._expression) ) ), // support map weirdness? for_element: $ => seq( optional('await'), 'for', $.for_loop_parts, field('body', $._element) ), // Annotations _annotation: $ => choice( $.marker_annotation, $.annotation ), marker_annotation: $ => seq( '@', field('name', choice($.identifier, $.scoped_identifier)) ), annotation: $ => seq( '@', field('name', choice($.identifier, $.scoped_identifier)), field('arguments', $.arguments) ), // Declarations _declaration: $ => prec(1, choice( $.import_specification, $.class_definition, // $.annotation_type_declaration, $.enum_declaration, )), import_or_export: $ => prec( DART_PREC.IMPORT_EXPORT, choice( $.library_import, $.library_export ) ), library_import: $ => seq( optional($._metadata), $.import_specification ), library_export: $ => seq( optional($._metadata), $._export, $.configurable_uri, repeat($.combinator), $._semicolon ), import_specification: $ => choice( seq( $._import, $.configurable_uri, optional( seq( $._as, $.identifier ) ), repeat($.combinator), $._semicolon ), seq( $._import, $.uri, $._deferred, $._as, $.identifier, repeat($.combinator), $._semicolon ) ), part_directive: $ => seq( optional($._metadata), 'part', $.uri, $._semicolon ), part_of_directive: $ => seq( optional($._metadata), 'part', 'of', choice($.dotted_identifier_list, $.uri), $._semicolon ), uri: $ => $.string_literal, configurable_uri: $ => seq( $.uri, repeat($.configuration_uri) ), configuration_uri: $ => seq( 'if', $.configuration_uri_condition, $.uri ), configuration_uri_condition: $ => seq('(', $.uri_test, ')'), uri_test: $ => seq( $.dotted_identifier_list, optional( seq( '==', $.string_literal ) ) ), combinator: $ => choice( seq('show', $._identifier_list), seq('hide', $._identifier_list) ), _identifier_list: $ => commaSep1($.identifier), asterisk: $ => '*', enum_declaration: $ => seq( optional($._metadata), 'enum', field('name', $.identifier), optional($.type_parameters), optional($.mixins), optional($.interfaces), field('body', $.enum_body), ), enum_body: $ => seq( '{', commaSep1TrailingComma($.enum_constant), optional( seq(';', repeat(seq(optional($._metadata), $._class_member_definition))) ), '}' ), enum_constant: $ => choice( seq( optional($._metadata), field('name', $.identifier), optional($.argument_part), ), seq( optional($._metadata), field('name', $.identifier), optional($.type_arguments), '.', choice($.identifier, $._new_builtin), $.arguments, )), type_alias: $ => choice( seq( optional($._metadata), $._typedef, optional($._type), $._type_name, $._formal_parameter_part, ';'), seq( optional($._metadata), $._typedef, $._type_name, optional($.type_parameters), '=', $._type, ';'), ), _class_modifiers: $ => seq(choice($.sealed, seq(optional($.abstract), optional(choice($.base, $.interface, 'final', 'inline')))), 'class'), _mixin_class_modifiers: $ => seq(optional($.abstract), optional($.base), $.mixin, 'class'), class_definition: $ => choice( seq( optional($._metadata), choice($._class_modifiers, $._mixin_class_modifiers), field('name', $.identifier), optional(field('type_parameters', $.type_parameters)), optional(field('superclass', $.superclass)), optional(field('interfaces', $.interfaces)), field('body', $.class_body) ), seq( optional($._metadata), $._class_modifiers, $.mixin_application_class ) ), extension_declaration: $ => choice( seq( optional($._metadata), 'extension', optional(field('name', $.identifier)), optional(field('type_parameters', $.type_parameters)), 'on', field('class', $._type), field('body', $.extension_body) ), ), _metadata: $ => prec.right(repeat1($._annotation)), type_parameters: $ => seq( '<', commaSep1($.type_parameter), '>' ), type_parameter: $ => seq( optional($._metadata), choice(alias( $.identifier, $.type_identifier), $.nullable_type ), // This is a comment // comment with a link made in https://github.com/flutter/flutter/pull/48547 // Changes made in https://github.com/flutter/flutter/pull/48547 /* This is also a comment */ /* this comment /* // /** ends here: */ optional($.nullable_type), optional($.type_bound) ), type_bound: $ => seq('extends', $._type_not_void), superclass: $ => choice( seq( 'extends', $._type_not_void, optional($.mixins) ), $.mixins ), mixins: $ => seq( 'with', $._type_not_void_list ), mixin_application_class: $ => seq( $.identifier, optional($.type_parameters), '=', $.mixin_application, $._semicolon ), mixin_application: $ => seq( $._type_not_void, $.mixins, optional($.interfaces) ), mixin_declaration: $ => seq( optional($._metadata), optional($.base), $.mixin, $.identifier, optional($.type_parameters), optional(seq( 'on', $._type_not_void_list )), optional($.interfaces), $.class_body ), interfaces: $ => seq( $._implements, $._type_not_void_list ), interface_type_list: $ => seq( $._type, repeat(seq(',', $._type)) ), class_body: $ => seq( '{', repeat( seq( optional($._metadata), $._class_member_definition ) ), '}' ), extension_body: $ => seq( '{', repeat( choice( seq(optional($._metadata), $.declaration, $._semicolon), seq( optional($._metadata), seq( $.method_signature, $.function_body ), ) ) ), '}' ), _class_member_definition: $ => choice( seq($.declaration, $._semicolon), seq( $.method_signature, $.function_body ), ), getter_signature: $ => seq( optional($._type), $._get, field('name', $.identifier), optional($._native) ), setter_signature: $ => seq( optional($._type), $._set, field('name', $.identifier), $._formal_parameter_part, optional($._native) ), method_signature: $ => choice( seq($.constructor_signature, optional($.initializers)), $.factory_constructor_signature, seq( optional($._static), choice( $.function_signature, $.getter_signature, $.setter_signature ) ), $.operator_signature ), declaration: $ => choice( seq($.constant_constructor_signature, optional(choice($.redirection, $.initializers))), seq($.constructor_signature, optional(choice($.redirection, $.initializers))), seq($._external, optional($.const_builtin), $.factory_constructor_signature ), seq( optional($.const_builtin), $.factory_constructor_signature, $._native ), seq($._external, $.constant_constructor_signature ), $.redirecting_factory_constructor_signature, seq($._external, $.constructor_signature ), seq( optional($._external_builtin), optional($._static), $.getter_signature, ), seq( optional($._external_and_static), $.setter_signature, ), seq( optional($._external), $.operator_signature ), seq( optional($._external_and_static), $.function_signature, ), // TODO: This should only work with native? seq( $._static, $.function_signature, ), // | static const 〈type〉? 〈staticFinalDeclarationList〉 // | static final 〈type〉? 〈staticFinalDeclarationList〉 // | static late final 〈type〉? 〈initializedIdentifierList〉 // | static late? 〈varOrType〉 〈initializedIdentifierList seq( $._static, choice( seq( $._final_or_const, optional($._type), $.static_final_declaration_list ), seq( $._late_builtin, choice( seq( $.final_builtin, optional($._type), $.initialized_identifier_list ), seq( choice( $._type, $.inferred_type, ), $.initialized_identifier_list ) ) ), seq( choice( $._type, $.inferred_type, ), $.initialized_identifier_list ) ) ), // | covariant late final 〈type〉? 〈identifierList〉 // | covariant late? 〈varOrType〉 〈initializedIdentifierList〉 seq( $._covariant, choice( seq( $._late_builtin, choice( seq( $.final_builtin, optional($._type), $.identifier_list ), seq( choice( $._type, $.inferred_type, ), $.initialized_identifier_list ) ) ), seq( choice( $._type, $.inferred_type, ), $.initialized_identifier_list ) ) ), seq( optional($._late_builtin), $.final_builtin, optional($._type), $.initialized_identifier_list ), seq( optional($._late_builtin), $._var_or_type, $.initialized_identifier_list ) // TODO: add in the 'late' keyword from the informal draft spec: // |static late final〈type〉?〈initializedIdentifierList〉 // |static late?〈varOrType〉 〈initializedIdentifierList〉 // |covariant late?〈varOrType〉 〈initializedIdentifierList〉 // |late?final〈type〉?〈initializedIdentifierList〉 // |late?〈varOrType〉 〈initializedIdentifierList〉 ), identifier_list: $ => commaSep1( $.identifier ), initialized_identifier_list: $ => commaSep1( $.initialized_identifier ), initialized_identifier: $ => seq( $.identifier, optional(seq( '=', $._expression )) ), static_final_declaration_list: $ => commaSep1( $.static_final_declaration ), binary_operator: $ => choice( $.multiplicative_operator, $.additive_operator, $.shift_operator, $.relational_operator, '==', $.bitwise_operator ), operator_signature: $ => seq( optional($._type), $._operator, choice( '~', $.binary_operator, '[]', '[]=' ), $.formal_parameter_list, optional($._native) ), static_final_declaration: $ => seq( $.identifier, '=', $._expression ), _external_and_static: $ => seq( $._external, optional($._static)), _static_or_covariant: $ => choice( $._covariant, $._static ), _final_or_const: $ => choice( $.final_builtin, $.const_builtin ), static_initializer: $ => seq( $._static, $.block ), initializers: $ => seq( ':', commaSep1($.initializer_list_entry) ), initializer_list_entry: $ => choice( seq($.super, $.arguments), seq($.super, seq('.', choice($.identifier, $._new_builtin), $.arguments), ), $.field_initializer, $.assertion ), field_initializer: $ => seq( optional(seq($.this, '.')), $.identifier, '=', // $.conditional_expression, $._real_expression, repeat( $.cascade_section ) ), // constructor_signature: $ => seq( // $._constructor_declarator, // // optional($.throws), // // field('body', choice( // // $.constructor_body, // // $._semicolon // // )) // ), factory_constructor_signature: $ => seq( $._factory, sep1($.identifier, '.'), $.formal_parameter_list, ), redirecting_factory_constructor_signature: $ => seq( optional($.const_builtin), $._factory, sep1($.identifier, '.'), $.formal_parameter_list, '=', $._type_not_void, optional(seq('.', $.identifier)), ), redirection: $ => seq( ':', $.this, optional(seq( '.', $._identifier_or_new )), $.arguments ), constructor_signature: $ => seq( field('name', seq($.identifier, optional( seq( '.', $._identifier_or_new ) ))), field('parameters', $.formal_parameter_list) ), constant_constructor_signature: $ => seq( $.const_builtin, seq($.identifier, optional(seq('.', $._identifier_or_new))), $.formal_parameter_list ), constructor_body: $ => seq( '{', optional($.explicit_constructor_invocation), repeat($._statement), '}' ), explicit_constructor_invocation: $ => seq( choice( seq( field('type_arguments', optional($.type_arguments)), field('constructor', choice($.this, $.super)), ), seq( field('object', choice($._ambiguous_name, $._primary)), '.', field('type_arguments', optional($.type_arguments)), field('constructor', $.super), ) ), field('arguments', $.arguments), $._semicolon ), _ambiguous_name: $ => choice( $.identifier, $.scoped_identifier ), scoped_identifier: $ => seq( field('scope', choice($.identifier, $.scoped_identifier)), '.', field('name', $.identifier) ), variable_declaration: $ => seq( $._declared_identifier, optional(seq( ',', commaSep1($.identifier) )) ), initialized_variable_definition: $ => seq( $._declared_identifier, optional(seq( prec(DART_PREC.BUILTIN, '='), field('value', $._expression) )), repeat(seq(',', $.initialized_identifier)) ), // initialized_identifier: $ => seq( // $.identifier, // optional(seq('=', $._expression)) // ), _declared_identifier: $ => seq( optional($._metadata), optional($._covariant), $._final_const_var_or_type, field('name', $.identifier) ), // Types _final_const_var_or_type: $ => choice( seq(optional($._late_builtin), $.final_builtin, optional($._type)), seq($.const_builtin, optional( $._type )), seq(optional($._late_builtin), $._var_or_type) ), _type: $ => choice( seq( $.function_type, optional($.nullable_type) ), $._type_not_function // $._function_type_tails, // seq( // $._type_not_function, // $._function_type_tails // ), // $._type_not_function // $._unannotated_type, // $.annotated_type ), _type_not_function: $ => choice( $._type_not_void_not_function, seq($.record_type, optional($.nullable_type)), $.void_type ), _type_not_void_not_function: $ => choice( seq( $._type_name, optional($.type_arguments), optional($.nullable_type) ), // rewritten in accordance with the draft spec page 198 seq( $._function_builtin_identifier, optional($.nullable_type) ) ), function_type: $ => choice( $._function_type_tails, seq( $._type_not_function, $._function_type_tails ) ), _function_type_tails: $ => repeat1($._function_type_tail), _function_type_tail: $ => seq( $._function_builtin_identifier, optional($.type_parameters), optional($.nullable_type), optional($.parameter_type_list), optional($.nullable_type), ), parameter_type_list: $ => seq( '(', optional(choice( commaSep1TrailingComma($.normal_parameter_type), seq( commaSep1($.normal_parameter_type), ',', $.optional_parameter_types, ), $.optional_parameter_types ),), ')' ), normal_parameter_type: $ => seq( optional($._metadata), choice( $.typed_identifier, $._type ) ), optional_parameter_types: $ => choice( $.optional_positional_parameter_types, $.named_parameter_types ), optional_positional_parameter_types: $ => seq( '[', commaSep1TrailingComma($.normal_parameter_type), ']' ), named_parameter_types: $ => seq( '{', commaSep1TrailingComma($._named_parameter_type), '}' ), _named_parameter_type: $ => seq( optional($._metadata), optional($._required), $.typed_identifier ), _type_not_void: $ => choice( seq( $.function_type, optional($.nullable_type) ), seq($.record_type, optional($.nullable_type)), // $.function_type, $._type_not_void_not_function // alias($.identifier, $.type_identifier), // // $.scoped_type_identifier, // $.generic_type ), record_type: $ => choice( seq('(', ')'), seq('(', commaSep1($.record_type_field), ',', '{' , commaSep1TrailingComma($.record_type_named_field), '}', ')'), seq('(', commaSep1TrailingComma($.record_type_field), ')'), seq('(','{', commaSep1TrailingComma($.record_type_named_field), '}', ')'), ), record_type_field: $ => seq( optional($._metadata), $._type, optional($.identifier), ), record_type_named_field: $ => seq( optional($._metadata), $.typed_identifier, ), _type_not_void_list: $ => commaSep1( $._type_not_void ), _type_name: $ => seq( alias( $.identifier, $.type_identifier ), optional( $._type_dot_identifier ), // optional($.nullable_type), ), // _type_name: $ => prec.right( // changed from above? // seq( // alias( // $.identifier, // $.type_identifier // ), // optional( // $._type_dot_identifier // ), // optional($.nullable_type), // ) // ), _type_dot_identifier: $ => prec.right( DART_PREC.IMPORT_EXPORT, seq( '.', alias( $.identifier, $.type_identifier ) ) ), typed_identifier: $ => seq( $._type, $.identifier ), nullable_type: $ => prec(DART_PREC.BUILTIN, '?'), nullable_selector: $ => prec(DART_PREC.BUILTIN, '?'), floating_point_type: $ => token( 'double' ), boolean_type: $ => prec( DART_PREC.BUILTIN, 'bool', ), void_type: $ => token('void'), _var_or_type: $ => choice( $._type, seq( $.inferred_type, optional($._type) ) ), _final_var_or_type: $ => choice($.inferred_type, $.final_builtin, seq(optional($.final_builtin), $._type)), inferred_type: $ => prec( DART_PREC.BUILTIN, 'var', ), function_body: $ => choice( seq( optional('async'), '=>', $._expression, $._semicolon ), seq( optional(choice( 'async', 'async*', 'sync*', )), $.block ) ), function_expression_body: $ => choice( seq( optional('async'), '=>', $._expression ), seq( optional(choice( 'async', 'async*', 'sync*', )), $.block ) ), function_signature: $ => seq( // optional($._metadata), optional($._type), field('name', choice( alias( $._get, $.identifier, // this way the syntax still highlights consistently. ), alias( $._set, $.identifier, // this way the syntax still highlights consistently. ), // $._get, // $._set, $.identifier )), $._formal_parameter_part, optional($._native), ), // _get_identifier: $ => alias( // $.identifier, // this way the syntax still highlights consistently. // $._get // ), _formal_parameter_part: $ => seq( optional($.type_parameters), $.formal_parameter_list ), formal_parameter_list: $ => $._strict_formal_parameter_list, _strict_formal_parameter_list: $ => choice( seq( '(', ')' ), seq( '(', $._normal_formal_parameters, optional( ',' ), ')' ), seq( '(', $._normal_formal_parameters, ',', $.optional_formal_parameters, ')' ), seq( '(', $.optional_formal_parameters, ')' ) ), _normal_formal_parameters: $ => commaSep1($.formal_parameter), optional_formal_parameters: $ => choice( $._optional_postional_formal_parameters, $._named_formal_parameters ), positional_parameters: $ => seq( '[', commaSep1( $._default_formal_parameter ), ']' ), _optional_postional_formal_parameters: $ => seq( '[', commaSep1TrailingComma( $._default_formal_parameter ), ']' ), _named_formal_parameters: $ => seq( '{', commaSep1TrailingComma( $._default_named_parameter ), '}' ), formal_parameter: $ => $._normal_formal_parameter, _default_formal_parameter: $ => seq( $.formal_parameter, optional( seq( '=', $._expression ) ) ), _default_named_parameter: $ => choice( seq( optional( $._required ), $.formal_parameter, optional( seq( '=', $._expression ) ) ), seq( optional( $._required ), $.formal_parameter, optional( seq( ':', $._expression ) ) ) ), _normal_formal_parameter: $ => seq( optional( $._metadata ), choice( $._function_formal_parameter, $._simple_formal_parameter, $.constructor_param, $.super_formal_parameter ) ), _function_formal_parameter: $ => seq( optional( $._covariant ), optional( $._type ), $.identifier, $._formal_parameter_part, optional($.nullable_type) ), _simple_formal_parameter: $ => choice( $._declared_identifier, seq( optional( $._covariant ), $.identifier ) ), // see https://github.com/dart-lang/language/blob/31f3d2bd6fd83b2e5f5019adb276c23fd2900941/working/1855%20-%20super%20parameters/proposal.md super_formal_parameter: $ => seq( optional($._final_const_var_or_type), $.super, '.', $.identifier, optional($._formal_parameter_part) ), //constructor param = field formal parameter constructor_param: $ => seq( optional($._final_const_var_or_type), $.this, '.', $.identifier, optional($._formal_parameter_part) ), local_variable_declaration: $ => choice( seq( optional($._metadata), $.initialized_variable_definition, $._semicolon ), seq( optional($._metadata), $.pattern_variable_declaration, $._semicolon ) ), script_tag: $ => seq('#!', /.+/, '\n'), library_name: $ => seq(optional($._metadata), 'library', $.dotted_identifier_list, $._semicolon), dotted_identifier_list: $ => sep1($.identifier, '.'), _identifier_or_new: $ => choice($.identifier, $._new_builtin), qualified: $ =>choice( seq($._type_name, '.', $._identifier_or_new), seq($._type_name, '.', $._type_name, '.', $._identifier_or_new), ), // Built in identifier tokens: These should be tokenized. //assert,break,case, // catch, // class, // const, // continue, // default, // do, // else, // enum, // extends, // false, // final, // finally, // for, // if, // in, // is, // new, // null, // rethrow, // return, // super, // switch, // this, // throw, // true, // try, // var, // void, // while, // with _as: $ => prec( DART_PREC.BUILTIN, 'as', ), _break_builtin: $ => token('break'), _assert_builtin: $ => token('assert'), case_builtin: $ => token('case'), _covariant: $ => prec( DART_PREC.BUILTIN, 'covariant', ), _deferred: $ => prec( DART_PREC.BUILTIN, 'deferred', ), _dynamic: $ => prec( DART_PREC.BUILTIN, 'dynamic', ), _export: $ => prec( DART_PREC.BUILTIN, 'export', ), _external: $ => $._external_builtin, _factory: $ => prec( DART_PREC.BUILTIN, 'factory', ), _function_builtin_identifier: $ => prec( DART_PREC.BUILTIN, 'Function', ), _get: $ => prec( DART_PREC.BUILTIN, 'get', ), _native: $ => seq( 'native', optional($.string_literal) ), _implements: $ => prec( DART_PREC.BUILTIN, 'implements', ), _import: $ => prec( DART_PREC.BUILTIN, 'import', ), interface: $ => prec( DART_PREC.BUILTIN, 'interface', ), base: $ => prec( DART_PREC.BUILTIN, 'base', ), abstract: $ => prec( DART_PREC.BUILTIN, 'abstract', ), sealed: $ => prec( DART_PREC.BUILTIN, 'sealed', ), _library: $ => prec( DART_PREC.BUILTIN, 'library', ), _operator: $ => prec( DART_PREC.BUILTIN, 'operator', ), mixin: $ => prec( DART_PREC.BUILTIN, 'mixin', ), _part: $ => prec( DART_PREC.BUILTIN, 'part', ), _required: $ => prec( DART_PREC.BUILTIN, 'required', ), _set: $ => prec( DART_PREC.BUILTIN, 'set', ), _static: $ => prec( DART_PREC.BUILTIN, 'static', ), _typedef: $ => prec( DART_PREC.BUILTIN, 'typedef', ), _new_builtin: $ => prec( DART_PREC.BUILTIN, 'new', ), logical_and_operator: $ => prec( DART_PREC.BUILTIN, '&&', ), logical_or_operator: $ => prec( DART_PREC.BUILTIN, '||' ), const_builtin: $ => token('const'), final_builtin: $ => token('final'), _late_builtin: $ => prec( DART_PREC.BUILTIN, 'late', ), _external_builtin: $ => prec( DART_PREC.BUILTIN, 'external', ), this: $ => prec( DART_PREC.BUILTIN, 'this', ), super: $ => prec( DART_PREC.BUILTIN, 'super', ), label: $ => seq($.identifier, ':'), _semicolon: $ => token(';'), identifier: $ => /[a-zA-Z_$][\w$]*/, identifier_dollar_escaped: $ => /([a-zA-Z_]|(\\\$))([\w]|(\\\$))*/, //TODO: add support for triple-slash comments as a special category. // Trying to add support for nested multiline comments. // http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890 // _line_comment: $ => token(seq( // '//', /[^\/].*/ // )), // _documentation_line_comment: $ => token(seq('///', /.*/)), comment: $ => choice( $._block_comment, seq('//', /([^/\n].*)?/), seq( '/*', /[^*]*\*+([^/*][^*]*\*+)*/, '/' ) ), //added nesting comments. documentation_comment: $ => choice( $._documentation_block_comment, seq('///', /.*/), ) , } }); function sep1(rule, separator) { return seq(rule, repeat(seq(separator, rule))); } function sep2(rule, separator) { return seq(rule, repeat1(seq(separator, rule))); } function commaSep1(rule) { return seq(rule, repeat(seq(',', rule))) } function commaSep(rule) { return optional(commaSep1(rule)) } function commaSep2TrailingComma(rule) { return seq(rule, repeat1(seq(',', rule)), optional(',')) } function commaSep1TrailingComma(rule) { return seq(rule, repeat(seq(',', rule)), optional(',')) } function commaSepTrailingComma(rule) { return optional(commaSep1TrailingComma(rule)) } function pureBinaryRun(rule, separator, precedence){ return prec.left( precedence, choice( sep2( rule, separator ))) } function binaryRunLeft(rule, separator, superItem, precedence) { return prec.left( //left precedence, choice( sep2( // $.bitwise_xor_expression, rule, separator ), seq( superItem, repeat1( seq( separator, rule, // $.bitwise_xor_expression ) ) ) ) ) }