Constant tree_sitter_luau::GRAMMAR

source ·
pub const GRAMMAR: &str = "/**\n * @file Luau grammar for tree-sitter\n * @author Amaan Qureshi <amaanq12@gmail.com>\n * @license MIT\n */\n\n/* eslint-disable arrow-parens */\n/* eslint-disable camelcase */\n/* eslint-disable-next-line spaced-comment */\n/// <reference types=\"tree-sitter-cli/dsl\" />\n// @ts-check\n\nconst lua = require(\'@muniftanjim/tree-sitter-lua/grammar\');\n\nconst PREC = {\n  ASSIGN: 0,\n  OR: 1, // or\n  AND: 2, // and\n  COMPARE: 3, // < > <= >= ~= ==\n  BIT_OR: 4, // |\n  BIT_NOT: 5, // ~\n  BIT_AND: 6, // &\n  BIT_SHIFT: 7, // << >>\n  CONCAT: 8, // ..\n  PLUS: 9, // + -\n  MULTI: 10, // * / // %\n  CAST: 11, // ::\n  UNARY: 12, // not # -\n  POWER: 13, // ^\n};\n\n/**\n * Creates a rule to match one or more of the rules separated by a comma\n *\n * @param {Rule} rule\n *\n * @return {SeqRule}\n *\n */\nfunction commaSep1(rule) {\n  return sep1(rule, \',\');\n}\n\n/**\n  * Creates a rule to match zero or more of the rules separated by a comma\n  * @param {Rule} rule\n  * @return {ChoiceRule}\n  */\nfunction commaSep(rule) {\n  return optional(commaSep1(rule));\n}\n\n/**\n * Creates a rule to match one or more occurrences of `rule` separated by `sep`\n *\n * @param {RegExp|Rule|String} rule\n *\n * @param {RegExp|Rule|String} sep\n *\n * @return {SeqRule}\n *\n */\nfunction sep1(rule, sep) {\n  return seq(rule, repeat(seq(sep, rule)));\n}\n\n\n/**\n * Creates a rule to match two or more occurrences of `rule` separated by `sep`\n *\n * @param {RegExp|Rule|String} rule\n *\n * @param {RegExp|Rule|String} sep\n *\n * @return {SeqRule}\n *\n */\nfunction sep2(rule, sep) {\n  return seq(rule, repeat1(seq(sep, rule)));\n}\n\nconst optional_block = $ => alias(optional($._block), $.block);\n\nmodule.exports = grammar(lua, {\n  name: \'luau\',\n\n  rules: {\n    // Luau has no goto and label statements, and has continue statements\n    statement: ($, original) => choice(\n      ...original.members.filter(\n        member => member.name !== \'goto_statement\' && member.name !== \'label_statement\',\n      ),\n      $.update_statement,\n      $.continue_statement,\n      $.type_definition,\n    ),\n\n    update_statement: $ => seq(\n      alias($._variable_assignment_varlist, $.variable_list),\n      choice(\'+=\', \'-=\', \'*=\', \'/=\', \'%=\', \'^=\', \'..=\'),\n      alias($._variable_assignment_explist, $.expression_list),\n    ),\n\n    continue_statement: _ => \'continue\',\n\n    type_definition: $ => seq(\n      optional(\'export\'),\n      \'type\',\n      field(\'name\', $.type),\n      \'=\',\n      choice(\n        $.type,\n        seq(\'typeof\', \'(\', $.expression, \')\'),\n      ),\n    ),\n\n    _function_body: $ => seq(\n      optional($.generic_type_list),\n      field(\'parameters\', $.parameters),\n      optional(seq(\':\', $.type)),\n      field(\'body\', optional_block($)),\n      \'end\',\n    ),\n    generic_type_list: $ => seq(\'<\', commaSep1($.identifier), \'>\'),\n    _parameter_list: $ => choice(\n      seq(commaSep1($.parameter), optional(seq(\',\', $.vararg_expression))),\n      $.vararg_expression,\n    ),\n\n    parameter: $ => seq($.identifier, optional(seq(\':\', $.type))),\n\n    _att_name_list: $ => sep1(\n      seq(\n        field(\'name\', $.identifier),\n        optional(seq(\':\', $.type)),\n        optional(field(\'attribute\', alias($._attrib, $.attribute))),\n      ),\n      \',\',\n    ),\n\n    type: $ => prec.right(choice(\n      $.identifier,\n      $.builtin_type,\n      $.tuple_type,\n      $.function_type,\n      $.generic_type,\n      $.object_type,\n      $.empty_type,\n      $.field_type,\n      $.union_type,\n      $.optional_type,\n      $.literal_type,\n    )),\n\n    builtin_type: _ => choice(\n      \'thread\',\n      \'buffer\',\n      \'any\',\n      \'userdata\',\n      \'unknown\',\n      \'never\',\n      \'string\',\n      \'number\',\n      \'table\',\n      \'boolean\',\n      \'nil\',\n    ),\n\n    tuple_type: $ => seq(\'(\', commaSep1($.type), \')\'),\n\n    function_type: $ => prec.right(seq(\n      \'(\',\n      choice(\n        seq(commaSep(seq($.identifier, \':\', $.type)), optional(seq(\',\', commaSep($.type)))),\n        commaSep($.type),\n      ),\n      \')\',\n      \'->\',\n      $.type,\n    )),\n\n    generic_type: $ => seq($.identifier, \'<\', commaSep($.type), \'>\'),\n\n    object_type: $ => seq(\n      \'{\',\n      choice(\n        commaSep1(\n          seq(choice($.identifier, $.object_field_type), \':\', $.type),\n        ),\n        commaSep1($.type),\n      ),\n      optional(\',\'),\n      \'}\',\n    ),\n\n    empty_type: _ => seq(\'(\', \')\'),\n\n    field_type: $ => sep2($.identifier, \'.\'),\n\n    object_field_type: $ => seq(\'[\', $.type, \']\'),\n\n    union_type: $ => prec.left(1, seq($.type, \'|\', $.type)),\n\n    intersection_type: $ => prec.left(2, seq($.type, \'&\', $.type)),\n\n    optional_type: $ => seq($.type, \'?\'),\n\n    literal_type: $ => choice($.string, $.true, $.false),\n\n    expression: ($, original) => choice(\n      original,\n      $.cast_expression,\n      $.if_expression,\n    ),\n\n    // Luau has no bitwise operators\n    binary_expression: $ => choice(\n      ...[\n        [\'or\', PREC.OR],\n        [\'and\', PREC.AND],\n        [\'<\', PREC.COMPARE],\n        [\'<=\', PREC.COMPARE],\n        [\'==\', PREC.COMPARE],\n        [\'~=\', PREC.COMPARE],\n        [\'>=\', PREC.COMPARE],\n        [\'>\', PREC.COMPARE],\n        [\'+\', PREC.PLUS],\n        [\'-\', PREC.PLUS],\n        [\'*\', PREC.MULTI],\n        [\'/\', PREC.MULTI],\n        [\'//\', PREC.MULTI],\n        [\'%\', PREC.MULTI],\n      ].map(([operator, precedence]) =>\n        prec.left(\n          precedence,\n          seq(\n            field(\'left\', $.expression),\n            // @ts-ignore\n            operator,\n            field(\'right\', $.expression),\n          ),\n        ),\n      ),\n      ...[\n        [\'..\', PREC.CONCAT],\n        [\'^\', PREC.POWER],\n      ].map(([operator, precedence]) =>\n        prec.right(\n          precedence,\n          seq(\n            field(\'left\', $.expression),\n            // @ts-ignore\n            operator,\n            field(\'right\', $.expression),\n          ),\n        ),\n      ),\n    ),\n\n    unary_expression: ($) => prec.left(\n      PREC.UNARY,\n      seq(choice(\'not\', \'#\', \'-\'), field(\'operand\', $.expression)),\n    ),\n\n    cast_expression: $ => prec(PREC.CAST, seq(\n      $.expression,\n      \'::\',\n      $.type,\n    )),\n\n    if_expression: $ => prec.right(seq(\n      \'if\',\n      field(\'condition\', $.expression),\n      \'then\',\n      field(\'consequence\', $.expression),\n      repeat($.elseif_clause),\n      optional($.else_clause),\n    )),\n\n    elseif_clause: $ => seq(\n      \'elseif\',\n      field(\'condition\', $.expression),\n      \'then\',\n      field(\'consequence\', $.expression),\n    ),\n\n    else_clause: $ => seq(\n      \'else\',\n      field(\'consequence\', $.expression),\n    ),\n\n    // Luau can have hex and binary numbers, with the 0x and 0b prefixes, and can have underscores\n    number: _ => {\n      const decimal_digits = /[0-9][0-9_]*/;\n      const signed_integer = seq(optional(choice(\'-\', \'+\')), decimal_digits);\n      const decimal_exponent_part = seq(choice(\'e\', \'E\'), signed_integer);\n\n      const hex_digits = /[a-fA-F0-9][a-fA-F0-9_]*/;\n      const hex_exponent_part = seq(choice(\'p\', \'P\'), signed_integer);\n\n      const binary_digits = /[0-1][0-1_]*/;\n\n      const decimal_literal = choice(\n        seq(\n          decimal_digits,\n          \'.\',\n          optional(decimal_digits),\n          optional(decimal_exponent_part),\n        ),\n        seq(\'.\', decimal_digits, optional(decimal_exponent_part)),\n        seq(decimal_digits, optional(decimal_exponent_part)),\n      );\n\n      const hex_literal = seq(\n        choice(\'0x\', \'0X\'),\n        hex_digits,\n        optional(seq(\'.\', hex_digits)),\n        optional(hex_exponent_part),\n      );\n\n      const binary_literal = seq(\n        choice(\'0b\', \'0B\'),\n        binary_digits,\n      );\n\n      return token(choice(decimal_literal, hex_literal, binary_literal));\n    },\n\n    string: ($, original) => choice(\n      original,\n      $._interpolated_string,\n    ),\n\n    _interpolated_string: $ => seq(\n      \'`\',\n      repeat(choice(\n        field(\'content\', alias($._interpolation_string_content, $.string_content)),\n        $._escape_sequence,\n        $.interpolation,\n      )),\n      \'`\',\n    ),\n\n    _interpolation_string_content: _ => choice(token.immediate(prec(1, /[^`\\{\\\\]+/)), \'\\\\{\'),\n\n    _escape_sequence: $ => choice(\n      prec(2, token.immediate(seq(\'\\\\\', /[^abfnrtvxu\'\\\"\\\\\\?]/))),\n      prec(1, $.escape_sequence),\n    ),\n\n    escape_sequence: _ => token.immediate(seq(\n      \'\\\\\',\n      choice(\n        /[^xu0-7]/,\n        /[0-7]{1,3}/,\n        /x[0-9a-fA-F]{2}/,\n        /u[0-9a-fA-F]{4}/,\n        /u{[0-9a-fA-F]+}/,\n        /U[0-9a-fA-F]{8}/,\n      ),\n    )),\n\n    interpolation: $ => seq(\'{\', $.expression, \'}\'),\n\n    // Name\n    identifier: _ => {\n      const identifier_start =\n        /[^\\p{Control}\\s+\\-*/%^#&~|<>=(){}\\[\\];:,.\\\\\'\"`?\\d]/;\n      const identifier_continue =\n        /[^\\p{Control}\\s+\\-*/%^#&~|<>=(){}\\[\\];:,.\\\\\'\"`?]*/;\n      return token(seq(identifier_start, identifier_continue));\n    },\n  },\n});\n";
Expand description

The content of the [node-types.json][] file for this grammar. The source of the Rust tree-sitter grammar description.