[][src]Constant tree_sitter_go::GRAMMAR

pub const GRAMMAR: &'static str = "const\n  PREC = {\n    primary: 7,\n    unary: 6,\n    multiplicative: 5,\n    additive: 4,\n    comparative: 3,\n    and: 2,\n    or: 1,\n    composite_literal: -1,\n  },\n\n  multiplicative_operators = [\'*\', \'/\', \'%\', \'<<\', \'>>\', \'&\', \'&^\'],\n  additive_operators = [\'+\', \'-\', \'|\', \'^\'],\n  comparative_operators = [\'==\', \'!=\', \'<\', \'<=\', \'>\', \'>=\'],\n  assignment_operators = multiplicative_operators.concat(additive_operators).map(operator => operator + \'=\').concat(\'=\'),\n\n  unicodeLetter = /[a-zA-Z\u{3b1}-\u{3c9}\u{391}-\u{3a9}\u{b5}]/,\n  unicodeDigit = /[0-9]/,\n  unicodeChar = /./,\n  unicodeValue = unicodeChar,\n  letter = choice(unicodeLetter, \'_\'),\n\n  newline = \'\\n\',\n  terminator = choice(newline, \';\'),\n\n  hexDigit = /[0-9a-fA-F]/,\n  octalDigit = /[0-7]/,\n  decimalDigit = /[0-9]/,\n  binaryDigit = /[01]/,\n\n  hexDigits = seq(hexDigit, repeat(seq(optional(\'_\'), hexDigit))),\n  octalDigits = seq(octalDigit, repeat(seq(optional(\'_\'), octalDigit))),\n  decimalDigits = seq(decimalDigit, repeat(seq(optional(\'_\'), decimalDigit))),\n  binaryDigits = seq(binaryDigit, repeat(seq(optional(\'_\'), binaryDigit))),\n\n  hexLiteral = seq(\'0\', choice(\'x\', \'X\'), optional(\'_\'), hexDigits),\n  octalLiteral = seq(\'0\', optional(choice(\'o\', \'O\')), optional(\'_\'), octalDigits),\n  decimalLiteral = choice(\'0\', seq(/[1-9]/, optional(seq(optional(\'_\'), decimalDigits)))),\n  binaryLiteral = seq(\'0\', choice(\'b\', \'B\'), optional(\'_\'), binaryDigits),\n\n  intLiteral = choice(binaryLiteral, decimalLiteral, octalLiteral, hexLiteral),\n\n  decimalExponent = seq(choice(\'e\', \'E\'), optional(choice(\'+\', \'-\')), decimalDigits),\n  decimalFloatLiteral = choice(\n    seq(decimalDigits, \'.\', optional(decimalDigits), optional(decimalExponent)),\n    seq(decimalDigits, decimalExponent),\n    seq(\'.\', decimalDigits, optional(decimalExponent)),\n  ),\n\n  hexExponent = seq(choice(\'p\', \'P\'), optional(choice(\'+\', \'-\')), decimalDigits),\n  hexMantissa = choice(\n    seq(optional(\'_\'), hexDigits, \'.\', optional(hexDigits)),\n    seq(optional(\'_\'), hexDigits),\n    seq(\'.\', hexDigits),\n  ),\n  hexFloatLiteral = seq(\'0\', choice(\'x\', \'X\'), hexMantissa, hexExponent),\n\n  floatLiteral = choice(decimalFloatLiteral, hexFloatLiteral),\n\n  imaginaryLiteral = seq(choice(decimalDigits, intLiteral, floatLiteral), \'i\')\n\nmodule.exports = grammar({\n  name: \'go\',\n\n  extras: $ => [\n    $.comment,\n    /\\s/\n  ],\n\n  inline: $ => [\n    $._type,\n    $._type_identifier,\n    $._field_identifier,\n    $._package_identifier,\n    $._top_level_declaration,\n    $._string_literal,\n  ],\n\n  word: $ => $.identifier,\n\n  conflicts: $ => [\n    [$._simple_type, $._expression],\n    [$.qualified_type, $._expression],\n    [$.func_literal, $.function_type],\n    [$.function_type],\n    [$.parameter_declaration, $._simple_type],\n  ],\n\n  supertypes: $ => [\n    $._expression,\n    $._type,\n    $._simple_type,\n    $._statement,\n    $._simple_statement,\n  ],\n\n  rules: {\n    source_file: $ => repeat(choice(\n      seq($._statement, terminator),\n      seq($._top_level_declaration, optional(terminator)),\n    )),\n\n    _top_level_declaration: $ => choice(\n      $.package_clause,\n      $.function_declaration,\n      $.method_declaration,\n      $.import_declaration\n    ),\n\n    package_clause: $ => seq(\n      \'package\',\n      $._package_identifier\n    ),\n\n    import_declaration: $ => seq(\n      \'import\',\n      choice(\n        $.import_spec,\n        $.import_spec_list\n      )\n    ),\n\n    import_spec: $ => seq(\n      optional(field(\'name\', choice(\n        $.dot,\n        $.blank_identifier,\n        $._package_identifier\n      ))),\n      field(\'path\', $._string_literal)\n    ),\n    dot: $ => \'.\',\n    blank_identifier: $ => \'_\',\n\n    import_spec_list: $ => seq(\n      \'(\',\n      repeat(seq(\n        $.import_spec,\n        terminator\n      )),\n      \')\'\n    ),\n\n    _declaration: $ => choice(\n      $.const_declaration,\n      $.type_declaration,\n      $.var_declaration\n    ),\n\n    const_declaration: $ => seq(\n      \'const\',\n      choice(\n        $.const_spec,\n        seq(\n          \'(\',\n          repeat(seq($.const_spec, terminator)),\n          \')\'\n        )\n      )\n    ),\n\n    const_spec: $ => prec.left(seq(\n      field(\'name\', commaSep1($.identifier)),\n      optional(seq(\n        optional(field(\'type\', $._type)),\n        \'=\',\n        field(\'value\', $.expression_list)\n      ))\n    )),\n\n    var_declaration: $ => seq(\n      \'var\',\n      choice(\n        $.var_spec,\n        seq(\n          \'(\',\n          repeat(seq($.var_spec, terminator)),\n          \')\'\n        )\n      )\n    ),\n\n    var_spec: $ => seq(\n      field(\'name\', commaSep1($.identifier)),\n      choice(\n        seq(\n          field(\'type\', $._type),\n          optional(seq(\'=\', field(\'value\', $.expression_list)))\n        ),\n        seq(\'=\', field(\'value\', $.expression_list))\n      )\n    ),\n\n    function_declaration: $ => prec.right(1, seq(\n      \'func\',\n      field(\'name\', $.identifier),\n      field(\'parameters\', $.parameter_list),\n      field(\'result\', optional(choice($.parameter_list, $._simple_type))),\n      field(\'body\', optional($.block))\n    )),\n\n    method_declaration: $ => prec.right(1, seq(\n      \'func\',\n      field(\'receiver\', $.parameter_list),\n      field(\'name\', $._field_identifier),\n      field(\'parameters\', $.parameter_list),\n      field(\'result\', optional(choice($.parameter_list, $._simple_type))),\n      field(\'body\', optional($.block))\n    )),\n\n    parameter_list: $ => seq(\n      \'(\',\n      optional(seq(\n        commaSep(choice($.parameter_declaration, $.variadic_parameter_declaration)),\n        optional(\',\')\n      )),\n      \')\'\n    ),\n\n    parameter_declaration: $ => seq(\n      field(\'name\', commaSep($.identifier)),\n      field(\'type\', $._type)\n    ),\n\n    variadic_parameter_declaration: $ => seq(\n      field(\'name\', optional($.identifier)),\n      \'...\',\n      field(\'type\', $._type)\n    ),\n\n    type_alias: $ => seq(\n      field(\'name\', $._type_identifier),\n      \'=\',\n      field(\'type\', $._type)\n    ),\n\n    type_declaration: $ => seq(\n      \'type\',\n      choice(\n        $.type_spec,\n        $.type_alias,\n        seq(\n          \'(\',\n          repeat(seq(choice($.type_spec, $.type_alias), terminator)),\n          \')\'\n        )\n      )\n    ),\n\n    type_spec: $ => seq(\n      field(\'name\', $._type_identifier),\n      field(\'type\', $._type)\n    ),\n\n    field_name_list: $ => commaSep1($._field_identifier),\n\n    expression_list: $ => commaSep1($._expression),\n\n    _type: $ => choice(\n      $._simple_type,\n      $.parenthesized_type\n    ),\n\n    parenthesized_type: $ => seq(\'(\', $._type, \')\'),\n\n    _simple_type: $ => choice(\n      prec.dynamic(-1, $._type_identifier),\n      $.qualified_type,\n      $.pointer_type,\n      $.struct_type,\n      $.interface_type,\n      $.array_type,\n      $.slice_type,\n      $.map_type,\n      $.channel_type,\n      $.function_type\n    ),\n\n    pointer_type: $ => prec(PREC.unary, seq(\'*\', $._type)),\n\n    array_type: $ => seq(\n      \'[\',\n      field(\'length\', $._expression),\n      \']\',\n      field(\'element\', $._type)\n    ),\n\n    implicit_length_array_type: $ => seq(\n      \'[\',\n      \'...\',\n      \']\',\n      field(\'element\', $._type)\n    ),\n\n    slice_type: $ => seq(\n      \'[\',\n      \']\',\n      field(\'element\', $._type)\n    ),\n\n    struct_type: $ => seq(\n      \'struct\',\n      $.field_declaration_list\n    ),\n\n    field_declaration_list: $ => seq(\n      \'{\',\n      optional(seq(\n        $.field_declaration,\n        repeat(seq(terminator, $.field_declaration)),\n        optional(terminator)\n      )),\n      \'}\'\n    ),\n\n    field_declaration: $ => seq(\n      choice(\n        seq(\n          field(\'name\', commaSep1($._field_identifier)),\n          field(\'type\', $._type)\n        ),\n        seq(\n          optional(\'*\'),\n          field(\'type\', choice(\n            $._type_identifier,\n            $.qualified_type\n          ))\n        )\n      ),\n      field(\'tag\', optional($._string_literal))\n    ),\n\n    interface_type: $ => seq(\n      \'interface\',\n      $.method_spec_list\n    ),\n\n    method_spec_list: $ => seq(\n      \'{\',\n      optional(seq(\n        choice($._type_identifier, $.qualified_type, $.method_spec),\n        repeat(seq(terminator, choice($._type_identifier, $.qualified_type, $.method_spec))),\n        optional(terminator)\n      )),\n      \'}\'\n    ),\n\n    method_spec: $ => seq(\n      field(\'name\', $._field_identifier),\n      field(\'parameters\', $.parameter_list),\n      field(\'result\', optional(choice($.parameter_list, $._simple_type)))\n    ),\n\n    map_type: $ => seq(\n      \'map\',\n      \'[\',\n      field(\'key\', $._type),\n      \']\',\n      field(\'value\', $._type)\n    ),\n\n    channel_type: $ => choice(\n      seq(\'chan\', field(\'value\', $._type)),\n      seq(\'chan\', \'<-\', field(\'value\', $._type)),\n      prec(PREC.unary, seq(\'<-\', \'chan\', field(\'value\', $._type)))\n    ),\n\n    function_type: $ => seq(\n      \'func\',\n      field(\'parameters\', $.parameter_list),\n      field(\'result\', optional(choice($.parameter_list, $._simple_type)))\n    ),\n\n    block: $ => seq(\n      \'{\',\n      optional($._statement_list),\n      \'}\'\n    ),\n\n    _statement_list: $ => choice(\n      seq(\n        $._statement,\n        repeat(seq(terminator, $._statement)),\n        optional(seq(\n          terminator,\n          optional(alias($.empty_labeled_statement, $.labeled_statement))\n        ))\n      ),\n      alias($.empty_labeled_statement, $.labeled_statement)\n    ),\n\n    _statement: $ => choice(\n      $._declaration,\n      $._simple_statement,\n      $.return_statement,\n      $.go_statement,\n      $.defer_statement,\n      $.if_statement,\n      $.for_statement,\n      $.expression_switch_statement,\n      $.type_switch_statement,\n      $.select_statement,\n      $.labeled_statement,\n      $.fallthrough_statement,\n      $.break_statement,\n      $.continue_statement,\n      $.goto_statement,\n      $.block,\n      $.empty_statement\n    ),\n\n    empty_statement: $ => \';\',\n\n    _simple_statement: $ => choice(\n      $._expression,\n      $.send_statement,\n      $.inc_statement,\n      $.dec_statement,\n      $.assignment_statement,\n      $.short_var_declaration\n    ),\n\n    send_statement: $ => seq(\n      field(\'channel\', $._expression),\n      \'<-\',\n      field(\'value\', $._expression)\n    ),\n\n    receive_statement: $ => seq(\n      optional(seq(\n        field(\'left\', $.expression_list),\n        choice(\'=\', \':=\')\n      )),\n      field(\'right\', $._expression)\n    ),\n\n    inc_statement: $ => seq(\n      $._expression,\n      \'++\'\n    ),\n\n    dec_statement: $ => seq(\n      $._expression,\n      \'--\'\n    ),\n\n    assignment_statement: $ => seq(\n      field(\'left\', $.expression_list),\n      field(\'operator\', choice(...assignment_operators)),\n      field(\'right\', $.expression_list)\n    ),\n\n    short_var_declaration: $ => seq(\n      // TODO: this should really only allow identifier lists, but that causes\n      // conflicts between identifiers as expressions vs identifiers here.\n      field(\'left\', $.expression_list),\n      \':=\',\n      field(\'right\', $.expression_list)\n    ),\n\n    labeled_statement: $ => seq(\n      field(\'label\', alias($.identifier, $.label_name)),\n      \':\',\n      $._statement\n    ),\n\n    empty_labeled_statement: $ => seq(\n      field(\'label\', alias($.identifier, $.label_name)),\n      \':\'\n    ),\n\n    // This is a hack to prevent `fallthrough_statement` from being parsed as\n    // a single token. For consistency with `break_statement` etc it should\n    // be parsed as a parent node that *contains* a `fallthrough` token.\n    fallthrough_statement: $ => prec.left(\'fallthrough\'),\n\n    break_statement: $ => seq(\'break\', optional(alias($.identifier, $.label_name))),\n\n    continue_statement: $ => seq(\'continue\', optional(alias($.identifier, $.label_name))),\n\n    goto_statement: $ => seq(\'goto\', alias($.identifier, $.label_name)),\n\n    return_statement: $ => seq(\'return\', optional($.expression_list)),\n\n    go_statement: $ => seq(\'go\', $._expression),\n\n    defer_statement: $ => seq(\'defer\', $._expression),\n\n    if_statement: $ => seq(\n      \'if\',\n      optional(seq(\n        field(\'initializer\', $._simple_statement),\n        \';\'\n      )),\n      field(\'condition\', $._expression),\n      field(\'consequence\', $.block),\n      optional(seq(\n        \'else\',\n        field(\'alternative\', choice($.block, $.if_statement))\n      ))\n    ),\n\n    for_statement: $ => seq(\n      \'for\',\n      optional(choice($._expression, $.for_clause, $.range_clause)),\n      field(\'body\', $.block)\n    ),\n\n    for_clause: $ => seq(\n      field(\'initializer\', optional($._simple_statement)),\n      \';\',\n      field(\'condition\', optional($._expression)),\n      \';\',\n      field(\'update\', optional($._simple_statement))\n    ),\n\n    range_clause: $ => seq(\n      optional(seq(\n        field(\'left\', $.expression_list),\n        choice(\'=\', \':=\')\n      )),\n      \'range\',\n      field(\'right\', $._expression)\n    ),\n\n    expression_switch_statement: $ => seq(\n      \'switch\',\n      optional(seq(\n        field(\'initializer\', $._simple_statement),\n        \';\'\n      )),\n      field(\'value\', optional($._expression)),\n      \'{\',\n      repeat(choice($.expression_case, $.default_case)),\n      \'}\'\n    ),\n\n    expression_case: $ => seq(\n      \'case\',\n      field(\'value\', $.expression_list),\n      \':\',\n      optional($._statement_list)\n    ),\n\n    default_case: $ => seq(\n      \'default\',\n      \':\',\n      optional($._statement_list)\n    ),\n\n    type_switch_statement: $ => seq(\n      \'switch\',\n      $._type_switch_header,\n      \'{\',\n      repeat(choice($.type_case, $.default_case)),\n      \'}\'\n    ),\n\n    _type_switch_header: $ => seq(\n      optional(seq(\n        field(\'initializer\', $._simple_statement),\n        \';\'\n      )),\n      optional(seq(field(\'alias\', $.expression_list), \':=\')),\n      field(\'value\', $._expression),\n      \'.\',\n      \'(\',\n      \'type\',\n      \')\'\n    ),\n\n    type_case: $ => seq(\n      \'case\',\n      field(\'type\', commaSep1($._type)),\n      \':\',\n      optional($._statement_list)\n    ),\n\n    select_statement: $ => seq(\n      \'select\',\n      \'{\',\n      repeat(choice($.communication_case, $.default_case)),\n      \'}\'\n    ),\n\n    communication_case: $ => seq(\n      \'case\',\n      field(\'communication\', choice($.send_statement, $.receive_statement)),\n      \':\',\n      optional($._statement_list)\n    ),\n\n    _expression: $ => choice(\n      $.unary_expression,\n      $.binary_expression,\n      $.selector_expression,\n      $.index_expression,\n      $.slice_expression,\n      $.call_expression,\n      $.type_assertion_expression,\n      $.type_conversion_expression,\n      $.identifier,\n      alias(choice(\'new\', \'make\'), $.identifier),\n      $.composite_literal,\n      $.func_literal,\n      $._string_literal,\n      $.int_literal,\n      $.float_literal,\n      $.imaginary_literal,\n      $.rune_literal,\n      $.nil,\n      $.true,\n      $.false,\n      $.parenthesized_expression\n    ),\n\n    parenthesized_expression: $ => seq(\n      \'(\',\n      $._expression,\n      \')\'\n    ),\n\n    call_expression: $ => prec(PREC.primary, choice(\n      seq(\n        field(\'function\', alias(choice(\'new\', \'make\'), $.identifier)),\n        field(\'arguments\', alias($.special_argument_list, $.argument_list))\n      ),\n      seq(\n        field(\'function\', $._expression),\n        field(\'arguments\', $.argument_list)\n      )\n    )),\n\n    variadic_argument: $ => prec.right(seq(\n      $._expression,\n      \'...\'\n    )),\n\n    special_argument_list: $ => seq(\n      \'(\',\n      $._type,\n      repeat(seq(\',\', $._expression)),\n      optional(\',\'),\n      \')\'\n    ),\n\n    argument_list: $ => seq(\n      \'(\',\n      optional(seq(\n        choice($._expression, $.variadic_argument),\n        repeat(seq(\',\', choice($._expression, $.variadic_argument))),\n        optional(\',\')\n      )),\n      \')\'\n    ),\n\n    selector_expression: $ => prec(PREC.primary, seq(\n      field(\'operand\', $._expression),\n      \'.\',\n      field(\'field\', $._field_identifier)\n    )),\n\n    index_expression: $ => prec(PREC.primary, seq(\n      field(\'operand\', $._expression),\n      \'[\',\n      field(\'index\', $._expression),\n      \']\'\n    )),\n\n    slice_expression: $ => prec(PREC.primary, seq(\n      field(\'operand\', $._expression),\n      \'[\',\n      choice(\n        seq(\n          field(\'start\', optional($._expression)),\n          \':\',\n          field(\'end\', optional($._expression))\n        ),\n        seq(\n          field(\'start\', optional($._expression)),\n          \':\',\n          field(\'end\', $._expression),\n          \':\',\n          field(\'capacity\', $._expression)\n        )\n      ),\n      \']\'\n    )),\n\n    type_assertion_expression: $ => prec(PREC.primary, seq(\n      field(\'operand\', $._expression),\n      \'.\',\n      \'(\',\n      field(\'type\', $._type),\n      \')\'\n    )),\n\n    type_conversion_expression: $ => prec.dynamic(-1, seq(\n      field(\'type\', $._type),\n      \'(\',\n      field(\'operand\', $._expression),\n      optional(\',\'),\n      \')\'\n    )),\n\n    composite_literal: $ => prec(PREC.composite_literal, seq(\n      field(\'type\', choice(\n        $.map_type,\n        $.slice_type,\n        $.array_type,\n        $.implicit_length_array_type,\n        $.struct_type,\n        $._type_identifier,\n        $.qualified_type\n      )),\n      field(\'body\', $.literal_value)\n    )),\n\n    literal_value: $ => seq(\n      \'{\',\n      optional(seq(\n        choice($.element, $.keyed_element),\n        repeat(seq(\',\', choice($.element, $.keyed_element))),\n        optional(\',\')\n      )),\n      \'}\'\n    ),\n\n    keyed_element: $ => seq(\n      choice(\n        seq($._expression, \':\'),\n        seq($.literal_value, \':\'),\n        prec(1, seq($._field_identifier, \':\'))\n      ),\n      choice(\n        $._expression,\n        $.literal_value\n      )\n    ),\n\n    element: $ => choice(\n      $._expression,\n      $.literal_value\n    ),\n\n    func_literal: $ => seq(\n      \'func\',\n      field(\'parameters\', $.parameter_list),\n      field(\'result\', optional(choice($.parameter_list, $._simple_type))),\n      field(\'body\', $.block)\n    ),\n\n    unary_expression: $ => prec(PREC.unary, seq(\n      field(\'operator\', choice(\'+\', \'-\', \'!\', \'^\', \'*\', \'&\', \'<-\')),\n      field(\'operand\', $._expression)\n    )),\n\n    binary_expression: $ => {\n      const table = [\n        [PREC.multiplicative, choice(...multiplicative_operators)],\n        [PREC.additive, choice(...additive_operators)],\n        [PREC.comparative, choice(...comparative_operators)],\n        [PREC.and, \'&&\'],\n        [PREC.or, \'||\'],\n      ];\n\n      return choice(...table.map(([precedence, operator]) =>\n        prec.left(precedence, seq(\n          field(\'left\', $._expression),\n          field(\'operator\', operator),\n          field(\'right\', $._expression)\n        ))\n      ));\n    },\n\n    qualified_type: $ => seq(\n      field(\'package\', $._package_identifier),\n      \'.\',\n      field(\'name\', $._type_identifier)\n    ),\n\n    identifier: $ => token(seq(\n      letter,\n      repeat(choice(letter, unicodeDigit))\n    )),\n\n    _type_identifier: $ => alias($.identifier, $.type_identifier),\n    _field_identifier: $ => alias($.identifier, $.field_identifier),\n    _package_identifier: $ => alias($.identifier, $.package_identifier),\n\n    _string_literal: $ => choice(\n      $.raw_string_literal,\n      $.interpreted_string_literal\n    ),\n\n    raw_string_literal: $ => token(seq(\n      \'`\',\n      repeat(/[^`]/),\n      \'`\'\n    )),\n\n    interpreted_string_literal: $ => seq(\n      \'\"\',\n      repeat(choice(\n        token.immediate(prec(1, /[^\"\\n\\\\]+/)),\n        $.escape_sequence\n      )),\n      \'\"\'\n    ),\n\n    escape_sequence: $ => token.immediate(seq(\n      \'\\\\\',\n      choice(\n        /[^xuU]/,\n        /\\d{2,3}/,\n        /x[0-9a-fA-F]{2,}/,\n        /u[0-9a-fA-F]{4}/,\n        /U[0-9a-fA-F]{8}/\n      )\n    )),\n\n    int_literal: $ => token(intLiteral),\n\n    float_literal: $ => token(floatLiteral),\n\n    imaginary_literal: $ => token(imaginaryLiteral),\n\n    rune_literal: $ => token(seq(\n      \"\'\",\n      choice(\n        /[^\'\\\\]/,\n        seq(\n          \'\\\\\',\n          choice(\n            seq(\'x\', hexDigit, hexDigit),\n            seq(octalDigit, octalDigit, octalDigit),\n            seq(\'u\', hexDigit, hexDigit, hexDigit, hexDigit),\n            seq(\'U\', hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit),\n            seq(choice(\'a\', \'b\', \'f\', \'n\', \'r\', \'t\', \'v\', \'\\\\\', \"\'\", \'\"\'))\n          )\n        )\n      ),\n      \"\'\"\n    )),\n\n    nil: $ => \'nil\',\n    true: $ => \'true\',\n    false: $ => \'false\',\n\n    // http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890\n    comment: $ => token(choice(\n      seq(\'//\', /.*/),\n      seq(\n        \'/*\',\n        /[^*]*\\*+([^/*][^*]*\\*+)*/,\n        \'/\'\n      )\n    ))\n  }\n})\n\nfunction commaSep1(rule) {\n  return seq(rule, repeat(seq(\',\', rule)))\n}\n\nfunction commaSep(rule) {\n  return optional(commaSep1(rule))\n}\n";

The source of the Go tree-sitter grammar description.