@willbooster/tree-sitter-c 0.0.0-placeholder.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/grammar.js ADDED
@@ -0,0 +1,1276 @@
1
+ /**
2
+ * @file C grammar for tree-sitter
3
+ * @author Max Brunsfeld <maxbrunsfeld@gmail.com>
4
+ * @author Amaan Qureshi <amaanq12@gmail.com>
5
+ * @license MIT
6
+ */
7
+
8
+ /// <reference types="tree-sitter-cli/dsl" />
9
+ // @ts-check
10
+
11
+ const PREC = {
12
+ PAREN_DECLARATOR: -10,
13
+ ASSIGNMENT: -2,
14
+ CONDITIONAL: -1,
15
+ DEFAULT: 0,
16
+ LOGICAL_OR: 1,
17
+ LOGICAL_AND: 2,
18
+ INCLUSIVE_OR: 3,
19
+ EXCLUSIVE_OR: 4,
20
+ BITWISE_AND: 5,
21
+ EQUAL: 6,
22
+ RELATIONAL: 7,
23
+ OFFSETOF: 8,
24
+ SHIFT: 9,
25
+ ADD: 10,
26
+ MULTIPLY: 11,
27
+ CAST: 12,
28
+ SIZEOF: 13,
29
+ UNARY: 14,
30
+ CALL: 15,
31
+ FIELD: 16,
32
+ SUBSCRIPT: 17,
33
+ };
34
+
35
+ // oxlint-disable-next-line unicorn/prefer-module -- This package is CommonJS, so tree-sitter loads grammar.js as CommonJS.
36
+ module.exports = Object.assign(
37
+ grammar({
38
+ name: 'c',
39
+
40
+ conflicts: ($) => [
41
+ [$.type_specifier, $._declarator],
42
+ [$.type_specifier, $._declarator, $.macro_type_specifier],
43
+ [$.type_specifier, $.expression],
44
+ [$.type_specifier, $.expression, $.macro_type_specifier],
45
+ [$.type_specifier, $.macro_type_specifier],
46
+ [$.type_specifier, $.sized_type_specifier],
47
+ [$.sized_type_specifier],
48
+ [$.attributed_statement],
49
+ [$._declaration_modifiers, $.attributed_statement],
50
+ [$.enum_specifier],
51
+ [$.type_specifier, $._old_style_parameter_list],
52
+ [$.parameter_list, $._old_style_parameter_list],
53
+ [$.function_declarator, $._function_declaration_declarator],
54
+ [$._block_item, $.statement],
55
+ [$._top_level_item, $._top_level_statement],
56
+ [$.type_specifier, $._top_level_expression_statement],
57
+ [$.type_qualifier, $.extension_expression],
58
+ ],
59
+
60
+ extras: ($) => [/\s|\\\r?\n/, $.comment],
61
+
62
+ inline: ($) => [
63
+ $._type_identifier,
64
+ $._field_identifier,
65
+ $._statement_identifier,
66
+ $._non_case_statement,
67
+ $._assignment_left_expression,
68
+ $._expression_not_binary,
69
+ ],
70
+
71
+ supertypes: ($) => [
72
+ $.expression,
73
+ $.statement,
74
+ $.type_specifier,
75
+ $._declarator,
76
+ $._field_declarator,
77
+ $._type_declarator,
78
+ $._abstract_declarator,
79
+ ],
80
+
81
+ word: ($) => $.identifier,
82
+
83
+ rules: {
84
+ translation_unit: ($) => repeat($._top_level_item),
85
+
86
+ // Top level items are block items with the exception of the expression statement
87
+ _top_level_item: ($) =>
88
+ choice(
89
+ $.function_definition,
90
+ alias($._old_style_function_definition, $.function_definition),
91
+ $.linkage_specification,
92
+ $.declaration,
93
+ $._top_level_statement,
94
+ $.attributed_statement,
95
+ $.type_definition,
96
+ $._empty_declaration,
97
+ $.preproc_if,
98
+ $.preproc_ifdef,
99
+ $.preproc_include,
100
+ $.preproc_def,
101
+ $.preproc_function_def,
102
+ $.preproc_call
103
+ ),
104
+
105
+ _block_item: ($) =>
106
+ choice(
107
+ $.function_definition,
108
+ alias($._old_style_function_definition, $.function_definition),
109
+ $.linkage_specification,
110
+ $.declaration,
111
+ $.statement,
112
+ $.attributed_statement,
113
+ $.type_definition,
114
+ $._empty_declaration,
115
+ $.preproc_if,
116
+ $.preproc_ifdef,
117
+ $.preproc_include,
118
+ $.preproc_def,
119
+ $.preproc_function_def,
120
+ $.preproc_call
121
+ ),
122
+
123
+ // Preprocesser
124
+
125
+ preproc_include: ($) =>
126
+ seq(
127
+ preprocessor('include'),
128
+ field(
129
+ 'path',
130
+ choice(
131
+ $.string_literal,
132
+ $.system_lib_string,
133
+ $.identifier,
134
+ alias($.preproc_call_expression, $.call_expression)
135
+ )
136
+ ),
137
+ token.immediate(/\r?\n/)
138
+ ),
139
+
140
+ preproc_def: ($) =>
141
+ seq(
142
+ preprocessor('define'),
143
+ field('name', $.identifier),
144
+ field('value', optional($.preproc_arg)),
145
+ token.immediate(/\r?\n/)
146
+ ),
147
+
148
+ preproc_function_def: ($) =>
149
+ seq(
150
+ preprocessor('define'),
151
+ field('name', $.identifier),
152
+ field('parameters', $.preproc_params),
153
+ field('value', optional($.preproc_arg)),
154
+ token.immediate(/\r?\n/)
155
+ ),
156
+
157
+ preproc_params: ($) => seq(token.immediate('('), commaSep(choice($.identifier, '...')), ')'),
158
+
159
+ preproc_call: ($) =>
160
+ seq(
161
+ field('directive', $.preproc_directive),
162
+ field('argument', optional($.preproc_arg)),
163
+ token.immediate(/\r?\n/)
164
+ ),
165
+
166
+ ...preprocIf('', ($) => $._block_item),
167
+ ...preprocIf('_in_field_declaration_list', ($) => $._field_declaration_list_item),
168
+ ...preprocIf('_in_enumerator_list', ($) => seq($.enumerator, ',')),
169
+ ...preprocIf('_in_enumerator_list_no_comma', ($) => $.enumerator, -1),
170
+
171
+ preproc_arg: () => token(prec(-1, /\S([^/\n]|\/[^*]|\\\r?\n)*/)),
172
+ preproc_directive: () => /#[ \t]*[a-zA-Z0-9]\w*/,
173
+
174
+ _preproc_expression: ($) =>
175
+ choice(
176
+ $.identifier,
177
+ alias($.preproc_call_expression, $.call_expression),
178
+ $.number_literal,
179
+ $.char_literal,
180
+ $.preproc_defined,
181
+ alias($.preproc_unary_expression, $.unary_expression),
182
+ alias($.preproc_binary_expression, $.binary_expression),
183
+ alias($.preproc_parenthesized_expression, $.parenthesized_expression)
184
+ ),
185
+
186
+ preproc_parenthesized_expression: ($) => seq('(', $._preproc_expression, ')'),
187
+
188
+ preproc_defined: ($) =>
189
+ choice(prec(PREC.CALL, seq('defined', '(', $.identifier, ')')), seq('defined', $.identifier)),
190
+
191
+ preproc_unary_expression: ($) =>
192
+ prec.left(
193
+ PREC.UNARY,
194
+ seq(field('operator', choice('!', '~', '-', '+')), field('argument', $._preproc_expression))
195
+ ),
196
+
197
+ preproc_call_expression: ($) =>
198
+ prec(
199
+ PREC.CALL,
200
+ seq(field('function', $.identifier), field('arguments', alias($.preproc_argument_list, $.argument_list)))
201
+ ),
202
+
203
+ preproc_argument_list: ($) => seq('(', commaSep($._preproc_expression), ')'),
204
+
205
+ preproc_binary_expression: ($) => {
206
+ const table = [
207
+ ['+', PREC.ADD],
208
+ ['-', PREC.ADD],
209
+ ['*', PREC.MULTIPLY],
210
+ ['/', PREC.MULTIPLY],
211
+ ['%', PREC.MULTIPLY],
212
+ ['||', PREC.LOGICAL_OR],
213
+ ['&&', PREC.LOGICAL_AND],
214
+ ['|', PREC.INCLUSIVE_OR],
215
+ ['^', PREC.EXCLUSIVE_OR],
216
+ ['&', PREC.BITWISE_AND],
217
+ ['==', PREC.EQUAL],
218
+ ['!=', PREC.EQUAL],
219
+ ['>', PREC.RELATIONAL],
220
+ ['>=', PREC.RELATIONAL],
221
+ ['<=', PREC.RELATIONAL],
222
+ ['<', PREC.RELATIONAL],
223
+ ['<<', PREC.SHIFT],
224
+ ['>>', PREC.SHIFT],
225
+ ];
226
+
227
+ return choice(
228
+ ...table.map(([operator, precedence]) => {
229
+ return prec.left(
230
+ precedence,
231
+ seq(
232
+ field('left', $._preproc_expression),
233
+ // @ts-ignore
234
+ field('operator', operator),
235
+ field('right', $._preproc_expression)
236
+ )
237
+ );
238
+ })
239
+ );
240
+ },
241
+
242
+ // Main Grammar
243
+
244
+ function_definition: ($) =>
245
+ seq(
246
+ optional($.ms_call_modifier),
247
+ $._declaration_specifiers,
248
+ optional($.ms_call_modifier),
249
+ field('declarator', $._declarator),
250
+ field('body', $.compound_statement)
251
+ ),
252
+
253
+ _old_style_function_definition: ($) =>
254
+ seq(
255
+ optional($.ms_call_modifier),
256
+ $._declaration_specifiers,
257
+ field('declarator', alias($._old_style_function_declarator, $.function_declarator)),
258
+ repeat1($.declaration),
259
+ field('body', $.compound_statement)
260
+ ),
261
+
262
+ declaration: ($) =>
263
+ seq(
264
+ $._declaration_specifiers,
265
+ commaSep1(
266
+ field(
267
+ 'declarator',
268
+ choice(
269
+ seq(optional($.ms_call_modifier), $._declaration_declarator, optional($.gnu_asm_expression)),
270
+ $.init_declarator
271
+ )
272
+ )
273
+ ),
274
+ ';'
275
+ ),
276
+
277
+ type_definition: ($) =>
278
+ seq(
279
+ optional('__extension__'),
280
+ 'typedef',
281
+ $._type_definition_type,
282
+ $._type_definition_declarators,
283
+ repeat($.attribute_specifier),
284
+ ';'
285
+ ),
286
+ _type_definition_type: ($) =>
287
+ seq(repeat($.type_qualifier), field('type', $.type_specifier), repeat($.type_qualifier)),
288
+ _type_definition_declarators: ($) => commaSep1(field('declarator', $._type_declarator)),
289
+
290
+ _declaration_modifiers: ($) =>
291
+ choice(
292
+ $.storage_class_specifier,
293
+ $.type_qualifier,
294
+ $.attribute_specifier,
295
+ $.attribute_declaration,
296
+ $.ms_declspec_modifier
297
+ ),
298
+
299
+ _declaration_specifiers: ($) =>
300
+ prec.right(
301
+ seq(repeat($._declaration_modifiers), field('type', $.type_specifier), repeat($._declaration_modifiers))
302
+ ),
303
+
304
+ linkage_specification: ($) =>
305
+ seq(
306
+ 'extern',
307
+ field('value', $.string_literal),
308
+ field('body', choice($.function_definition, $.declaration, $.declaration_list))
309
+ ),
310
+
311
+ attribute_specifier: ($) => seq(choice('__attribute__', '__attribute'), '(', $.argument_list, ')'),
312
+
313
+ attribute: ($) =>
314
+ seq(optional(seq(field('prefix', $.identifier), '::')), field('name', $.identifier), optional($.argument_list)),
315
+
316
+ attribute_declaration: ($) => seq('[[', commaSep1($.attribute), ']]'),
317
+
318
+ ms_declspec_modifier: ($) => seq('__declspec', '(', $.identifier, ')'),
319
+
320
+ ms_based_modifier: ($) => seq('__based', $.argument_list),
321
+
322
+ ms_call_modifier: () => choice('__cdecl', '__clrcall', '__stdcall', '__fastcall', '__thiscall', '__vectorcall'),
323
+
324
+ ms_restrict_modifier: () => '__restrict',
325
+
326
+ ms_unsigned_ptr_modifier: () => '__uptr',
327
+
328
+ ms_signed_ptr_modifier: () => '__sptr',
329
+
330
+ ms_unaligned_ptr_modifier: () => choice('_unaligned', '__unaligned'),
331
+
332
+ ms_pointer_modifier: ($) =>
333
+ choice(
334
+ $.ms_unaligned_ptr_modifier,
335
+ $.ms_restrict_modifier,
336
+ $.ms_unsigned_ptr_modifier,
337
+ $.ms_signed_ptr_modifier
338
+ ),
339
+
340
+ declaration_list: ($) => seq('{', repeat($._block_item), '}'),
341
+
342
+ _declarator: ($) =>
343
+ choice(
344
+ $.attributed_declarator,
345
+ $.pointer_declarator,
346
+ $.function_declarator,
347
+ $.array_declarator,
348
+ $.parenthesized_declarator,
349
+ $.identifier
350
+ ),
351
+
352
+ _declaration_declarator: ($) =>
353
+ choice(
354
+ $.attributed_declarator,
355
+ $.pointer_declarator,
356
+ alias($._function_declaration_declarator, $.function_declarator),
357
+ $.array_declarator,
358
+ $.parenthesized_declarator,
359
+ $.identifier
360
+ ),
361
+
362
+ _field_declarator: ($) =>
363
+ choice(
364
+ alias($.attributed_field_declarator, $.attributed_declarator),
365
+ alias($.pointer_field_declarator, $.pointer_declarator),
366
+ alias($.function_field_declarator, $.function_declarator),
367
+ alias($.array_field_declarator, $.array_declarator),
368
+ alias($.parenthesized_field_declarator, $.parenthesized_declarator),
369
+ $._field_identifier
370
+ ),
371
+
372
+ _type_declarator: ($) =>
373
+ choice(
374
+ alias($.attributed_type_declarator, $.attributed_declarator),
375
+ alias($.pointer_type_declarator, $.pointer_declarator),
376
+ alias($.function_type_declarator, $.function_declarator),
377
+ alias($.array_type_declarator, $.array_declarator),
378
+ alias($.parenthesized_type_declarator, $.parenthesized_declarator),
379
+ $._type_identifier,
380
+ alias(choice('signed', 'unsigned', 'long', 'short'), $.primitive_type),
381
+ $.primitive_type
382
+ ),
383
+
384
+ _abstract_declarator: ($) =>
385
+ choice(
386
+ $.abstract_pointer_declarator,
387
+ $.abstract_function_declarator,
388
+ $.abstract_array_declarator,
389
+ $.abstract_parenthesized_declarator
390
+ ),
391
+
392
+ parenthesized_declarator: ($) =>
393
+ prec.dynamic(PREC.PAREN_DECLARATOR, seq('(', optional($.ms_call_modifier), $._declarator, ')')),
394
+ parenthesized_field_declarator: ($) =>
395
+ prec.dynamic(PREC.PAREN_DECLARATOR, seq('(', optional($.ms_call_modifier), $._field_declarator, ')')),
396
+ parenthesized_type_declarator: ($) =>
397
+ prec.dynamic(PREC.PAREN_DECLARATOR, seq('(', optional($.ms_call_modifier), $._type_declarator, ')')),
398
+ abstract_parenthesized_declarator: ($) =>
399
+ prec(1, seq('(', optional($.ms_call_modifier), $._abstract_declarator, ')')),
400
+
401
+ attributed_declarator: ($) => prec.right(seq($._declarator, repeat1($.attribute_declaration))),
402
+ attributed_field_declarator: ($) => prec.right(seq($._field_declarator, repeat1($.attribute_declaration))),
403
+ attributed_type_declarator: ($) => prec.right(seq($._type_declarator, repeat1($.attribute_declaration))),
404
+
405
+ pointer_declarator: ($) =>
406
+ prec.dynamic(
407
+ 1,
408
+ prec.right(
409
+ seq(
410
+ optional($.ms_based_modifier),
411
+ '*',
412
+ repeat($.ms_pointer_modifier),
413
+ repeat($.type_qualifier),
414
+ field('declarator', $._declarator)
415
+ )
416
+ )
417
+ ),
418
+ pointer_field_declarator: ($) =>
419
+ prec.dynamic(
420
+ 1,
421
+ prec.right(
422
+ seq(
423
+ optional($.ms_based_modifier),
424
+ '*',
425
+ repeat($.ms_pointer_modifier),
426
+ repeat($.type_qualifier),
427
+ field('declarator', $._field_declarator)
428
+ )
429
+ )
430
+ ),
431
+ pointer_type_declarator: ($) =>
432
+ prec.dynamic(
433
+ 1,
434
+ prec.right(
435
+ seq(
436
+ optional($.ms_based_modifier),
437
+ '*',
438
+ repeat($.ms_pointer_modifier),
439
+ repeat($.type_qualifier),
440
+ field('declarator', $._type_declarator)
441
+ )
442
+ )
443
+ ),
444
+ abstract_pointer_declarator: ($) =>
445
+ prec.dynamic(
446
+ 1,
447
+ prec.right(
448
+ seq(
449
+ '*',
450
+ repeat($.ms_pointer_modifier),
451
+ repeat($.type_qualifier),
452
+ field('declarator', optional($._abstract_declarator))
453
+ )
454
+ )
455
+ ),
456
+
457
+ function_declarator: ($) =>
458
+ prec.right(
459
+ 1,
460
+ seq(
461
+ field('declarator', $._declarator),
462
+ field('parameters', $.parameter_list),
463
+ optional($.gnu_asm_expression),
464
+ repeat(choice($.attribute_specifier, $.identifier, alias($.preproc_call_expression, $.call_expression)))
465
+ )
466
+ ),
467
+
468
+ _function_declaration_declarator: ($) =>
469
+ prec.right(
470
+ 1,
471
+ seq(
472
+ field('declarator', $._declarator),
473
+ field('parameters', $.parameter_list),
474
+ optional($.gnu_asm_expression),
475
+ repeat($.attribute_specifier)
476
+ )
477
+ ),
478
+
479
+ function_field_declarator: ($) =>
480
+ prec(1, seq(field('declarator', $._field_declarator), field('parameters', $.parameter_list))),
481
+ function_type_declarator: ($) =>
482
+ prec(1, seq(field('declarator', $._type_declarator), field('parameters', $.parameter_list))),
483
+ abstract_function_declarator: ($) =>
484
+ prec(1, seq(field('declarator', optional($._abstract_declarator)), field('parameters', $.parameter_list))),
485
+
486
+ _old_style_function_declarator: ($) =>
487
+ seq(
488
+ field('declarator', $._declarator),
489
+ field('parameters', alias($._old_style_parameter_list, $.parameter_list))
490
+ ),
491
+
492
+ array_declarator: ($) =>
493
+ prec(
494
+ 1,
495
+ seq(
496
+ field('declarator', $._declarator),
497
+ '[',
498
+ repeat(choice($.type_qualifier, 'static')),
499
+ field('size', optional(choice($.expression, '*'))),
500
+ ']'
501
+ )
502
+ ),
503
+ array_field_declarator: ($) =>
504
+ prec(
505
+ 1,
506
+ seq(
507
+ field('declarator', $._field_declarator),
508
+ '[',
509
+ repeat(choice($.type_qualifier, 'static')),
510
+ field('size', optional(choice($.expression, '*'))),
511
+ ']'
512
+ )
513
+ ),
514
+ array_type_declarator: ($) =>
515
+ prec(
516
+ 1,
517
+ seq(
518
+ field('declarator', $._type_declarator),
519
+ '[',
520
+ repeat(choice($.type_qualifier, 'static')),
521
+ field('size', optional(choice($.expression, '*'))),
522
+ ']'
523
+ )
524
+ ),
525
+ abstract_array_declarator: ($) =>
526
+ prec(
527
+ 1,
528
+ seq(
529
+ field('declarator', optional($._abstract_declarator)),
530
+ '[',
531
+ repeat(choice($.type_qualifier, 'static')),
532
+ field('size', optional(choice($.expression, '*'))),
533
+ ']'
534
+ )
535
+ ),
536
+
537
+ init_declarator: ($) =>
538
+ seq(field('declarator', $._declarator), '=', field('value', choice($.initializer_list, $.expression))),
539
+
540
+ compound_statement: ($) => seq('{', repeat($._block_item), '}'),
541
+
542
+ storage_class_specifier: () =>
543
+ choice(
544
+ 'extern',
545
+ 'static',
546
+ 'auto',
547
+ 'register',
548
+ 'inline',
549
+ '__inline',
550
+ '__inline__',
551
+ '__forceinline',
552
+ 'thread_local',
553
+ '__thread'
554
+ ),
555
+
556
+ type_qualifier: ($) =>
557
+ choice(
558
+ 'const',
559
+ 'constexpr',
560
+ 'volatile',
561
+ 'restrict',
562
+ '__restrict__',
563
+ '__extension__',
564
+ '_Atomic',
565
+ '_Noreturn',
566
+ 'noreturn',
567
+ '_Nonnull',
568
+ $.alignas_qualifier
569
+ ),
570
+
571
+ alignas_qualifier: ($) => seq(choice('alignas', '_Alignas'), '(', choice($.expression, $.type_descriptor), ')'),
572
+
573
+ type_specifier: ($) =>
574
+ choice(
575
+ $.struct_specifier,
576
+ $.union_specifier,
577
+ $.enum_specifier,
578
+ $.macro_type_specifier,
579
+ $.sized_type_specifier,
580
+ $.primitive_type,
581
+ $._type_identifier
582
+ ),
583
+
584
+ sized_type_specifier: ($) =>
585
+ choice(
586
+ seq(
587
+ repeat(choice('signed', 'unsigned', 'long', 'short')),
588
+ field('type', optional(choice(prec.dynamic(-1, $._type_identifier), $.primitive_type))),
589
+ repeat1(choice('signed', 'unsigned', 'long', 'short'))
590
+ ),
591
+ seq(
592
+ repeat1(choice('signed', 'unsigned', 'long', 'short')),
593
+ repeat($.type_qualifier),
594
+ field('type', optional(choice(prec.dynamic(-1, $._type_identifier), $.primitive_type))),
595
+ repeat(choice('signed', 'unsigned', 'long', 'short'))
596
+ )
597
+ ),
598
+
599
+ primitive_type: () =>
600
+ token(
601
+ choice(
602
+ 'bool',
603
+ 'char',
604
+ 'int',
605
+ 'float',
606
+ 'double',
607
+ 'void',
608
+ 'size_t',
609
+ 'ssize_t',
610
+ 'ptrdiff_t',
611
+ 'intptr_t',
612
+ 'uintptr_t',
613
+ 'charptr_t',
614
+ 'nullptr_t',
615
+ 'max_align_t',
616
+ ...[8, 16, 32, 64].map((n) => `int${n}_t`),
617
+ ...[8, 16, 32, 64].map((n) => `uint${n}_t`),
618
+ ...[8, 16, 32, 64].map((n) => `char${n}_t`)
619
+ )
620
+ ),
621
+
622
+ enum_specifier: ($) =>
623
+ seq(
624
+ 'enum',
625
+ choice(
626
+ seq(
627
+ field('name', $._type_identifier),
628
+ optional(seq(':', field('underlying_type', $.primitive_type))),
629
+ field('body', optional($.enumerator_list))
630
+ ),
631
+ field('body', $.enumerator_list)
632
+ ),
633
+ optional($.attribute_specifier)
634
+ ),
635
+
636
+ enumerator_list: ($) =>
637
+ seq(
638
+ '{',
639
+ repeat(
640
+ choice(
641
+ seq($.enumerator, ','),
642
+ alias($.preproc_if_in_enumerator_list, $.preproc_if),
643
+ alias($.preproc_ifdef_in_enumerator_list, $.preproc_ifdef),
644
+ seq($.preproc_call, ',')
645
+ )
646
+ ),
647
+ optional(
648
+ seq(
649
+ choice(
650
+ $.enumerator,
651
+ alias($.preproc_if_in_enumerator_list_no_comma, $.preproc_if),
652
+ alias($.preproc_ifdef_in_enumerator_list_no_comma, $.preproc_ifdef),
653
+ $.preproc_call
654
+ )
655
+ )
656
+ ),
657
+ '}'
658
+ ),
659
+
660
+ struct_specifier: ($) =>
661
+ prec.right(
662
+ seq(
663
+ 'struct',
664
+ optional($.attribute_specifier),
665
+ optional($.ms_declspec_modifier),
666
+ choice(
667
+ seq(field('name', $._type_identifier), field('body', optional($.field_declaration_list))),
668
+ field('body', $.field_declaration_list)
669
+ ),
670
+ optional($.attribute_specifier)
671
+ )
672
+ ),
673
+
674
+ union_specifier: ($) =>
675
+ prec.right(
676
+ seq(
677
+ 'union',
678
+ optional($.ms_declspec_modifier),
679
+ choice(
680
+ seq(field('name', $._type_identifier), field('body', optional($.field_declaration_list))),
681
+ field('body', $.field_declaration_list)
682
+ ),
683
+ optional($.attribute_specifier)
684
+ )
685
+ ),
686
+
687
+ field_declaration_list: ($) => seq('{', repeat($._field_declaration_list_item), '}'),
688
+
689
+ _field_declaration_list_item: ($) =>
690
+ choice(
691
+ $.field_declaration,
692
+ $.preproc_def,
693
+ $.preproc_function_def,
694
+ $.preproc_call,
695
+ alias($.preproc_if_in_field_declaration_list, $.preproc_if),
696
+ alias($.preproc_ifdef_in_field_declaration_list, $.preproc_ifdef)
697
+ ),
698
+
699
+ field_declaration: ($) =>
700
+ seq($._declaration_specifiers, optional($._field_declaration_declarator), optional($.attribute_specifier), ';'),
701
+ _field_declaration_declarator: ($) =>
702
+ commaSep1(seq(field('declarator', $._field_declarator), optional($.bitfield_clause))),
703
+
704
+ bitfield_clause: ($) => seq(':', $.expression),
705
+
706
+ enumerator: ($) => seq(field('name', $.identifier), optional(seq('=', field('value', $.expression)))),
707
+
708
+ variadic_parameter: () => '...',
709
+
710
+ parameter_list: ($) =>
711
+ seq('(', choice(commaSep(choice($.parameter_declaration, $.variadic_parameter)), $.compound_statement), ')'),
712
+ _old_style_parameter_list: ($) => seq('(', commaSep(choice($.identifier, $.variadic_parameter)), ')'),
713
+
714
+ parameter_declaration: ($) =>
715
+ seq(
716
+ $._declaration_specifiers,
717
+ optional(field('declarator', choice($._declarator, $._abstract_declarator))),
718
+ repeat($.attribute_specifier)
719
+ ),
720
+
721
+ // Statements
722
+
723
+ attributed_statement: ($) => seq(repeat1($.attribute_declaration), $.statement),
724
+
725
+ statement: ($) => choice($.case_statement, $._non_case_statement),
726
+
727
+ _non_case_statement: ($) =>
728
+ choice(
729
+ $.attributed_statement,
730
+ $.labeled_statement,
731
+ $.compound_statement,
732
+ $.expression_statement,
733
+ $.if_statement,
734
+ $.switch_statement,
735
+ $.do_statement,
736
+ $.while_statement,
737
+ $.for_statement,
738
+ $.return_statement,
739
+ $.break_statement,
740
+ $.continue_statement,
741
+ $.goto_statement,
742
+ $.seh_try_statement,
743
+ $.seh_leave_statement
744
+ ),
745
+
746
+ _top_level_statement: ($) =>
747
+ choice(
748
+ $.case_statement,
749
+ $.attributed_statement,
750
+ $.labeled_statement,
751
+ $.compound_statement,
752
+ alias($._top_level_expression_statement, $.expression_statement),
753
+ $.if_statement,
754
+ $.switch_statement,
755
+ $.do_statement,
756
+ $.while_statement,
757
+ $.for_statement,
758
+ $.return_statement,
759
+ $.break_statement,
760
+ $.continue_statement,
761
+ $.goto_statement
762
+ ),
763
+
764
+ labeled_statement: ($) => seq(field('label', $._statement_identifier), ':', choice($.declaration, $.statement)),
765
+
766
+ // This is missing binary expressions, others were kept so that macro code can be parsed better and code examples
767
+ _top_level_expression_statement: ($) => seq(optional($._expression_not_binary), ';'),
768
+
769
+ expression_statement: ($) => seq(optional(choice($.expression, $.comma_expression)), ';'),
770
+
771
+ if_statement: ($) =>
772
+ prec.right(
773
+ seq(
774
+ 'if',
775
+ field('condition', $.parenthesized_expression),
776
+ field('consequence', $.statement),
777
+ optional(field('alternative', $.else_clause))
778
+ )
779
+ ),
780
+
781
+ else_clause: ($) => seq('else', $.statement),
782
+
783
+ switch_statement: ($) =>
784
+ seq('switch', field('condition', $.parenthesized_expression), field('body', $.compound_statement)),
785
+
786
+ case_statement: ($) =>
787
+ prec.right(
788
+ seq(
789
+ choice(seq('case', field('value', $.expression)), 'default'),
790
+ ':',
791
+ repeat(choice($._non_case_statement, $.declaration, $.type_definition))
792
+ )
793
+ ),
794
+
795
+ while_statement: ($) => seq('while', field('condition', $.parenthesized_expression), field('body', $.statement)),
796
+
797
+ do_statement: ($) =>
798
+ seq('do', field('body', $.statement), 'while', field('condition', $.parenthesized_expression), ';'),
799
+
800
+ for_statement: ($) => seq('for', '(', $._for_statement_body, ')', field('body', $.statement)),
801
+ _for_statement_body: ($) =>
802
+ seq(
803
+ choice(
804
+ field('initializer', $.declaration),
805
+ seq(field('initializer', optional(choice($.expression, $.comma_expression))), ';')
806
+ ),
807
+ field('condition', optional(choice($.expression, $.comma_expression))),
808
+ ';',
809
+ field('update', optional(choice($.expression, $.comma_expression)))
810
+ ),
811
+
812
+ return_statement: ($) => seq('return', optional(choice($.expression, $.comma_expression)), ';'),
813
+
814
+ break_statement: () => seq('break', ';'),
815
+
816
+ continue_statement: () => seq('continue', ';'),
817
+
818
+ goto_statement: ($) => seq('goto', field('label', $._statement_identifier), ';'),
819
+
820
+ seh_try_statement: ($) =>
821
+ seq('__try', field('body', $.compound_statement), choice($.seh_except_clause, $.seh_finally_clause)),
822
+
823
+ seh_except_clause: ($) =>
824
+ seq('__except', field('filter', $.parenthesized_expression), field('body', $.compound_statement)),
825
+
826
+ seh_finally_clause: ($) => seq('__finally', field('body', $.compound_statement)),
827
+
828
+ seh_leave_statement: () => seq('__leave', ';'),
829
+
830
+ // Expressions
831
+
832
+ expression: ($) => choice($._expression_not_binary, $.binary_expression),
833
+
834
+ _expression_not_binary: ($) =>
835
+ choice(
836
+ $.conditional_expression,
837
+ $.assignment_expression,
838
+ $.unary_expression,
839
+ $.update_expression,
840
+ $.cast_expression,
841
+ $.pointer_expression,
842
+ $.sizeof_expression,
843
+ $.alignof_expression,
844
+ $.offsetof_expression,
845
+ $.generic_expression,
846
+ $.subscript_expression,
847
+ $.call_expression,
848
+ $.field_expression,
849
+ $.compound_literal_expression,
850
+ $.identifier,
851
+ $.number_literal,
852
+ $._string,
853
+ $.true,
854
+ $.false,
855
+ $.null,
856
+ $.char_literal,
857
+ $.parenthesized_expression,
858
+ $.gnu_asm_expression,
859
+ $.extension_expression
860
+ ),
861
+
862
+ _string: ($) => prec.left(choice($.string_literal, $.concatenated_string)),
863
+
864
+ comma_expression: ($) =>
865
+ seq(field('left', $.expression), ',', field('right', choice($.expression, $.comma_expression))),
866
+
867
+ conditional_expression: ($) =>
868
+ prec.right(
869
+ PREC.CONDITIONAL,
870
+ seq(
871
+ field('condition', $.expression),
872
+ '?',
873
+ optional(field('consequence', choice($.expression, $.comma_expression))),
874
+ ':',
875
+ field('alternative', $.expression)
876
+ )
877
+ ),
878
+
879
+ _assignment_left_expression: ($) =>
880
+ choice(
881
+ $.identifier,
882
+ $.call_expression,
883
+ $.field_expression,
884
+ $.pointer_expression,
885
+ $.subscript_expression,
886
+ $.parenthesized_expression
887
+ ),
888
+
889
+ assignment_expression: ($) =>
890
+ prec.right(
891
+ PREC.ASSIGNMENT,
892
+ seq(
893
+ field('left', $._assignment_left_expression),
894
+ field('operator', choice('=', '*=', '/=', '%=', '+=', '-=', '<<=', '>>=', '&=', '^=', '|=')),
895
+ field('right', $.expression)
896
+ )
897
+ ),
898
+
899
+ pointer_expression: ($) =>
900
+ prec.left(PREC.CAST, seq(field('operator', choice('*', '&')), field('argument', $.expression))),
901
+
902
+ unary_expression: ($) =>
903
+ prec.left(PREC.UNARY, seq(field('operator', choice('!', '~', '-', '+')), field('argument', $.expression))),
904
+
905
+ binary_expression: ($) => {
906
+ const table = [
907
+ ['+', PREC.ADD],
908
+ ['-', PREC.ADD],
909
+ ['*', PREC.MULTIPLY],
910
+ ['/', PREC.MULTIPLY],
911
+ ['%', PREC.MULTIPLY],
912
+ ['||', PREC.LOGICAL_OR],
913
+ ['&&', PREC.LOGICAL_AND],
914
+ ['|', PREC.INCLUSIVE_OR],
915
+ ['^', PREC.EXCLUSIVE_OR],
916
+ ['&', PREC.BITWISE_AND],
917
+ ['==', PREC.EQUAL],
918
+ ['!=', PREC.EQUAL],
919
+ ['>', PREC.RELATIONAL],
920
+ ['>=', PREC.RELATIONAL],
921
+ ['<=', PREC.RELATIONAL],
922
+ ['<', PREC.RELATIONAL],
923
+ ['<<', PREC.SHIFT],
924
+ ['>>', PREC.SHIFT],
925
+ ];
926
+
927
+ return choice(
928
+ ...table.map(([operator, precedence]) => {
929
+ return prec.left(
930
+ precedence,
931
+ seq(
932
+ field('left', $.expression),
933
+ // @ts-ignore
934
+ field('operator', operator),
935
+ field('right', $.expression)
936
+ )
937
+ );
938
+ })
939
+ );
940
+ },
941
+
942
+ update_expression: ($) => {
943
+ const argument = field('argument', $.expression);
944
+ const operator = field('operator', choice('--', '++'));
945
+ return prec.right(PREC.UNARY, choice(seq(operator, argument), seq(argument, operator)));
946
+ },
947
+
948
+ cast_expression: ($) =>
949
+ prec(PREC.CAST, seq('(', field('type', $.type_descriptor), ')', field('value', $.expression))),
950
+
951
+ type_descriptor: ($) =>
952
+ seq(
953
+ repeat($.type_qualifier),
954
+ field('type', $.type_specifier),
955
+ repeat($.type_qualifier),
956
+ field('declarator', optional($._abstract_declarator))
957
+ ),
958
+
959
+ sizeof_expression: ($) =>
960
+ prec(
961
+ PREC.SIZEOF,
962
+ seq('sizeof', choice(field('value', $.expression), seq('(', field('type', $.type_descriptor), ')')))
963
+ ),
964
+
965
+ alignof_expression: ($) =>
966
+ prec(
967
+ PREC.SIZEOF,
968
+ seq(
969
+ choice('__alignof__', '__alignof', '_alignof', 'alignof', '_Alignof'),
970
+ seq('(', field('type', $.type_descriptor), ')')
971
+ )
972
+ ),
973
+
974
+ offsetof_expression: ($) =>
975
+ prec(
976
+ PREC.OFFSETOF,
977
+ seq('offsetof', seq('(', field('type', $.type_descriptor), ',', field('member', $._field_identifier), ')'))
978
+ ),
979
+
980
+ generic_expression: ($) =>
981
+ prec(
982
+ PREC.CALL,
983
+ seq('_Generic', '(', $.expression, ',', commaSep1(seq($.type_descriptor, ':', $.expression)), ')')
984
+ ),
985
+
986
+ subscript_expression: ($) =>
987
+ prec(PREC.SUBSCRIPT, seq(field('argument', $.expression), '[', field('index', $.expression), ']')),
988
+
989
+ call_expression: ($) =>
990
+ prec(PREC.CALL, seq(field('function', $.expression), field('arguments', $.argument_list))),
991
+
992
+ gnu_asm_expression: ($) =>
993
+ prec(
994
+ PREC.CALL,
995
+ seq(
996
+ choice('asm', '__asm__', '__asm'),
997
+ repeat($.gnu_asm_qualifier),
998
+ '(',
999
+ field('assembly_code', $._string),
1000
+ optional(
1001
+ seq(
1002
+ field('output_operands', $.gnu_asm_output_operand_list),
1003
+ optional(
1004
+ seq(
1005
+ field('input_operands', $.gnu_asm_input_operand_list),
1006
+ optional(
1007
+ seq(
1008
+ field('clobbers', $.gnu_asm_clobber_list),
1009
+ optional(field('goto_labels', $.gnu_asm_goto_list))
1010
+ )
1011
+ )
1012
+ )
1013
+ )
1014
+ )
1015
+ ),
1016
+ ')'
1017
+ )
1018
+ ),
1019
+
1020
+ gnu_asm_qualifier: () => choice('volatile', '__volatile__', 'inline', 'goto'),
1021
+
1022
+ gnu_asm_output_operand_list: ($) => seq(':', commaSep(field('operand', $.gnu_asm_output_operand))),
1023
+
1024
+ gnu_asm_output_operand: ($) =>
1025
+ seq(
1026
+ optional(seq('[', field('symbol', $.identifier), ']')),
1027
+ field('constraint', $.string_literal),
1028
+ '(',
1029
+ field('value', $.expression),
1030
+ ')'
1031
+ ),
1032
+
1033
+ gnu_asm_input_operand_list: ($) => seq(':', commaSep(field('operand', $.gnu_asm_input_operand))),
1034
+
1035
+ gnu_asm_input_operand: ($) =>
1036
+ seq(
1037
+ optional(seq('[', field('symbol', $.identifier), ']')),
1038
+ field('constraint', $.string_literal),
1039
+ '(',
1040
+ field('value', $.expression),
1041
+ ')'
1042
+ ),
1043
+
1044
+ gnu_asm_clobber_list: ($) => seq(':', commaSep(field('register', $._string))),
1045
+
1046
+ gnu_asm_goto_list: ($) => seq(':', commaSep(field('label', $.identifier))),
1047
+
1048
+ extension_expression: ($) => seq('__extension__', $.expression),
1049
+
1050
+ // The compound_statement is added to parse macros taking statements as arguments, e.g. MYFORLOOP(1, 10, i, { foo(i); bar(i); })
1051
+ argument_list: ($) => seq('(', commaSep(choice($.expression, $.compound_statement)), ')'),
1052
+
1053
+ field_expression: ($) =>
1054
+ seq(
1055
+ prec(PREC.FIELD, seq(field('argument', $.expression), field('operator', choice('.', '->')))),
1056
+ field('field', $._field_identifier)
1057
+ ),
1058
+
1059
+ compound_literal_expression: ($) =>
1060
+ seq('(', field('type', $.type_descriptor), ')', field('value', $.initializer_list)),
1061
+
1062
+ parenthesized_expression: ($) => seq('(', choice($.expression, $.comma_expression, $.compound_statement), ')'),
1063
+
1064
+ initializer_list: ($) =>
1065
+ seq('{', commaSep(choice($.initializer_pair, $.expression, $.initializer_list)), optional(','), '}'),
1066
+
1067
+ initializer_pair: ($) =>
1068
+ choice(
1069
+ seq(
1070
+ field(
1071
+ 'designator',
1072
+ repeat1(choice($.subscript_designator, $.field_designator, $.subscript_range_designator))
1073
+ ),
1074
+ '=',
1075
+ field('value', choice($.expression, $.initializer_list))
1076
+ ),
1077
+ seq(field('designator', $._field_identifier), ':', field('value', choice($.expression, $.initializer_list)))
1078
+ ),
1079
+
1080
+ subscript_designator: ($) => seq('[', $.expression, ']'),
1081
+
1082
+ subscript_range_designator: ($) => seq('[', field('start', $.expression), '...', field('end', $.expression), ']'),
1083
+
1084
+ field_designator: ($) => seq('.', $._field_identifier),
1085
+
1086
+ number_literal: () => {
1087
+ const separator = "'";
1088
+ const hex = /[0-9a-fA-F]/;
1089
+ const decimal = /[0-9]/;
1090
+ const hexDigits = seq(repeat1(hex), repeat(seq(separator, repeat1(hex))));
1091
+ const decimalDigits = seq(repeat1(decimal), repeat(seq(separator, repeat1(decimal))));
1092
+ return token(
1093
+ seq(
1094
+ optional(/[-+]/),
1095
+ optional(choice(/0[xX]/, /0[bB]/)),
1096
+ choice(
1097
+ seq(
1098
+ choice(decimalDigits, seq(/0[bB]/, decimalDigits), seq(/0[xX]/, hexDigits)),
1099
+ optional(seq('.', optional(hexDigits)))
1100
+ ),
1101
+ seq('.', decimalDigits)
1102
+ ),
1103
+ optional(seq(/[eEpP]/, optional(seq(optional(/[-+]/), hexDigits)))),
1104
+ /[uUlLwWfFbBdD]*/
1105
+ )
1106
+ );
1107
+ },
1108
+
1109
+ char_literal: ($) =>
1110
+ seq(
1111
+ choice("L'", "u'", "U'", "u8'", "'"),
1112
+ repeat1(choice($.escape_sequence, alias(token.immediate(/[^\n']/), $.character))),
1113
+ "'"
1114
+ ),
1115
+
1116
+ // Must concatenate at least 2 nodes, one of which must be a string_literal.
1117
+ // Identifier is added to parse macros that are strings, like PRIu64.
1118
+ concatenated_string: ($) =>
1119
+ prec.right(
1120
+ seq(
1121
+ choice(
1122
+ seq($.identifier, $.string_literal),
1123
+ seq($.string_literal, $.string_literal),
1124
+ seq($.string_literal, $.identifier)
1125
+ ),
1126
+ repeat(choice($.string_literal, $.identifier))
1127
+ )
1128
+ ),
1129
+
1130
+ string_literal: ($) =>
1131
+ seq(
1132
+ choice('L"', 'u"', 'U"', 'u8"', '"'),
1133
+ repeat(choice(alias(token.immediate(prec(1, /[^\\"\n]+/)), $.string_content), $.escape_sequence)),
1134
+ '"'
1135
+ ),
1136
+
1137
+ escape_sequence: () =>
1138
+ token(
1139
+ prec(1, seq('\\', choice(/[^xuU]/, /\d{2,3}/, /x[0-9a-fA-F]{1,4}/, /u[0-9a-fA-F]{4}/, /U[0-9a-fA-F]{8}/)))
1140
+ ),
1141
+
1142
+ system_lib_string: () => token(seq('<', repeat(choice(/[^>\n]/, String.raw`\>`)), '>')),
1143
+
1144
+ true: () => token(choice('TRUE', 'true')),
1145
+ false: () => token(choice('FALSE', 'false')),
1146
+ null: () => choice('NULL', 'nullptr'),
1147
+
1148
+ identifier: () =>
1149
+ /(\p{XID_Start}|\$|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\$|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/u,
1150
+
1151
+ _type_identifier: ($) => alias($.identifier, $.type_identifier),
1152
+ _field_identifier: ($) => alias($.identifier, $.field_identifier),
1153
+ _statement_identifier: ($) => alias($.identifier, $.statement_identifier),
1154
+
1155
+ _empty_declaration: ($) => seq($.type_specifier, ';'),
1156
+
1157
+ macro_type_specifier: ($) =>
1158
+ prec.dynamic(-1, seq(field('name', $.identifier), '(', field('type', $.type_descriptor), ')')),
1159
+
1160
+ // http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890
1161
+ comment: () => token(choice(seq('//', /(\\+(.|\r?\n)|[^\\\n])*/), seq('/*', /[^*]*\*+([^/*][^*]*\*+)*/, '/'))),
1162
+ },
1163
+ }),
1164
+ { PREC, preprocIf, preprocessor, commaSep, commaSep1 }
1165
+ );
1166
+
1167
+ /**
1168
+ *
1169
+ * @param {string} suffix
1170
+ *
1171
+ * @param {RuleBuilder<string>} content
1172
+ *
1173
+ * @param {number} precedence
1174
+ *
1175
+ * @returns {RuleBuilders<string, string>}
1176
+ */
1177
+ function preprocIf(suffix, content, precedence = 0) {
1178
+ /**
1179
+ *
1180
+ * @param {GrammarSymbols<string>} $
1181
+ *
1182
+ * @returns {ChoiceRule}
1183
+ */
1184
+ function alternativeBlock($) {
1185
+ return choice(
1186
+ suffix ? alias($['preproc_else' + suffix], $.preproc_else) : $.preproc_else,
1187
+ suffix ? alias($['preproc_elif' + suffix], $.preproc_elif) : $.preproc_elif,
1188
+ suffix ? alias($['preproc_elifdef' + suffix], $.preproc_elifdef) : $.preproc_elifdef
1189
+ );
1190
+ }
1191
+
1192
+ return {
1193
+ ['preproc_if' + suffix]: ($) =>
1194
+ prec(
1195
+ precedence,
1196
+ seq(
1197
+ preprocessor('if'),
1198
+ field('condition', $._preproc_expression),
1199
+ '\n',
1200
+ repeat(content($)),
1201
+ field('alternative', optional(alternativeBlock($))),
1202
+ preprocessor('endif')
1203
+ )
1204
+ ),
1205
+
1206
+ ['preproc_ifdef' + suffix]: ($) =>
1207
+ prec(
1208
+ precedence,
1209
+ seq(
1210
+ choice(preprocessor('ifdef'), preprocessor('ifndef')),
1211
+ field('name', $.identifier),
1212
+ repeat(content($)),
1213
+ field('alternative', optional(alternativeBlock($))),
1214
+ preprocessor('endif')
1215
+ )
1216
+ ),
1217
+
1218
+ ['preproc_else' + suffix]: ($) => prec(precedence, seq(preprocessor('else'), repeat(content($)))),
1219
+
1220
+ ['preproc_elif' + suffix]: ($) =>
1221
+ prec(
1222
+ precedence,
1223
+ seq(
1224
+ preprocessor('elif'),
1225
+ field('condition', $._preproc_expression),
1226
+ '\n',
1227
+ repeat(content($)),
1228
+ field('alternative', optional(alternativeBlock($)))
1229
+ )
1230
+ ),
1231
+
1232
+ ['preproc_elifdef' + suffix]: ($) =>
1233
+ prec(
1234
+ precedence,
1235
+ seq(
1236
+ choice(preprocessor('elifdef'), preprocessor('elifndef')),
1237
+ field('name', $.identifier),
1238
+ repeat(content($)),
1239
+ field('alternative', optional(alternativeBlock($)))
1240
+ )
1241
+ ),
1242
+ };
1243
+ }
1244
+
1245
+ /**
1246
+ * Creates a preprocessor regex rule
1247
+ *
1248
+ * @param {string} command
1249
+ *
1250
+ * @returns {AliasRule}
1251
+ */
1252
+ function preprocessor(command) {
1253
+ return alias(new RegExp('#[ \t]*' + command), '#' + command);
1254
+ }
1255
+
1256
+ /**
1257
+ * Creates a rule to optionally match one or more of the rules separated by a comma
1258
+ *
1259
+ * @param {Rule} rule
1260
+ *
1261
+ * @returns {ChoiceRule}
1262
+ */
1263
+ function commaSep(rule) {
1264
+ return optional(commaSep1(rule));
1265
+ }
1266
+
1267
+ /**
1268
+ * Creates a rule to match one or more of the rules separated by a comma
1269
+ *
1270
+ * @param {Rule} rule
1271
+ *
1272
+ * @returns {SeqRule}
1273
+ */
1274
+ function commaSep1(rule) {
1275
+ return seq(rule, repeat(seq(',', rule)));
1276
+ }