/* eslint-disable arrow-parens */ /* eslint-disable camelcase */ /* eslint-disable-next-line spaced-comment */ /// // @ts-check const PREC = { call: 15, field: 14, try: 13, unary: 12, cast: 11, multiplicative: 10, additive: 9, shift: 8, bitand: 7, bitxor: 6, bitor: 5, comparative: 4, and: 3, or: 2, range: 1, assign: 0, closure: -1, }; const numeric_types = ["int", "float", "decimal"]; const TOKEN_TREE_NON_SPECIAL_TOKENS = [ "/", "_", "\\", "-", "=", "->", ",", ";", ":", "::", "!", "?", ".", "@", "*", "&", "#", "%", "^", "+", "<", ">", "|", "~", ]; const primitive_types = numeric_types.concat(["bool", "string", "channel"]); module.exports = grammar({ name: "navi", extras: ($) => [/\s/, $.line_comment, $.block_comment], externals: ($) => [ $._string_content, $._template_chars, $.float_literal, $.block_comment, ], supertypes: ($) => [ $._expression, $._literal, $._literal_pattern, $._declaration_statement, $._pattern, ], inline: ($) => [ $._path, $._type_identifier, $._tokens, $._field_identifier, $._non_special_token, $._declaration_statement, $._reserved_identifier, $._expression_ending_with_block, ], conflicts: ($) => [ // Local ambiguity due to anonymous types: // See https://internals.rust-lang.org/t/pre-rfc-deprecating-anonymous-parameters/3710 [$._option_type], [$._option_type, $._type], [$.union_type], [$.union_type, $._type], [$._base_type, $._pattern], [$.closure_type, $.tuple_pattern], [$.unit_type, $.tuple_pattern], [$.scoped_identifier, $.scoped_type_identifier], [$.parameters, $._pattern], [$.array_expression], [$.scoped_identifier, $._expression_except_range], [$._base_type, $.scoped_identifier], [$._base_type, $.scoped_identifier, $.scoped_type_identifier], [$._base_type, $.scoped_type_identifier], [$.expression_statement, $.switch_case_arm], [$.union_type, $.type_item], [$._base_type, $._expression_except_range], [$.array_expression, $.block], [$.map_expression, $.block], [$.assignment_expression, $.assert_expression], [$.assignment_expression, $.throw_expression], [$.unwrap_expression, $.assert_expression], [$.unwrap_expression, $.throw_expression], [$.compound_assignment_expr, $.assert_expression], [$.compound_assignment_expr, $.throw_expression], [$.expression_statement, $.throw_expression], [$._non_delim_token, $.nil_literal], ], word: ($) => $.identifier, rules: { source_file: ($) => seq(repeat($._statement)), _statement: ($) => choice($.expression_statement, $._declaration_statement), empty_statement: (_) => ";", expression_statement: ($) => choice(seq($._expression, ";"), prec(1, $._expression_ending_with_block)), _declaration_statement: ($) => choice( $.const_item, $.empty_statement, $.attribute_item, $.inner_attribute_item, $.struct_item, $.enum_item, $.type_item, $.function_item, $.function_signature_item, $.impl_item, $.interface_item, $.associated_type, $.let_declaration, $.use_declaration, $.test_item, $.bench_item, ), // Matches non-delimiter tokens common to both macro invocations and // definitions. This is everything except $ and metavariables (which begin // with $). _non_special_token: ($) => choice( $._literal, $.identifier, $.mutable_specifier, $.self, $.super, $.crate, alias(choice(...primitive_types), $.primitive_type), prec.right(repeat1(choice(...TOKEN_TREE_NON_SPECIAL_TOKENS))), "'", "alias", "as", "assert", "assert_eq", "assert_ne", "async", "bench", "break", "case", "catch", "const", "continue", "default", "default", "defer", "do", "else", "enum", "finally", "fn", "for", "if", "impl", "interface", "is", "let", "loop", "nil", "panic", "pub", "return", "select", "spawn", "struct", "switch", "test", "throw", "throws", "try", "type", "use", "while", ), // Section - Declarations attribute_item: ($) => seq("#", "[", $.attribute, "]"), inner_attribute_item: ($) => seq("#", "!", "[", $.attribute, "]"), _option_type: ($) => seq($._base_type, optional("?")), unwrap_expression: ($) => seq($._expression, token("!")), attribute: ($) => seq( $._path, optional( choice( seq("=", field("value", $._expression)), field("arguments", alias($.delim_token_tree, $.token_tree)), ), ), ), declaration_list: ($) => seq("{", repeat($._declaration_statement), "}"), struct_item: ($) => seq( optional($.visibility_modifier), "struct", field("name", $._type_identifier), seq(field("body", $.field_declaration_list)), ), enum_item: ($) => seq( optional($.visibility_modifier), "enum", field("name", $._type_identifier), field("type_parameters", optional($.type_parameters)), field("body", $.enum_variant_list), ), enum_variant_list: ($) => seq( "{", sepBy(",", seq(repeat($.attribute_item), $.enum_variant)), optional(","), "}", ), enum_variant: ($) => seq( optional($.visibility_modifier), field("name", $.identifier), field( "body", optional( choice($.field_declaration_list, $.ordered_field_declaration_list), ), ), optional(seq("=", field("value", $._expression))), ), field_declaration_list: ($) => seq( "{", sepBy(",", seq(repeat($.attribute_item), $.field_declaration)), optional(","), "}", ), field_declaration: ($) => seq( optional($.visibility_modifier), field("name", $._field_identifier), ":", field("type", $._type), optional(seq("=", field("value", $._expression))), ), ordered_field_declaration_list: ($) => seq( "(", sepBy( ",", seq( repeat($.attribute_item), optional($.visibility_modifier), field("type", $._type), ), ), optional(","), ")", ), const_item: ($) => seq( optional($.visibility_modifier), "const", field("name", $.identifier), optional(seq(":", field("type", $._type))), optional(seq("=", field("value", $._expression))), ";", ), type_item: ($) => seq( optional($.visibility_modifier), "type", optional("alias"), field("name", $._type_identifier), // field("type_parameters", optional($.type_parameters)), "=", field("type", $._type), ";", ), union_type: ($) => seq($._option_type, "|", optional(sepBy("|", $._option_type))), _type: ($) => choice($._option_type, $.union_type), function_item: ($) => seq( // pub optional($.visibility_modifier), "fn", // function_name field("name", choice($.identifier, $.metavariable)), // field("type_parameters", optional($.type_parameters)), // (a: int, b: string) field("parameters", $.parameters), // : int throws optional( choice( // : int throws seq(":", field("return_type", $._type), optional($.throws)), // throws ErrorType1, ErrorType2 $.throws, ), ), // {} field("body", $.block), ), throws: ($) => seq("throws", field("error_types", optional(sepBy(",", $._type)))), function_signature_item: ($) => seq( optional($.visibility_modifier), "fn", field("name", choice($.identifier, $.metavariable)), field("type_parameters", optional($.type_parameters)), field("parameters", $.parameters), optional( choice( seq(":", field("return_type", $._type), optional($.throws)), $.throws, ), ), ";", ), closure_type: ($) => seq( "|", "(", optional(sepBy(",", $._type)), ")", optional( choice( seq(":", field("return_type", $._type), optional("throws")), "throws", ), ), "|", ), test_item: ($) => seq("test", field("name", $.string_literal), field("body", $.block)), bench_item: ($) => seq("bench", field("name", $.string_literal), field("body", $.block)), impl_item: ($) => seq( "impl", optional( seq( field( "interface", choice( $._type_identifier, $.scoped_type_identifier, $.generic_type, ), ), "for", ), ), field("type", $._type), choice(field("body", $.declaration_list), ";"), ), interface_item: ($) => seq( optional($.visibility_modifier), "interface", field("name", $._type_identifier), field("type_parameters", optional($.type_parameters)), field("body", $.declaration_list), ), associated_type: ($) => seq( "type", field("name", $._type_identifier), field("type_parameters", optional($.type_parameters)), // field("bounds", optional($.trait_bounds)), ";", ), trait_bounds: ($) => seq( ":", sepBy1( "+", choice( $._type, $.lifetime, $.higher_ranked_trait_bound, $.removed_trait_bound, ), ), ), higher_ranked_trait_bound: ($) => seq( "for", field("type_parameters", $.type_parameters), field("type", $._type), ), removed_trait_bound: ($) => seq("?", $._type), type_parameters: ($) => prec( 1, seq( "<", sepBy1( ",", choice( // $.lifetime, $.metavariable, $._type_identifier, // $.constrained_type_parameter, // $.optional_type_parameter, // $.const_parameter, ), ), optional(","), ">", ), ), const_parameter: ($) => seq("const", field("name", $.identifier), ":", field("type", $._type)), constrained_type_parameter: ($) => seq( field("left", choice($.lifetime, $._type_identifier)), field("bounds", $.trait_bounds), ), optional_type_parameter: ($) => seq( field("name", choice($._type_identifier, $.constrained_type_parameter)), "=", field("default_type", $._type), ), let_declaration: ($) => seq( "let", // optional($.mutable_specifier), field("pattern", $._pattern), optional(seq(":", field("type", $._type))), optional(seq("=", field("value", $._expression))), // optional(seq("else", field("alternative", $.block))), ";", ), use_declaration: ($) => seq( optional($.visibility_modifier), "use", field("argument", $._use_clause), ";", ), _use_clause: ($) => choice( $._path, $.use_as_clause, $.use_list, $.scoped_use_list, $.use_wildcard, ), scoped_use_list: ($) => seq(field("path", optional($._path)), ".", field("list", $.use_list)), use_list: ($) => seq("{", sepBy(",", choice($._use_clause)), optional(","), "}"), use_as_clause: ($) => seq(field("path", $._path), "as", field("alias", $.identifier)), use_wildcard: ($) => seq(optional(seq($._path, ".")), "*"), parameters: ($) => seq( "(", sepBy( ",", seq( // #[attribute] optional($.attribute_item), choice( $.parameter, $.self_parameter, "_", // $._type, ), ), ), optional(","), ")", ), self_parameter: ($) => seq( // optional("&"), // optional($.lifetime), // optional($.mutable_specifier), $.self, ), variadic_parameter: (_) => "..", parameter: ($) => seq( field("pattern", $._pattern), ":", choice( seq( field("type", $._type), // = default_value optional(seq("=", field("default", $._expression))), ), seq("..", field("type", $._type)), ), ), visibility_modifier: ($) => prec.right(choice($.crate, seq("pub"))), // Section - Types _base_type: ($) => choice( $.metavariable, $.pointer_type, $.generic_type, $.scoped_type_identifier, $.array_type, $.map_type, $.function_type, $._type_identifier, $.closure_type, alias(choice(...primitive_types), $.primitive_type), ), bracketed_type: ($) => seq("<", choice($._type, $.qualified_type), ">"), qualified_type: ($) => seq(field("type", $._type), "as", field("alias", $._type)), lifetime: ($) => seq("'", $.identifier), array_type: ($) => seq("[", field("element", $._type), "]"), map_type: ($) => seq("<", field("key", $._type), ",", field("value", $._type), ">"), function_type: ($) => seq( prec( PREC.call, seq( choice( field( "trait", choice($._type_identifier, $.scoped_type_identifier), ), seq("fn"), ), field("parameters", $.parameters), ), ), optional(seq("->", field("return_type", $._type))), ), tuple_type: ($) => seq("(", sepBy1(",", $._type), optional(","), ")"), unit_type: (_) => seq("(", ")"), generic_function: ($) => prec( 1, seq( field( "function", choice($.identifier, $.scoped_identifier, $.field_expression), ), "::", field("type_arguments", $.type_arguments), ), ), generic_type: ($) => prec( 1, seq( field( "type", choice( $._type_identifier, $._reserved_identifier, $.scoped_type_identifier, ), ), field("type_arguments", $.type_arguments), ), ), generic_type_with_turbofish: ($) => seq( field("type", choice($._type_identifier, $.scoped_identifier)), "::", field("type_arguments", $.type_arguments), ), bounded_type: ($) => prec.left( -1, choice( seq($.lifetime, "+", $._type), seq($._base_type, "+", $._type), seq($._base_type, "+", $.lifetime), ), ), type_arguments: ($) => seq( token(prec(1, "<")), sepBy1( ",", choice($._type, $.type_binding, $.lifetime, $._literal, $.block), ), optional(","), ">", ), type_binding: ($) => seq( field("name", $._type_identifier), field("type_arguments", optional($.type_arguments)), "=", field("type", $._type), ), reference_type: ($) => seq( "&", optional($.lifetime), optional($.mutable_specifier), field("type", $._type), ), pointer_type: ($) => seq("*", choice("const", $.mutable_specifier), field("type", $._type)), empty_type: (_) => "!", abstract_type: ($) => seq( "impl", optional(seq("for", $.type_parameters)), field( "trait", choice( $._type_identifier, $.scoped_type_identifier, $.generic_type, $.function_type, ), ), ), mutable_specifier: (_) => "mut", // Section - Expressions _expression: ($) => choice($._expression_except_range, $.range_expression), _expression_except_range: ($) => choice( $.unary_expression, // $.reference_expression, $.try_expression, $.binary_expression, $.assignment_expression, $.compound_assignment_expr, $.type_cast_expression, $.type_assertion, $.call_expression, $.return_expression, $.yield_expression, $.throw_expression, $.assert_expression, $._literal, prec.left($.identifier), alias(choice(...primitive_types), $.identifier), prec.left($._reserved_identifier), $.self, $.scoped_identifier, $.generic_function, $.field_expression, $.array_expression, $.map_expression, $.tuple_expression, $.unit_expression, $.break_expression, $.continue_expression, $.index_expression, $.metavariable, $.closure_expression, $.parenthesized_expression, $.struct_expression, $._expression_ending_with_block, $.unwrap_expression, ), _expression_ending_with_block: ($) => choice( // $.unsafe_block, $.spawn_block, $.defer_block, $.do_catch_block, $.block, $.if_expression, $.switch_expression, $.while_expression, $.loop_expression, $.for_expression, $.const_block, ), delim_token_tree: ($) => choice( seq("(", repeat($._delim_tokens), ")"), seq("[", repeat($._delim_tokens), "]"), seq("{", repeat($._delim_tokens), "}"), ), _delim_tokens: ($) => choice($._non_delim_token, alias($.delim_token_tree, $.token_tree)), // Should match any token other than a delimiter. _non_delim_token: ($) => choice($._non_special_token, "$"), scoped_identifier: ($) => seq( field( "path", optional( choice( $._path, $.bracketed_type, alias($.generic_type_with_turbofish, $.generic_type), ), ), ), ".", field("name", choice($.type_assertion, $.identifier, $.super)), ), scoped_type_identifier_in_expression_position: ($) => prec( -2, seq( field( "path", optional( choice( $._path, alias($.generic_type_with_turbofish, $.generic_type), ), ), ), ".", field("name", $._type_identifier), ), ), scoped_type_identifier: ($) => seq( field( "path", optional( choice( $._path, alias($.generic_type_with_turbofish, $.generic_type), $.bracketed_type, $.generic_type, ), ), ), ".", field("name", $._type_identifier), ), range_expression: ($) => prec.left(PREC.range, choice(seq("..", $._expression), "..")), unary_expression: ($) => prec(PREC.unary, seq(choice("-", "*", "!"), $._expression)), try_expression: ($) => prec(PREC.try, seq(choice("try!", "try"), $._expression)), // reference_expression: ($) => // prec( // PREC.unary, // seq("&", optional($.mutable_specifier), field("value", $._expression)), // ), binary_expression: ($) => { const table = [ [PREC.and, "&&"], [PREC.or, "||"], [PREC.bitand, "&"], [PREC.bitor, "|"], [PREC.bitxor, "^"], [PREC.comparative, choice("==", "!=", "<", "<=", ">", ">=")], [PREC.shift, choice("<<", ">>")], [PREC.additive, choice("+", "-")], [PREC.multiplicative, choice("*", "/", "%")], ]; // @ts-ignore return choice( ...table.map(([precedence, operator]) => prec.left( precedence, seq( field("left", $._expression), // @ts-ignore field("operator", operator), field("right", $._expression), ), ), ), ); }, assignment_expression: ($) => prec.left( PREC.assign, seq(field("left", $._expression), "=", field("right", $._expression)), ), compound_assignment_expr: ($) => prec.left( PREC.assign, seq( field("left", $._expression), field( "operator", choice( "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>=", ), ), field("right", $._expression), ), ), type_assertion: ($) => seq("(", choice("type", $._type), ")"), type_cast_expression: ($) => prec.left( PREC.cast, seq(field("value", $._expression), "as", field("type", $._type)), ), return_expression: ($) => choice(prec.left(seq("return", $._expression)), prec(-1, "return")), yield_expression: ($) => choice(prec.left(seq("yield", $._expression)), prec(-1, "yield")), assert_expression: ($) => choice( seq("assert", $._expression), seq( choice("assert_eq", "assert_ne"), $._expression, ",", $._expression, ), ), throw_expression: ($) => seq(choice("throw", "panic"), $._expression), call_expression: ($) => prec( PREC.call, seq( field("function", $._expression_except_range), field("arguments", $.arguments), ), ), arguments: ($) => seq( "(", sepBy( ",", seq( repeat($.attribute_item), choice($._expression, $.keyword_argument), ), ), optional(","), ")", ), keyword_argument: ($) => seq(field("key", $.identifier), ":", $._expression), array_expression: ($) => seq( "[", seq(sepBy(",", $._expression), optional(",")), optional(","), "]", ), map_expression: ($) => choice( // { key: value, key: value, ...} seq( "{", sepBy(",", seq($._literal, ":", $._expression)), optional(","), "}", ), // {:} seq("{", ":", "}"), ), parenthesized_expression: ($) => seq("(", $._expression, ")"), tuple_expression: ($) => seq( "(", repeat($.attribute_item), seq($._expression, ","), repeat(seq($._expression, ",")), optional($._expression), ")", ), unit_expression: (_) => seq("(", ")"), struct_expression: ($) => seq( field( "name", choice( $._type_identifier, alias( $.scoped_type_identifier_in_expression_position, $.scoped_type_identifier, ), $.generic_type_with_turbofish, ), ), field("body", $.field_initializer_list), ), field_initializer_list: ($) => seq( "{", sepBy( ",", choice( $.shorthand_field_initializer, $.field_initializer, $.base_field_initializer, ), ), optional(","), "}", ), shorthand_field_initializer: ($) => seq(repeat($.attribute_item), $.identifier), field_initializer: ($) => seq( repeat($.attribute_item), field("name", $._field_identifier), ":", field("value", $._expression), ), base_field_initializer: ($) => seq("..", $._expression), if_expression: ($) => prec.right( seq( "if", field("condition", seq("(", $._condition, ")")), field("consequence", $.block), optional(field("alternative", $.else_clause)), ), ), let_condition: ($) => seq( "let", field("pattern", $._pattern), "=", field("value", prec.left(PREC.and, $._expression)), ), _let_chain: ($) => prec.left( PREC.and, choice( seq($._let_chain, "&&", $.let_condition), seq($._let_chain, "&&", $._expression), seq($.let_condition, "&&", $._expression), seq($.let_condition, "&&", $.let_condition), seq($._expression, "&&", $.let_condition), ), ), _condition: ($) => choice($._expression, $.let_condition, alias($._let_chain, $.let_chain)), else_clause: ($) => seq("else", choice($.block, $.if_expression)), switch_expression: ($) => seq( "switch", field("condition", seq("(", $._condition, ")")), field("body", $.switch_block), ), switch_block: ($) => seq( "{", optional(seq(repeat($.switch_case_arm))), optional($.switch_default_arm), "}", ), switch_case_arm: ($) => prec.right( seq( seq("case", field("pattern", $._pattern)), ":", field("value", $.expression_statement), ), ), switch_default_arm: ($) => prec.right(seq("default", ":", field("value", $.expression_statement))), while_expression: ($) => seq( optional(seq($.label, ":")), "while", field("condition", seq("(", $._condition, ")")), field("body", $.block), ), loop_expression: ($) => seq(optional(seq($.label, ":")), "loop", field("body", $.block)), for_expression: ($) => seq( "for", "(", "let", field("pattern", $._pattern), optional(seq(",", $.identifier)), "in", field("value", $._expression), ")", field("body", $.block), ), const_block: ($) => seq("const", field("body", $.block)), closure_expression: ($) => prec( PREC.closure, seq( field("parameters", $.closure_parameters), field("body", $._expression), ), ), closure_parameters: ($) => seq("|", sepBy(",", choice($._pattern, $.parameter)), "|"), label: ($) => seq("'", $.identifier), break_expression: ($) => prec.left(seq("break", optional($.label), optional($._expression))), continue_expression: ($) => prec.left(seq("continue", optional($.label))), index_expression: ($) => prec(PREC.call, seq($._expression, "[", $._expression, "]")), field_expression: ($) => prec( PREC.field, seq( field("value", $._expression), ".", field( "field", choice($.type_assertion, $._field_identifier, $.integer_literal), ), ), ), spawn_block: ($) => seq("spawn", $.block), defer_block: ($) => seq("defer", $.block), do_catch_block: ($) => seq( "do", $.block, seq("catch", "(", $.identifier, ")", $.block), optional(seq("finally", $.block)), ), block: ($) => seq( optional(seq($.label, ":")), "{", repeat($._statement), optional($._expression), "}", ), // Section - Patterns _pattern: ($) => choice( $._literal_pattern, alias(choice(...primitive_types), $.identifier), $.identifier, $.scoped_identifier, $.tuple_pattern, // $.tuple_struct_pattern, $.struct_pattern, $._reserved_identifier, $.ref_pattern, $.slice_pattern, $.captured_pattern, $.reference_pattern, $.remaining_field_pattern, $.mut_pattern, $.range_pattern, $.or_pattern, $.const_block, "_", ), tuple_pattern: ($) => seq( "(", sepBy(",", choice($._pattern, $.closure_expression)), optional(","), ")", ), slice_pattern: ($) => seq("[", sepBy(",", $._pattern), optional(","), "]"), // tuple_struct_pattern: ($) => // seq( // field("type", choice($.identifier, $.scoped_identifier)), // "(", // sepBy(",", $._pattern), // optional(","), // ")", // ), struct_pattern: ($) => seq( field("type", choice($._type_identifier, $.scoped_type_identifier)), "{", sepBy(",", choice($.field_pattern, $.remaining_field_pattern)), optional(","), "}", ), field_pattern: ($) => seq( // optional("ref"), // optional($.mutable_specifier), choice( field("name", alias($.identifier, $.shorthand_field_identifier)), seq( field("name", $._field_identifier), ":", field("pattern", $._pattern), ), ), ), remaining_field_pattern: (_) => "..", mut_pattern: ($) => prec(-1, seq($.mutable_specifier, $._pattern)), range_pattern: ($) => seq( choice($._literal_pattern, $._path), choice( seq(choice("...", "..="), choice($._literal_pattern, $._path)), "..", ), ), ref_pattern: ($) => seq("ref", $._pattern), captured_pattern: ($) => seq($.identifier, "@", $._pattern), reference_pattern: ($) => seq("&", optional($.mutable_specifier), $._pattern), or_pattern: ($) => prec.left(-2, seq($._pattern, "|", $._pattern)), // Section - Literals _literal: ($) => choice( $.string_literal, $.string_template, $.raw_string_literal, $.char_literal, $.bool_literal, $.integer_literal, $.float_literal, $.nil_literal, ), _literal_pattern: ($) => choice( $.string_literal, $.string_template, $.raw_string_literal, $.char_literal, $.bool_literal, $.integer_literal, $.float_literal, $.negative_literal, ), negative_literal: ($) => seq("-", choice($.integer_literal, $.float_literal)), integer_literal: (_) => token( seq( choice(/[0-9][0-9_]*/, /0x[0-9a-fA-F_]+/, /0b[01_]+/, /0o[0-7_]+/), optional(choice(...numeric_types)), ), ), string_literal: ($) => choice( seq( '"', repeat( choice( alias($.unescaped_double_string_fragment, $.string_fragment), $.escape_sequence, ), ), '"', ), ), unescaped_double_string_fragment: (_) => token.immediate(prec(1, /[^"\\\r\n]+/)), raw_string_literal: ($) => seq("r", $.string_literal), string_template: ($) => seq( "`", repeat( choice( alias($.string_template_fragment, $.string_fragment), $.escape_sequence, $.string_template_substitution, ), ), "`", ), string_template_fragment: (_) => token.immediate(prec(1, /[^`\$\\]+/)), string_template_substitution: ($) => seq("${", $._expression, "}"), char_literal: (_) => token( seq( optional("b"), "'", optional( choice( seq( "\\", choice( /[^xu]/, /u[0-9a-fA-F]{4}/, /u{[0-9a-fA-F]+}/, /x[0-9a-fA-F]{2}/, ), ), /[^\\']/, ), ), "'", ), ), escape_sequence: (_) => token.immediate( seq( "\\", choice( /[^xu]/, /u[0-9a-fA-F]{4}/, /u{[0-9a-fA-F]+}/, /x[0-9a-fA-F]{2}/, ), ), ), bool_literal: (_) => choice("true", "false"), nil_literal: (_) => "nil", comment: ($) => choice($.block_comment, $.line_comment), line_comment: (_) => token(seq("//", /.*/)), block_comment: (_) => token(seq("///", /.*/)), _path: ($) => choice( $.self, alias(choice(...primitive_types), $.identifier), $.metavariable, $.super, $.crate, $.identifier, $.scoped_identifier, $._reserved_identifier, ), identifier: (_) => /(r#)?[_\p{XID_Start}][_\p{XID_Continue}]*/, _reserved_identifier: ($) => alias(choice("default", "union"), $.identifier), _type_identifier: ($) => alias($.identifier, $.type_identifier), _field_identifier: ($) => alias($.identifier, $.field_identifier), self: (_) => "self", super: (_) => "super", crate: (_) => "crate", metavariable: (_) => /\$[a-zA-Z_]\w*/, }, }); /** * Creates a rule to match one or more of the rules separated by the separator. * * @param {RuleOrLiteral} sep - The separator to use. * @param {RuleOrLiteral} rule * * @return {SeqRule} * */ function sepBy1(sep, rule) { return seq(rule, repeat(seq(sep, rule))); } /** * Creates a rule to optionally match one or more of the rules separated by the separator. * * @param {RuleOrLiteral} sep - The separator to use. * @param {RuleOrLiteral} rule * * @return {ChoiceRule} * */ function sepBy(sep, rule) { return optional(sepBy1(sep, rule)); }