aboutsummaryrefslogtreecommitdiff
path: root/vendor/tree-sitter-zig/grammar.js
diff options
context:
space:
mode:
authorDavid Czihak <git@dcz.at>2026-05-07 14:33:19 +0200
committerDavid Czihak <git@dcz.at>2026-05-07 14:33:19 +0200
commitddf2de739068b5ff0866ccb1d067f3cb53a4fc55 (patch)
tree1a77efe9d73a6172be3c37d29b321eadd4efe379 /vendor/tree-sitter-zig/grammar.js
Initial commitv0.1.7
Diffstat (limited to 'vendor/tree-sitter-zig/grammar.js')
-rw-r--r--vendor/tree-sitter-zig/grammar.js898
1 files changed, 898 insertions, 0 deletions
diff --git a/vendor/tree-sitter-zig/grammar.js b/vendor/tree-sitter-zig/grammar.js
new file mode 100644
index 0000000..e167748
--- /dev/null
+++ b/vendor/tree-sitter-zig/grammar.js
@@ -0,0 +1,898 @@
+/**
+ * @file Zig grammar for tree-sitter
+ * @author Amaan Qureshi <amaanq12@gmail.com>
+ * @license MIT
+ */
+
+/// <reference types="tree-sitter-cli/dsl" />
+// @ts-check
+
+const PREC = {
+ PAREN_DECLARATOR: -10,
+ CONDITIONAL: -1,
+ DEFAULT: 0,
+ LOGICAL_OR: 1,
+ LOGICAL_AND: 2,
+ EQUAL: 3,
+ BITWISE: 4,
+ SHIFT: 5,
+ ADD: 6,
+ MULTIPLY: 7,
+ UNARY: 8,
+ STRUCT: 9,
+ MEMBER: 10,
+};
+
+const builtinTypes = [
+ 'bool',
+ 'f16',
+ 'f32',
+ 'f64',
+ 'f128',
+ 'void',
+ 'type',
+ 'anyerror',
+ 'anyopaque',
+ 'anytype',
+ 'noreturn',
+ 'isize',
+ 'usize',
+ 'comptime_int',
+ 'comptime_float',
+ 'c_short',
+ 'c_ushort',
+ 'c_int',
+ 'c_uint',
+ 'c_long',
+ 'c_ulong',
+ 'c_longlong',
+ 'c_ulonglong',
+ 'c_longdouble',
+ /(i|u)[1-9][0-9]*/,
+];
+
+module.exports = grammar({
+ name: 'zig',
+
+ conflicts: $ => [
+ [$.for_expression],
+ [$.while_expression],
+
+ [$.expression, $._function_prototype],
+ [$.expression, $.if_type_expression],
+
+ [$.comptime_type_expression, $.expression],
+ [$.comptime_type_expression, $.parameter],
+ ],
+
+ extras: $ => [
+ $.comment,
+ /\s/,
+ ],
+
+ inline: $ => [
+ $._reserved_identifier,
+ ],
+
+ precedences: $ => [
+ [$.container_field, $.type_expression],
+ ],
+
+ supertypes: $ => [
+ $.statement,
+ $.expression,
+ $.type_expression,
+ $.primary_type_expression,
+ ],
+
+ word: $ => $._identifier,
+
+ rules: {
+ source_file: $ => optional($._container_members),
+
+ _container_members: $ => choice(
+ seq(
+ repeat1(choice(
+ $.test_declaration,
+ $.comptime_declaration,
+ $.variable_declaration,
+ $.function_declaration,
+ $.using_namespace_declaration,
+ seq($.container_field, ','),
+ )),
+ optional($.container_field),
+ ),
+ $.container_field,
+ ),
+
+ test_declaration: $ => seq(
+ optional('pub'),
+ 'test',
+ optional(choice($.string, $.identifier)),
+ $.block,
+ ),
+
+ comptime_declaration: $ => prec(1, seq(
+ optional('pub'),
+ 'comptime',
+ $.block,
+ )),
+
+ container_field: $ => prec.right(prec.dynamic(1, seq(
+ optional('comptime'),
+ choice(
+ seq(
+ field('name', choice($.identifier, $._reserved_identifier, alias($.builtin_type, $.identifier))),
+ ':',
+ field('type', choice($.primary_type_expression, $.if_type_expression, $.comptime_type_expression)),
+ ),
+ field('name', choice($.primary_type_expression, $.if_type_expression, $.comptime_type_expression)),
+ ),
+ optional($.byte_alignment),
+ optional(seq('=', $.expression)),
+ ))),
+
+ variable_declaration: $ => seq(
+ optional('pub'),
+ optional(choice(
+ 'export',
+ seq('extern', optional($.string)),
+ )),
+ optional('threadlocal'),
+ $._variable_declaration_header,
+ optional(seq('=', $.expression)),
+ ';',
+ ),
+
+ _variable_declaration_expression_statement: $ => choice(
+ seq(
+ $._variable_declaration_header,
+ repeat(prec(1, seq(',', choice($._variable_declaration_header, $.expression)))),
+ '=',
+ $.expression,
+ ';',
+ ),
+ seq(
+ $.expression,
+ choice(
+ seq(
+ choice(
+ '=', '*=', '*%=', '*|=', '/=', '%=',
+ '+=', '+%=', '+|=', '-=', '-%=', '-|=',
+ '<<=', '<<|=', '>>=', '&=', '^=', '|=',
+ ),
+ $.expression,
+ ),
+ seq(
+ repeat1(prec(1, seq(',', choice($._variable_declaration_header, $.expression)))),
+ '=',
+ $.expression,
+ ),
+ ),
+ ';',
+ ),
+ ),
+
+ _variable_declaration_header: $ => prec(1, seq(
+ choice('const', 'var'),
+ $.identifier,
+ optional(seq(
+ ':',
+ field('type', choice($.type_expression, $.if_type_expression, $.comptime_type_expression)),
+ )),
+ optional($.byte_alignment),
+ optional($.address_space),
+ optional($.link_section),
+ )),
+
+ function_declaration: $ => seq(
+ optional('pub'),
+ optional(choice(
+ 'export',
+ seq('extern', optional($.string)),
+ 'inline',
+ 'noinline',
+ )),
+ $._function_prototype,
+ choice(
+ ';',
+ field('body', $.block),
+ ),
+ ),
+
+ _function_prototype: $ => seq(
+ 'fn',
+ optional(field('name', $.identifier)),
+ $.parameters,
+ optional($.byte_alignment),
+ optional($.address_space),
+ optional($.link_section),
+ optional($.calling_convention),
+ field('type', choice($.type_expression, $.if_type_expression, $.comptime_type_expression)),
+ ),
+
+ parameters: $ => seq('(', optionalCommaSep($.parameter), ')'),
+
+ parameter: $ => choice(
+ seq(
+ optional(choice('noalias', 'comptime')),
+ optional(seq(
+ field('name', choice($.identifier, alias($.builtin_type, $.identifier))),
+ ':',
+ )),
+ field('type', choice($.type_expression, $.if_type_expression, $.comptime_type_expression)),
+ ),
+ '...',
+ ),
+
+ using_namespace_declaration: $ => seq(
+ optional('pub'),
+ 'usingnamespace',
+ $.expression,
+ ';',
+ ),
+
+ block: $ => seq(
+ '{',
+ repeat($.statement),
+ '}',
+ ),
+
+ struct_declaration: $ => seq(
+ optional(choice('extern', 'packed')),
+ 'struct',
+ optional(seq('(', $.expression, ')')),
+ '{',
+ $._container_members,
+ '}',
+ ),
+
+ opaque_declaration: $ => seq(
+ optional(choice('extern', 'packed')),
+ 'opaque',
+ '{',
+ $._container_members,
+ '}',
+ ),
+
+ enum_declaration: $ => seq(
+ optional(choice('extern', 'packed')),
+ 'enum',
+ optional(seq('(', $.expression, ')')),
+ '{',
+ $._container_members,
+ '}',
+ ),
+
+ union_declaration: $ => seq(
+ optional(choice('extern', 'packed')),
+ 'union',
+ optional(seq(
+ '(',
+ choice(
+ seq('enum', optional(seq('(', $.expression, ')'))),
+ $.expression,
+ ),
+ ')',
+ )),
+ '{',
+ $._container_members,
+ '}',
+ ),
+
+ error_set_declaration: $ => seq(
+ 'error',
+ '{',
+ optionalCommaSep($.identifier),
+ '}',
+ ),
+
+ statement: $ => choice(
+ $.comptime_statement,
+ $.nosuspend_statement,
+ $.suspend_statement,
+ $.defer_statement,
+ $.errdefer_statement,
+ $.expression_statement,
+ alias($._variable_declaration_expression_statement, $.variable_declaration),
+ $.if_statement,
+ $.for_statement,
+ $.while_statement,
+ $.labeled_statement,
+ prec(1, $.switch_expression),
+ ),
+
+ comptime_statement: $ => seq(
+ 'comptime',
+ choice(
+ $._block_expr_statement,
+ alias($._variable_declaration_expression_statement, $.variable_declaration),
+ ),
+ ),
+
+ nosuspend_statement: $ => seq('nosuspend', $._block_expr_statement),
+
+ suspend_statement: $ => seq('suspend', $._block_expr_statement),
+
+ defer_statement: $ => seq('defer', $._block_expr_statement),
+
+ errdefer_statement: $ => seq('errdefer', optional($.payload), $._block_expr_statement),
+
+ _block_expr_statement: $ => prec(1, choice(
+ seq(optional($.block_label), $.block),
+ $.expression_statement,
+ )),
+
+ block_expression: $ => prec(1, seq(optional($.block_label), $.block)),
+
+ labeled_statement: $ => prec(1, seq(
+ optional($.block_label),
+ choice($.block, $.for_statement, $.while_statement),
+ )),
+
+ expression_statement: $ => seq($.expression, ';'),
+
+ if_statement: $ => seq(
+ $._if_prefix,
+ $._conditional_body,
+ ),
+
+ _if_prefix: $ => seq(
+ 'if',
+ '(',
+ field('condition', $.expression),
+ ')',
+ optional($.payload),
+ ),
+
+ else_clause: $ => seq(
+ 'else',
+ optional($.payload),
+ field('alternative', $.statement),
+ ),
+
+ for_statement: $ => seq(
+ optional('inline'),
+ $._for_prefix,
+ $._conditional_body,
+ ),
+
+ _for_prefix: $ => seq(
+ 'for',
+ '(',
+ optionalCommaSep(seq(
+ $.expression,
+ optional(seq('..', $.expression)),
+ )),
+ ')',
+ $.payload,
+ ),
+
+ while_statement: $ => seq(
+ optional('inline'),
+ $._while_prefix,
+ $._conditional_body,
+ ),
+
+ _while_prefix: $ => seq(
+ 'while',
+ '(',
+ field('condition', $.expression),
+ ')',
+ optional($.payload),
+ optional(seq(':', '(', $.expression, ')')),
+ ),
+
+ _conditional_body: $ => choice(
+ seq(
+ field('body', $.block_expression),
+ optional($.else_clause),
+ ),
+ seq(
+ field('body', $.expression),
+ choice(';', $.else_clause),
+ ),
+ ),
+
+ payload: $ => seq('|', optionalCommaSep1(seq(optional('*'), $.identifier)), '|'),
+
+ byte_alignment: $ => seq('align', '(', $.expression, ')'),
+
+ address_space: $ => seq('addrspace', '(', $.expression, ')'),
+
+ link_section: $ => seq('linksection', '(', $.expression, ')'),
+
+ calling_convention: $ => seq('callconv', '(', $.expression, ')'),
+
+ expression: $ => prec.right(choice(
+ $.asm_expression,
+ $.if_expression,
+ $.for_expression,
+ $.while_expression,
+ $.assignment_expression,
+ $.unary_expression,
+ $.binary_expression,
+ $.comptime_expression,
+ $.async_expression,
+ $.await_expression,
+ $.nosuspend_expression,
+ $.continue_expression,
+ $.resume_expression,
+ $.return_expression,
+ $.break_expression,
+ $.try_expression,
+ $.catch_expression,
+ $.type_expression,
+ $.block,
+ )),
+
+ asm_expression: $ => seq(
+ 'asm',
+ optional('volatile'),
+ '(',
+ $.expression,
+ optional($.asm_output),
+ ')',
+ ),
+ asm_output: $ => seq(':', optionalCommaSep($.asm_output_item), optional($.asm_input)),
+ asm_output_item: $ => seq(
+ '[',
+ $.identifier,
+ ']',
+ choice($.string, $.multiline_string),
+ '(',
+ choice(seq('->', $.type_expression), $.identifier),
+ ')',
+ ),
+ asm_input: $ => seq(':', optionalCommaSep($.asm_input_item), optional($.asm_clobbers)),
+ asm_input_item: $ => seq(
+ '[',
+ $.identifier,
+ ']',
+ choice($.string, $.multiline_string),
+ '(',
+ $.expression,
+ ')',
+ ),
+ asm_clobbers: $ => seq(':', optionalCommaSep(choice($.string, $.multiline_string))),
+
+ if_expression: $ => prec.right(seq(
+ $._if_prefix,
+ $.expression,
+ optional(seq('else', optional($.payload), $.expression)),
+ )),
+
+ for_expression: $ => prec.right(seq(
+ optional($.block_label),
+ optional('inline'),
+ $._for_prefix,
+ $.expression,
+ optional(seq('else', $.expression)),
+ )),
+
+ while_expression: $ => prec.right(seq(
+ optional($.block_label),
+ optional('inline'),
+ $._while_prefix,
+ $.expression,
+ optional(seq('else', optional($.payload), $.expression)),
+ )),
+
+ assignment_expression: $ => prec.right(seq(
+ field('left', $.expression),
+ field('operator', choice(
+ '=', '*=', '*%=', '*|=', '/=', '%=',
+ '+=', '+%=', '+|=', '-=', '-%=', '-|=',
+ '<<=', '<<|=', '>>=', '&=', '^=', '|=',
+ )),
+ field('right', $.expression),
+ )),
+
+ unary_expression: $ => prec.left(PREC.UNARY, seq(
+ field('operator', choice('!', '~', '-', '-%', '&')),
+ field('argument', $.expression),
+ )),
+
+ binary_expression: $ => {
+ const table = [
+ ['or', PREC.LOGICAL_OR],
+ ['and', PREC.LOGICAL_AND],
+ ['==', PREC.EQUAL],
+ ['!=', PREC.EQUAL],
+ ['>', PREC.EQUAL],
+ ['>=', PREC.EQUAL],
+ ['<=', PREC.EQUAL],
+ ['<', PREC.EQUAL],
+ ['&', PREC.BITWISE],
+ ['^', PREC.BITWISE],
+ ['|', PREC.BITWISE],
+ ['orelse', PREC.BITWISE],
+ ['<<', PREC.SHIFT],
+ ['>>', PREC.SHIFT],
+ ['<<|', PREC.SHIFT],
+ ['+', PREC.ADD],
+ ['-', PREC.ADD],
+ ['++', PREC.ADD],
+ ['+%', PREC.ADD],
+ ['-%', PREC.ADD],
+ ['+|', PREC.ADD],
+ ['-|', PREC.ADD],
+ ['*', PREC.MULTIPLY],
+ ['/', PREC.MULTIPLY],
+ ['%', PREC.MULTIPLY],
+ ['**', PREC.MULTIPLY],
+ ['*%', PREC.MULTIPLY],
+ ['*|', PREC.MULTIPLY],
+ ['||', PREC.MULTIPLY],
+ ];
+
+ return choice(...table.map(([operator, precedence]) => {
+ return prec.left(precedence, seq(
+ field('left', $.expression),
+ // @ts-ignore
+ field('operator', operator),
+ field('right', $.expression),
+ ));
+ }));
+ },
+
+ comptime_expression: $ => prec.right(seq('comptime', $.expression)),
+
+ async_expression: $ => prec.right(seq('async', $.expression)),
+
+ await_expression: $ => prec.right(seq('await', $.expression)),
+
+ nosuspend_expression: $ => prec.right(seq('nosuspend', $.expression)),
+
+ continue_expression: $ => prec.right(seq(
+ 'continue',
+ optional($.break_label),
+ optional($.expression),
+ )),
+
+ resume_expression: $ => prec.right(seq('resume', $.expression)),
+
+ return_expression: $ => prec.right(seq('return', optional($.expression))),
+
+ break_expression: $ => prec.right(seq(
+ 'break',
+ optional($.break_label),
+ optional($.expression),
+ )),
+
+ try_expression: $ => prec.right(PREC.BITWISE, seq('try', $.expression)),
+
+ catch_expression: $ => prec.right(PREC.BITWISE, seq(
+ $.expression,
+ 'catch',
+ optional($.payload),
+ $.expression,
+ )),
+
+ switch_expression: $ => seq(
+ optional($.block_label),
+ 'switch',
+ '(', $.expression, ')',
+ '{',
+ optionalCommaSep($.switch_case),
+ '}',
+ ),
+ switch_case: $ => seq(
+ $._switch_case_exp,
+ '=>',
+ optional($.payload),
+ choice($.expression),
+ ),
+ _switch_case_exp: $ => seq(
+ optional('inline'),
+ choice(
+ optionalCommaSep1(seq($.expression, optional(seq('...', $.expression)))),
+ 'else',
+ ),
+ ),
+
+ type_expression: $ => prec.right(choice(
+ $.anonymous_struct_initializer,
+ $.struct_initializer,
+ $.labeled_type_expression,
+ $.error_set_declaration,
+ $.parenthesized_expression,
+ $.primary_type_expression,
+ )),
+
+ primary_type_expression: $ => choice(
+ $.nullable_type,
+ $.anyframe_type,
+ $.slice_type,
+ $.pointer_type,
+ $.array_type,
+ $.error_union_type,
+ $.builtin_function,
+ $.character,
+ $.field_expression,
+ $.index_expression,
+ $.dereference_expression,
+ $.null_coercion_expression,
+ $.range_expression,
+ $.call_expression,
+ prec.right(alias($._function_prototype, $.function_signature)),
+ $.identifier,
+ $.float,
+ $.integer,
+ $.boolean,
+ $.error_type,
+ 'anyframe',
+ 'unreachable',
+ 'undefined',
+ 'null',
+ $.string,
+ $.multiline_string,
+ $.builtin_type,
+ $.struct_declaration,
+ $.opaque_declaration,
+ $.enum_declaration,
+ $.union_declaration,
+ $.switch_expression,
+ ),
+
+ nullable_type: $ => prec(1, seq(
+ '?',
+ choice($.type_expression, $.if_type_expression, $.comptime_type_expression),
+ )),
+
+ anyframe_type: $ => prec(1, seq(
+ 'anyframe',
+ '->',
+ $.type_expression,
+ )),
+
+ slice_type: $ => prec.right(1, seq(
+ '[',
+ optional(seq(
+ ':',
+ field('sentinel', $.expression),
+ )),
+ ']',
+ repeat(choice(
+ $.byte_alignment,
+ $.address_space,
+ 'const',
+ 'volatile',
+ 'allowzero',
+ )),
+ $.type_expression,
+ )),
+
+ pointer_type: $ => prec.right(1, seq(
+ choice(
+ '*',
+ seq(
+ '[',
+ '*',
+ optional(choice('c', seq(':', $.expression))),
+ ']',
+ ),
+ ),
+ repeat(choice(
+ $.address_space,
+ seq(
+ 'align',
+ '(',
+ $.expression,
+ optional(seq(':', $.expression, ':', $.expression)),
+ ')',
+ ),
+ 'const',
+ 'volatile',
+ 'allowzero',
+ )),
+ $.type_expression,
+ )),
+
+ array_type: $ => prec(1, seq(
+ '[',
+ $.expression,
+ optional(seq(':', $.expression)),
+ ']',
+ $.type_expression,
+ )),
+
+ error_union_type: $ => prec.right(2, seq(
+ optional(field('error', $.type_expression)),
+ '!',
+ field('ok', $.type_expression),
+ )),
+
+ field_expression: $ => prec(PREC.MEMBER, seq(
+ optional(field('object', $.expression)),
+ '.',
+ field('member', $.identifier),
+ )),
+
+ index_expression: $ => prec(PREC.MEMBER, seq(
+ field('object', $.expression),
+ '[',
+ field('index', $.expression),
+ optional(seq(':', field('sentinel', $.expression))),
+ ']',
+ )),
+
+ dereference_expression: $ => prec(PREC.MEMBER, seq($.expression, '.*')),
+
+ null_coercion_expression: $ => prec(PREC.MEMBER, seq($.expression, '.?')),
+
+ range_expression: $ => prec.right(PREC.MEMBER, seq(
+ field('left', $.expression),
+ '..',
+ optional(field('right', $.expression)),
+ )),
+
+ call_expression: $ => prec(PREC.MEMBER, seq(
+ field('function', $.expression),
+ field('arguments', $.arguments),
+ )),
+
+ anonymous_struct_initializer: $ => seq('.', $.initializer_list),
+
+ struct_initializer: $ => prec(-1, seq($.primary_type_expression, $.initializer_list)),
+
+ initializer_list: $ => seq(
+ '{',
+ choice(
+ optionalCommaSep($.field_initializer),
+ optionalCommaSep($.expression),
+ ),
+ '}',
+ ),
+
+ field_initializer: $ => seq(
+ '.',
+ $.identifier,
+ '=',
+ $.expression,
+ ),
+
+ labeled_type_expression: $ => seq($.block_label, $.block),
+
+ comptime_type_expression: $ => seq('comptime', $.type_expression),
+
+ if_type_expression: $ => prec.right(seq(
+ $._if_prefix,
+ $.type_expression,
+ optional(seq('else', optional($.payload), $.type_expression)),
+ )),
+
+ parenthesized_expression: $ => seq('(', $.expression, ')'),
+
+ block_label: $ => prec(-1, seq(
+ choice($.identifier, alias($.builtin_type, $.identifier)),
+ ':',
+ )),
+ break_label: $ => seq(':', $.identifier),
+
+ arguments: $ => seq('(', optionalCommaSep($.expression), ')'),
+
+ builtin_function: $ => seq(
+ $.builtin_identifier,
+ $.arguments,
+ ),
+
+ string: $ => seq(
+ '"',
+ repeat(choice(
+ alias(token.immediate(prec(1, /[^\\"\n]+/)), $.string_content),
+ $.escape_sequence,
+ )),
+ '"',
+ ),
+
+ multiline_string: _ => prec.right(repeat1(token(seq('\\\\', /[^\n]*/)))),
+
+ escape_sequence: _ => token(prec(1, seq(
+ '\\',
+ choice(
+ /[^xuU]/,
+ /\d{2,3}/,
+ /x[0-9a-fA-F]{2,}/,
+ /u\{[0-9a-fA-F]{1,6}\}/,
+ ),
+ ))),
+
+ character: $ => seq(
+ '\'',
+ choice(
+ alias(/[^'\n]/, $.character_content),
+ $.escape_sequence,
+ ),
+ '\'',
+ ),
+
+ integer: _ => {
+ const separator = '_';
+ const hex = /[0-9A-Fa-f]/;
+ const oct = /[0-7]/;
+ const bin = /[0-1]/;
+ const decimal = /[0-9]/;
+ const hexDigits = seq(repeat1(hex), repeat(seq(separator, repeat1(hex))));
+ const octDigits = seq(repeat1(oct), repeat(seq(separator, repeat1(oct))));
+ const binDigits = seq(repeat1(bin), repeat(seq(separator, repeat1(bin))));
+ const decimalDigits = seq(repeat1(decimal), repeat(seq(separator, repeat1(decimal))));
+
+ return token(choice(
+ seq('0x', hexDigits),
+ seq('0o', octDigits),
+ seq('0b', binDigits),
+ decimalDigits,
+ ));
+ },
+
+ float: _ => {
+ const separator = '_';
+ const hex = /[0-9A-Fa-f]/;
+ const decimal = /[0-9]/;
+ const hexDigits = seq(repeat1(hex), repeat(seq(separator, repeat1(hex))));
+ const decimalDigits = seq(repeat1(decimal), repeat(seq(separator, repeat1(decimal))));
+
+ return token(choice(
+ seq('0x', hexDigits, '.', hexDigits, optional(seq(/[pP][+-]?/, decimalDigits))),
+ seq(decimalDigits, '.', decimalDigits, optional(seq(/[eE][+-]?/, decimalDigits))),
+ seq('0x', hexDigits, /[pP][+-]?/, decimalDigits),
+ seq(decimalDigits, /[eE][+-]?/, decimalDigits),
+ ));
+ },
+
+ boolean: _ => choice('true', 'false'),
+
+ builtin_type: _ => choice(...builtinTypes),
+
+ error_type: $ => seq('error', '.', $.identifier),
+
+ builtin_identifier: _ => /@[A-Za-z_][A-Za-z0-9_]*/,
+
+ identifier: $ => choice($._identifier, seq('@', $.string)),
+ _identifier: _ => /[A-Za-z_][A-Za-z0-9_]*/,
+ _reserved_identifier: _ => choice(
+ 'undefined',
+ 'null',
+ 'true',
+ 'false',
+ ),
+
+ comment: _ => token(seq('//', /.*/)),
+ },
+});
+
+/**
+ * Creates a rule to match optionally match one or more of the rules
+ * separated by a comma and optionally ending with a comma
+ *
+ * @param {RuleOrLiteral} rule
+ *
+ * @returns {ChoiceRule}
+ */
+function optionalCommaSep(rule) {
+ return optional(optionalCommaSep1(rule));
+}
+
+/**
+ * Creates a rule to match one or more of the rules separated by a comma
+ * and optionally ending with a comma
+ *
+ * @param {RuleOrLiteral} rule
+ *
+ * @returns {SeqRule}
+ */
+function optionalCommaSep1(rule) {
+ return seq(commaSep1(rule), optional(','));
+}
+
+/**
+ * Creates a rule to match one or more of the rules separated by a comma
+ *
+ * @param {RuleOrLiteral} rule
+ *
+ * @returns {SeqRule}
+ */
+function commaSep1(rule) {
+ return seq(rule, repeat(seq(',', rule)));
+}