GRAMMAR

Constant GRAMMAR 

Source
pub const GRAMMAR: &str = "/**\n * @file Squirrel grammar for tree-sitter\n * @author Amaan Qureshi <amaanq12@gmail.com>\n * @license MIT\n * @see {@link http://squirrel-lang.org|official website}\n * @see {@link https://github.com/albertodemichelis/squirrel|official repository}\n * @see {@link http://squirrel-lang.org/squirreldoc/reference/index.html|official spec}\n */\n\n// deno-lint-ignore-file ban-ts-comment\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\n// http://squirrel-lang.org/squirreldoc/reference/language/expressions.html#operators-precedence\nconst PREC = {\n  PAREN: -1,\n  ASSIGN: 1,\n  TERNARY: 2,\n  LOGICAL_OR: 3,\n  LOGICAL_AND: 4,\n  IN: 4,\n  INCLUSIVE_OR: 5,\n  EXCLUSIVE_OR: 6,\n  BITWISE_AND: 7,\n  EQUALITY: 8,\n  COMPARISON: 9,\n  INSTANCEOF: 9,\n  SHIFT: 10,\n  ADDITIVE: 11,\n  MULTIPLICATIVE: 12,\n  UNARY: 13,\n  CALL: 14,\n  MEMBER: 15,\n};\n\n/**\n * Creates a rule to match zero or more of the rules optionally separated by a comma\n *\n * @param {Rule} rule\n *\n * @return {SeqRule}\n *\n */\nfunction optionalCommaSep(rule) {\n  return sep1(rule, optional(\',\'));\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 of the rules separated by the separator\n*\n* @param {Rule} rule\n* @param {string|Rule} separator - The separator to use.\n*\n* @return {SeqRule}\n*\n*/\nfunction sep1(rule, separator) {\n  return seq(rule, repeat(seq(separator, rule)));\n}\n\nmodule.exports = grammar({\n  name: \'squirrel\',\n\n  externals: $ => [\n    $.verbatim_string,\n  ],\n\n  extras: $ => [\n    $.comment,\n    /\\s/,\n  ],\n\n  inline: $ => [\n    $.expression_statement,\n    $._statements,\n    $._statement,\n  ],\n\n  supertypes: $ => [\n    $.expression,\n    $.primary_expression,\n    // $._statement,\n  ],\n\n  word: $ => $.identifier,\n\n  rules: {\n    script: $ => optional($._statements),\n\n    _statements: $ => repeat1($._statement),\n\n    _statement: $ => choice(\n      $.block,\n      $.if_statement,\n      $.while_statement,\n      $.do_while_statement,\n      $.switch_statement,\n      $.for_statement,\n      $.foreach_statement,\n      $.break,\n      $.continue,\n      $.return,\n      $.yield,\n      $.local_declaration,\n      $.var_statement,\n      $.function_declaration,\n      $.class_declaration,\n      $.try_statement,\n      $.throw_statement,\n      $.const_declaration,\n      $.enum_declaration,\n      $.expression_statement,\n    ),\n\n    expression_statement: $ =>\n      prec.right(choice(\n        seq(\n          $.expression,\n          optional(\';\'),\n        ),\n        \';\',\n      )),\n\n    block: $ => seq(\n      \'{\',\n      repeat($._statement),\n      \'}\',\n    ),\n\n    if_statement: $ => prec.right(1, seq(\n      \'if\',\n      field(\'condition\', $.parenthesized_expression),\n      field(\'consequence\', $._statement),\n      optional($.else_statement),\n    )),\n    else_statement: $ => prec.right(1, seq(\n      \'else\',\n      field(\'alternative\', $._statement),\n    )),\n\n    while_statement: $ => prec.right(seq(\n      \'while\',\n      \'(\', $.expression, \')\',\n      optional($._statement),\n      // optional(\';\'),\n    )),\n\n    do_while_statement: $ => prec.right(seq(\n      \'do\',\n      $._statement,\n      \'while\',\n      \'(\', $.expression, \')\',\n      // optional(\';\'),\n    )),\n\n    switch_statement: $ => seq(\n      \'switch\',\n      \'(\', $.expression, \')\',\n      \'{\',\n      repeat($.case_statement),\n      optional($.default_statement),\n      \'}\',\n    ),\n    case_statement: $ => seq(\n      \'case\',\n      field(\'case\', $.expression),\n      \':\',\n      repeat($._statement),\n    ),\n    default_statement: $ => seq(\n      \'default\',\n      \':\',\n      repeat($._statement),\n    ),\n\n    for_statement: $ => seq(\n      \'for\',\n      \'(\',\n      field(\'initial\', optional(choice($.expression, $.local_declaration))),\n      \';\',\n      field(\'condition\', optional($.expression)),\n      \';\',\n      field(\'increment\', optional($.expression)),\n      \')\',\n      $._statement,\n    ),\n\n    foreach_statement: $ => seq(\n      \'foreach\',\n      \'(\',\n      optional(seq(field(\'index\', $.identifier), \',\')),\n      field(\'value\', $.identifier),\n      \'in\',\n      field(\'collection\', $.expression),\n      \')\',\n      $._statement,\n    ),\n\n    break: _ => seq(\'break\', \';\'),\n\n    continue: _ => seq(\'continue\', \';\'),\n\n    return: $ => prec.right(seq(\n      \'return\',\n      optional(choice($.expression, $.table)),\n      // NOTE: Feels like it should be explicitly \';\' but some files omit this\n      optional(\';\'),\n    )),\n\n    yield: $ => seq(\n      \'yield\',\n      optional($.expression),\n      choice(\';\', \'\\n\'),\n    ),\n\n    resume_expression: $ => seq(\n      \'resume\',\n      $.expression,\n    ),\n\n    local_declaration: $ => prec.left(seq(\'local\', $._initz, optional(\';\'))),\n    _initz: $ => prec.right(seq(\n      $.identifier,\n      optional(seq(choice(\'=\', \'<-\'), choice($.expression, $.table))),\n      optional(seq(\',\', $._initz)),\n    )),\n\n    function_declaration: $ => seq(\n      \'function\',\n      $.identifier,\n      repeat(seq(\'::\', $.identifier)),\n      \'(\',\n      optional($.parameters),\n      \')\',\n      $._statement,\n    ),\n    parameters: $ => commaSep1($.parameter),\n    parameter: $ => choice(\n      seq(\n        $.identifier,\n        optional(seq(\'=\', $.const_value)),\n      ),\n      \'...\',\n    ),\n\n\n    class_declaration: $ => seq(\n      \'class\',\n      $.identifier,\n      repeat(seq(\'.\', $.identifier)),\n      optional(seq(\'extends\', $.identifier)),\n      optional($.attribute_declaration),\n      \'{\',\n      repeat($.member_declaration),\n      \'}\',\n    ),\n    member_declaration: $ => seq(\n      optional($.attribute_declaration),\n      choice(\n        seq(optional($.qualifier), $.identifier, \'=\', choice($.expression, $.table), optional(\';\')),\n        seq(\'[\', $.expression, \']\', \'=\', $.expression, optional(\';\')),\n        $.function_declaration,\n        seq(\'constructor\', \'(\', optional($.parameters), \')\', $._statement),\n      ),\n    ),\n    qualifier: _ => choice(\n      \'static\',\n    ),\n\n    try_statement: $ => seq(\n      \'try\',\n      $._statement,\n      $.catch_statement,\n    ),\n    catch_statement: $ => seq(\n      \'catch\',\n      \'(\',\n      $.identifier,\n      \')\',\n      $._statement,\n    ),\n\n    throw_statement: $ => prec.right(seq(\n      \'throw\',\n      $.expression,\n      optional(\';\'),\n    )),\n\n    const_declaration: $ => seq(\n      \'const\',\n      $.identifier,\n      \'=\',\n      $.const_value,\n      // optional(\';\'),\n      choice(\';\', \'\\n\'),\n    ),\n    const_value: $ => choice(\n      $.array,\n      $.table,\n      $.integer,\n      $.float,\n      $.string,\n      $.verbatim_string,\n      $.char,\n      $.bool,\n      $.null,\n      $.call_expression,\n      $.identifier,\n      $.global_variable,\n    ),\n\n    enum_declaration: $ => prec.right(seq(\n      \'enum\',\n      $.identifier,\n      optional($.attribute_declaration),\n      \'{\',\n      commaSep1(seq($.identifier, optional(seq(\'=\', $.const_value)))),\n      \'}\',\n      optional(\';\'),\n    )),\n\n    attribute_declaration: $ => seq(\n      \'</\',\n      commaSep1(\n        seq(\n          field(\'left\', $.identifier),\n          field(\'operator\', \'=\'),\n          field(\'right\', $.const_value),\n        ),\n      ),\n      \'/>\',\n    ),\n\n    expression: $ => choice(\n      // $.table,\n      $.delete_expression,\n      $.clone_expression,\n      $.array,\n      $.assignment_expression,\n      $.update_expression,\n      $.resume_expression,\n      $.primary_expression,\n    ),\n\n    primary_expression: $ => prec.right(choice(\n      $.unary_expression,\n      $.binary_expression,\n      $.ternary_expression,\n      $.anonymous_function,\n      $.deref_expression,\n      $.index_expression,\n      $.call_expression,\n      $.lambda_expression,\n      $.parenthesized_expression,\n      $.integer,\n      $.float,\n      $.string,\n      $.verbatim_string,\n      $.char,\n      $.bool,\n      $.null,\n      $.identifier,\n      $.global_variable,\n    )),\n\n    unary_expression: $ => prec.left(PREC.UNARY, choice(\n      seq(\n        field(\'operator\', choice(\'-\', \'~\', \'!\', \'typeof\', \'++\', \'--\')),\n        field(\'operand\', choice($.expression, $.table)),\n        optional(\';\'),\n      ),\n      seq(\n        field(\'operand\', $.expression),\n        field(\'operator\', choice(\'++\', \'--\')),\n        optional(\';\'),\n      ),\n    )),\n\n    binary_expression: $ => {\n      const table = [\n        [\'+\', PREC.ADDITIVE],\n        [\'-\', PREC.ADDITIVE],\n        [\'*\', PREC.MULTIPLICATIVE],\n        [\'/\', PREC.MULTIPLICATIVE],\n        [\'%\', PREC.MULTIPLICATIVE],\n        [\'||\', PREC.LOGICAL_OR],\n        [\'&&\', PREC.LOGICAL_AND],\n        [\'in\', PREC.IN],\n        [\'|\', PREC.INCLUSIVE_OR],\n        [\'^\', PREC.EXCLUSIVE_OR],\n        [\'&\', PREC.BITWISE_AND],\n        [\'==\', PREC.EQUALITY],\n        [\'!=\', PREC.EQUALITY],\n        [\'<=>\', PREC.COMPARISON],\n        [\'>\', PREC.COMPARISON],\n        [\'>=\', PREC.COMPARISON],\n        [\'<=\', PREC.COMPARISON],\n        [\'<\', PREC.COMPARISON],\n        [\'instanceof\', PREC.INSTANCEOF],\n        [\'<<\', PREC.SHIFT],\n        [\'>>\', PREC.SHIFT],\n        [\'>>>\', PREC.SHIFT],\n      ];\n\n      return choice(...table.map(([operator, precedence]) => {\n        return prec.left(precedence, seq(\n          field(\'left\', $.expression),\n          // @ts-ignore\n          field(\'operator\', operator),\n          field(\'right\', $.expression),\n          optional(\';\'),\n        ));\n      }));\n    },\n\n    ternary_expression: $ => prec.right(PREC.TERNARY, seq(\n      field(\'condition\', $.expression),\n      \'?\',\n      field(\'consequence\', choice($.expression, $.table)),\n      \':\',\n      field(\'alternative\', choice($.expression, $.table)),\n    )),\n\n    assignment_expression: $ => prec.right(PREC.ASSIGN, seq(\n      field(\'left\', $.expression),\n      field(\'operator\', \'=\'),\n      field(\'right\', choice($.expression, $.table)),\n    )),\n\n    update_expression: $ => prec.right(PREC.ASSIGN, seq(\n      field(\'left\', $.expression),\n      field(\'operator\', choice(\n        \'<-\',\n        \'+=\',\n        \'-=\',\n        \'*=\',\n        \'/=\',\n        \'%=\',\n      )),\n      field(\'right\', choice($.expression, $.table)),\n    )),\n\n    table: $ => prec.right(seq(\n      \'{\',\n      optional($.table_slots),\n      \'}\',\n      optional(seq(\'.\', $.expression)),\n    )),\n    table_slots: $ => seq(\n      optionalCommaSep($.table_slot),\n      optional(\',\'),\n    ),\n    table_slot: $ => choice(\n      seq($.identifier, \'=\', choice($.expression, $.table)),\n      seq(\'[\', $.expression, \']\', \'=\', choice($.expression, $.table)),\n      seq($.expression, \':\', choice($.expression, $.table)),\n      $.function_declaration,\n    ),\n\n    delete_expression: $ => seq(\n      \'delete\',\n      $.expression,\n      choice(\';\', \'\\n\'),\n    ),\n\n    var_statement: $ => (seq(\n      \'var\',\n      $.identifier,\n      \'=\',\n      $.expression,\n    )),\n\n    deref_expression: $ => prec(PREC.MEMBER, choice(\n      seq(\n        $.expression,\n        \'.\',\n        $.identifier,\n      ),\n    )),\n\n    index_expression: $ => prec.left(PREC.MEMBER, seq(\n      field(\'object\', $.expression),\n      \'[\',\n      field(\'index\', $.expression),\n      \']\',\n    )),\n\n    call_expression: $ => prec.left(PREC.CALL, seq(\n      choice(field(\'function\', $.expression), \'rawcall\'),\n      \'(\',\n      optional($.call_args),\n      \')\',\n    )),\n\n    call_args: $ => commaSep1(choice(\n      $.expression,\n      $.table,\n    )),\n    anonymous_function: $ => seq(\n      \'function\',\n      \'(\',\n      optional($.parameters),\n      \')\',\n      $._statement,\n    ),\n\n    lambda_expression: $ => seq(\n      \'@\',\n      \'(\',\n      optional($.parameters),\n      \')\',\n      $.expression,\n    ),\n\n    parenthesized_expression: $ => prec(PREC.PAREN, seq(\n      \'(\',\n      $.expression,\n      \')\',\n    )),\n\n    clone_expression: $ => prec.right(seq(\n      \'clone\',\n      $.expression,\n      // optional(\';\'),\n    )),\n\n    array: $ => prec.right(seq(\n      \'[\',\n      commaSep($.expression),\n      optional(\',\'),\n      \']\',\n    )),\n\n    identifier: _ => /[a-zA-Z_][a-zA-Z0-9_]*/,\n    global_variable: $ => seq(\'::\', $.identifier),\n\n    // IntegerLiteral ::= [1-9][0-9]* | \'0x\' [0-9A-Fa-f]+ | \'\'\' [.]+ \'\'\' | 0[0-7]+\n    integer: _ => token(choice(\n      /0/,\n      /-?[1-9][0-9]*/,\n      /0[xX][0-9A-Fa-f]+/,\n      /\'\'\'[.]+\'\'\'/,\n      /0[0-7]+/,\n    )),\n\n    // FloatLiteral ::= [0-9]+ \'.\' [0-9]+\n    // FloatLiteral ::= [0-9]+ \'.\' \'e\'|\'E\' \'+\'|\'-\' [0-9]+\n    float: _ => token(choice(\n      /-?[0-9]+\\.[0-9]+/,\n      /[0-9]+\\.[eE][+-]?[0-9]+/,\n    )),\n\n    string: $ => seq(\n      \'\"\',\n      repeat(choice(\n        $.string_content,\n        $._escape_sequence,\n      )),\n      \'\"\',\n    ),\n\n    // Workaround to https://github.com/tree-sitter/tree-sitter/issues/1156\n    // We give names to the token_ constructs containing a regexp\n    // so as to obtain a node in the CST.\n    string_content: _ => token.immediate(prec(1, /[^\"\\\\]+/)),\n\n    char: $ => choice(\n      seq(\n        \'\\\'\',\n        choice(\n          $.escape_sequence,\n          /[^\\\\\']/,\n        ),\n        \'\\\'\',\n      ),\n      // workaround because for some reason the char literal \'#\' is being interpreted as a comment\n      \'\\\'#\\\'\',\n    ),\n\n    _escape_sequence: $ =>\n      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      ))),\n\n    bool: _ => choice(\'true\', \'false\'),\n\n    null: _ => \'null\',\n\n    comment: _ =>\n      token(\n        choice(\n          seq(\'#\', /.*/),\n          seq(\'//\', /(\\\\(.|\\r?\\n)|[^\\\\\\n])*/),\n          seq(\'/*\', /[^*]*\\*+([^/*][^*]*\\*+)*/, \'/\'),\n        ),\n      ),\n  },\n});\n\nmodule.exports.PREC = PREC;\n";
Expand description

The source of the Rust tree-sitter grammar description.