Allow SymbolUserOpInterface operators to be used in RemoveDeadValues Pass (#117405)
[llvm-project.git] / mlir / utils / tree-sitter-mlir / grammar.js
blob2dadd46c4760cad8c9b419dfbf9eb65742eaf012
1 'use strict';
3 const builtin_dialect = require('./dialect/builtin');
4 const func_dialect = require('./dialect/func');
5 const llvm_dialect = require('./dialect/llvm');
6 const arith_dialect = require('./dialect/arith');
7 const math_dialect = require('./dialect/math');
8 const cf_dialect = require('./dialect/cf');
9 const scf_dialect = require('./dialect/scf');
10 const memref_dialect = require('./dialect/memref');
11 const vector_dialect = require('./dialect/vector');
12 const tensor_dialect = require('./dialect/tensor');
13 const bufferization_dialect = require('./dialect/bufferization');
14 const affine_dialect = require('./dialect/affine');
15 const linalg_dialect = require('./dialect/linalg');
17 const common = {
18   // Top level production:
19   //   (operation | attribute-alias-def | type-alias-def)
20   toplevel : $ => seq($._toplevel, repeat($._toplevel)),
21   _toplevel : $ => choice($.operation, $.attribute_alias_def, $.type_alias_def),
23   // Common syntax (lang-ref)
24   //  digit     ::= [0-9]
25   //  hex_digit ::= [0-9a-fA-F]
26   //  letter    ::= [a-zA-Z]
27   //  id-punct  ::= [$._-]
28   //
29   //  integer-literal ::= decimal-literal | hexadecimal-literal
30   //  decimal-literal ::= digit+
31   //  hexadecimal-literal ::= `0x` hex_digit+
32   //  float-literal ::= [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)?
33   //  string-literal  ::= `"` [^"\n\f\v\r]* `"`   TODO: define escaping rules
34   //
35   _digit : $ => /[0-9]/,
36   integer_literal : $ => choice($._decimal_literal, $._hexadecimal_literal),
37   _decimal_literal : $ => token(seq(optional(/[-+]/), repeat1(/[0-9]/))),
38   _hexadecimal_literal : $ => token(seq('0x', repeat1(/[0-9a-fA-F]/))),
39   float_literal : $ =>
40       token(seq(optional(/[-+]/), repeat1(/[0-9]/), '.', repeat(/[0-9]/),
41                 optional(seq(/[eE]/, optional(/[-+]/), repeat1(/[0-9]/))))),
42   string_literal : $ => token(seq('"', repeat(/[^\\"\n\f\v\r]+/), '"')),
43   bool_literal : $ => token(choice('true', 'false')),
44   unit_literal : $ => token('unit'),
45   complex_literal : $ =>
46       seq('(', choice($.integer_literal, $.float_literal), ',',
47           choice($.integer_literal, $.float_literal), ')'),
48   tensor_literal : $ =>
49       seq(token(choice('dense', 'sparse')), '<',
50           optional(choice(
51               seq($.nested_idx_list, repeat(seq(',', $.nested_idx_list))),
52               $._primitive_idx_literal)),
53           '>'),
54   array_literal : $ => seq(token('array'), '<', $.type, ':', $._idx_list, '>'),
55   _literal : $ => choice($.integer_literal, $.float_literal, $.string_literal,
56                          $.bool_literal, $.tensor_literal, $.array_literal,
57                          $.complex_literal, $.unit_literal),
59   nested_idx_list : $ =>
60       seq('[', optional(choice($.nested_idx_list, $._idx_list)),
61           repeat(seq(',', $.nested_idx_list)), ']'),
62   _idx_list : $ => prec.right(seq($._primitive_idx_literal,
63                                   repeat(seq(',', $._primitive_idx_literal)))),
64   _primitive_idx_literal : $ => choice($.integer_literal, $.float_literal,
65                                        $.bool_literal, $.complex_literal),
67   // Identifiers
68   //   bare-id ::= (letter|[_]) (letter|digit|[_$.])*
69   //   bare-id-list ::= bare-id (`,` bare-id)*
70   //   value-id ::= `%` suffix-id
71   //   suffix-id ::= (digit+ | ((letter|id-punct) (letter|id-punct|digit)*))
72   //   alias-name :: = bare-id
73   //
74   //   symbol-ref-id ::= `@` (suffix-id | string-literal) (`::`
75   //                     symbol-ref-id)?
76   //   value-id-list ::= value-id (`,` value-id)*
77   //
78   //   // Uses of value, e.g. in an operand list to an operation.
79   //   value-use ::= value-id
80   //   value-use-list ::= value-use (`,` value-use)*
81   bare_id : $ => token(seq(/[a-zA-Z_]/, repeat(/[a-zA-Z0-9_$.]/))),
82   _alias_or_dialect_id : $ => token(seq(/[a-zA-Z_]/, repeat(/[a-zA-Z0-9_$]/))),
83   bare_id_list : $ => seq($.bare_id, repeat(seq(',', $.bare_id))),
84   value_use : $ => seq('%', $._suffix_id),
85   _suffix_id : $ => token(seq(
86       choice(repeat1(/[0-9]/), seq(/[a-zA-Z_$.-]/, repeat(/[a-zA-Z0-9_$.-]/))),
87       optional(seq(choice(':', '#'), repeat1(/[0-9]/))))),
88   symbol_ref_id : $ => seq('@', choice($._suffix_id, $.string_literal),
89                            optional(seq('::', $.symbol_ref_id))),
90   _value_use_list : $ => seq($.value_use, repeat(seq(',', $.value_use))),
92   // Operations
93   //   operation            ::= op-result-list? (generic-operation |
94   //                            custom-operation)
95   //                            trailing-location?
96   //   generic-operation    ::= string-literal `(` value-use-list? `)`
97   //                            successor-list? region-list?
98   //                            dictionary-attribute? `:` function-type
99   //   custom-operation     ::= bare-id custom-operation-format
100   //   op-result-list       ::= op-result (`,` op-result)* `=`
101   //   op-result            ::= value-id (`:` integer-literal)
102   //   successor-list       ::= `[` successor (`,` successor)* `]`
103   //   successor            ::= caret-id (`:` bb-arg-list)?
104   //   region-list          ::= `(` region (`,` region)* `)`
105   //   dictionary-attribute ::= `{` (attribute-entry (`,` attribute-entry)*)?
106   //                            `}`
107   //   trailing-location    ::= (`loc` `(` location `)`)?
108   operation : $ =>
109       seq(field('lhs', optional($._op_result_list)),
110           field('rhs', choice($.generic_operation, $.custom_operation)),
111           field('location', optional($.trailing_location))),
112   generic_operation : $ => seq(
113       $.string_literal, $._value_use_list_parens, optional($._successor_list),
114       optional($._region_list), optional($.attribute), ':', $.function_type),
115   // custom-operation rule is defined later in the grammar, post the generic.
116   _op_result_list : $ => seq($.op_result, repeat(seq(',', $.op_result)), '='),
117   op_result : $ => seq($.value_use, optional(seq(':', $.integer_literal))),
118   _successor_list : $ =>
119       seq('[', $.successor, repeat(seq(',', $.successor)), ']'),
120   successor : $ => seq($.caret_id, optional($._value_arg_list)),
121   _region_list : $ => seq('(', $.region, repeat(seq(',', $.region)), ')'),
122   dictionary_attribute : $ => seq('{', optional($.attribute_entry),
123                                   repeat(seq(',', $.attribute_entry)), '}'),
124   trailing_location : $ => seq(token('loc'), '(', $.location, ')'),
125   // TODO: Complete location forms.
126   location : $ => $.string_literal,
128   // Blocks
129   //   block           ::= block-label operation+
130   //   block-label     ::= block-id block-arg-list? `:`
131   //   block-id        ::= caret-id
132   //   caret-id        ::= `^` suffix-id
133   //   value-id-and-type ::= value-id `:` type
134   //
135   //   // Non-empty list of names and types.
136   //   value-id-and-type-list ::= value-id-and-type (`,` value-id-and-type)*
137   //
138   //   block-arg-list ::= `(` value-id-and-type-list? `)`
139   block : $ => seq($.block_label, repeat1($.operation)),
140   block_label : $ => seq($._block_id, optional($.block_arg_list), ':'),
141   _block_id : $ => $.caret_id,
142   caret_id : $ => seq('^', $._suffix_id),
143   _value_use_and_type : $ => seq($.value_use, optional(seq(':', $.type))),
144   _value_use_and_type_list : $ =>
145       seq($._value_use_and_type, repeat(seq(',', $._value_use_and_type))),
146   block_arg_list : $ => seq('(', optional($._value_use_and_type_list), ')'),
147   _value_arg_list : $ => seq('(', optional($._value_use_type_list), ')'),
148   _value_use_type_list : $ => seq($._value_use_list, $._type_annotation),
150   // Regions
151   //   region      ::= `{` entry-block? block* `}`
152   //   entry-block ::= operation+
153   region : $ => seq('{', optional($.entry_block), repeat($.block), '}'),
154   entry_block : $ => repeat1($.operation),
156   // Types
157   //   type ::= type-alias | dialect-type | builtin-type
158   //
159   //   type-list-no-parens ::=  type (`,` type)*
160   //   type-list-parens ::= `(` type-list-no-parens? `)`
161   //
162   //   // This is a common way to refer to a value with a specified type.
163   //   ssa-use-and-type ::= ssa-use `:` type
164   //   ssa-use ::= value-use
165   //
166   //   // Non-empty list of names and types.
167   //   ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
168   //
169   //   function-type ::= (type | type-list-parens) `->` (type |
170   //                      type-list-parens)
171   type : $ => choice($.type_alias, $.dialect_type, $.builtin_type),
172   _type_list_no_parens : $ => prec.left(seq($.type, repeat(seq(',', $.type)))),
173   _type_list_parens : $ => seq('(', optional($._type_list_no_parens), ')'),
174   function_type : $ =>
175       seq(choice($.type, $._type_list_parens), $._function_return),
176   _function_return : $ => seq(token('->'), choice($.type, $._type_list_parens)),
177   _type_annotation : $ =>
178       seq(':', choice(seq($.type, choice('from', 'into', 'to'), $.type),
179                       $._type_list_no_parens)),
180   _function_type_annotation : $ => seq(':', $.function_type),
181   _literal_and_type : $ => seq($._literal, optional($._type_annotation)),
183   // Type aliases
184   //   type-alias-def ::= '!' alias-name '=' type
185   //   type-alias ::= '!' alias-name
186   type_alias_def : $ => seq('!', $._alias_or_dialect_id, '=', $.type),
187   type_alias : $ => seq('!', $._alias_or_dialect_id),
189   // Dialect Types
190   //   dialect-namespace ::= bare-id
191   //
192   //   opaque-dialect-item ::= dialect-namespace '<' string-literal '>'
193   //
194   //   pretty-dialect-item ::= dialect-namespace '.'
195   //   pretty-dialect-item-lead-ident pretty-dialect-item-body?
196   //
197   //   pretty-dialect-item-lead-ident ::= '[A-Za-z][A-Za-z0-9._]*'
198   //   pretty-dialect-item-body ::= '<' pretty-dialect-item-contents+ '>'
199   //   pretty-dialect-item-contents ::= pretty-dialect-item-body
200   //                                 | '(' pretty-dialect-item-contents+ ')'
201   //                                 | '[' pretty-dialect-item-contents+ ']'
202   //                                 | '{' pretty-dialect-item-contents+ '}'
203   //                                 | '[^[<({>\])}\0]+'
204   //
205   //   dialect-type ::= '!' (opaque-dialect-item | pretty-dialect-item)
206   dialect_type : $ =>
207       seq('!', choice($.opaque_dialect_item, $.pretty_dialect_item)),
208   dialect_namespace : $ => $._alias_or_dialect_id,
209   dialect_ident : $ => $._alias_or_dialect_id,
210   opaque_dialect_item : $ =>
211       seq($.dialect_namespace, '<', $.string_literal, '>'),
212   pretty_dialect_item : $ => seq($.dialect_namespace, '.', $.dialect_ident,
213                                  optional($.pretty_dialect_item_body)),
214   pretty_dialect_item_body : $ =>
215       seq('<', repeat($._pretty_dialect_item_contents), '>'),
216   _pretty_dialect_item_contents : $ =>
217       prec.left(choice($.pretty_dialect_item_body, repeat1(/[^<>]/))),
219   // Builtin types
220   builtin_type : $ => choice(
221       // TODO: Add opaque_type
222       $.integer_type, $.float_type, $.complex_type, $.index_type, $.memref_type,
223       $.none_type, $.tensor_type, $.vector_type, $.tuple_type),
225   // signed-integer-type ::= `si`[1-9][0-9]*
226   // unsigned-integer-type ::= `ui`[1-9][0-9]*
227   // signless-integer-type ::= `i`[1-9][0-9]*
228   // integer-type ::= signed-integer-type | unsigned-integer-type |
229   // signless-integer-type
230   integer_type : $ =>
231       token(seq(choice('si', 'ui', 'i'), /[1-9]/, repeat(/[0-9]/))),
232   float_type : $ => token(
233       choice('f16', 'f32', 'f64', 'f80', 'f128', 'bf16', 'f8E3M4', 'f8E4M3FN',
234              'f8E4M3', 'f8E5M2', 'f4E2M1FN', 'f6E2M3FN', 'f6E3M2FN',
235              'f8E8M0FNU')),
236   index_type : $ => token('index'),
237   none_type : $ => token('none'),
238   complex_type : $ => seq(token('complex'), '<', $._prim_type, '>'),
239   _prim_type : $ =>
240       choice($.integer_type, $.float_type, $.index_type, $.complex_type,
241              $.none_type, $.memref_type, $.vector_type, $.tensor_type),
243   // memref-type ::= `memref` `<` dimension-list-ranked type
244   //                 (`,` layout-specification)? (`,` memory-space)? `>`
245   // layout-specification ::= attribute-value
246   // memory-space ::= attribute-value
247   memref_type : $ =>
248       seq(token('memref'), '<', field('dimension_list', $.dim_list),
249           optional(seq(',', $.attribute_value)),
250           optional(seq(',', $.attribute_value)), '>'),
251   dim_list : $ => seq($._dim_primitive, repeat(seq('x', $._dim_primitive))),
252   _dim_primitive : $ => choice($._prim_type, repeat1($._digit), '?', '*'),
254   // tensor-type ::= `tensor` `<` dimension-list type (`,` encoding)? `>`
255   // dimension-list ::= (dimension `x`)*
256   // dimension ::= `?` | decimal-literal
257   // encoding ::= attribute-value
258   // tensor-type ::= `tensor` `<` `*` `x` type `>`
259   tensor_type : $ => seq(token('tensor'), '<', $.dim_list,
260                          optional(seq(',', $.tensor_encoding)), '>'),
261   tensor_encoding : $ => $.attribute_value,
263   // vector-type ::= `vector` `<` vector-dim-list vector-element-type `>`
264   // vector-element-type ::= float-type | integer-type | index-type
265   // vector-dim-list := (static-dim-list `x`)? (`[` static-dim-list `]` `x`)?
266   // static-dim-list ::= decimal-literal (`x` decimal-literal)*
267   vector_type : $ =>
268       seq(token('vector'), '<', optional($.vector_dim_list), $._prim_type, '>'),
269   vector_dim_list : $ =>
270       choice(seq($._static_dim_list, 'x',
271                  optional(seq('[', $._static_dim_list, ']', 'x'))),
272              seq('[', $._static_dim_list, ']', 'x')),
273   _static_dim_list : $ =>
274       seq(repeat1($._digit), repeat(seq('x', repeat1($._digit)))),
276   // tuple-type ::= `tuple` `<` (type ( `,` type)*)? `>`
277   tuple_type : $ =>
278       seq(token('tuple'), '<', $.tuple_dim, repeat(seq(',', $.tuple_dim)), '>'),
279   tuple_dim : $ => $._prim_type,
281   // Attributes
282   //   attribute-entry ::= (bare-id | string-literal) `=` attribute-value
283   //   attribute-value ::= attribute-alias | dialect-attribute |
284   //   builtin-attribute
285   attribute_entry : $ => seq(choice($.bare_id, $.string_literal),
286                              optional(seq('=', $.attribute_value))),
287   attribute_value : $ =>
288       choice(seq('[', optional($._attribute_value_nobracket),
289                  repeat(seq(',', $._attribute_value_nobracket)), ']'),
290              $._attribute_value_nobracket),
291   _attribute_value_nobracket : $ =>
292       choice($.attribute_alias, $.dialect_attribute, $.builtin_attribute,
293              $.dictionary_attribute, $._literal_and_type, $.type),
294   attribute : $ => choice($.attribute_alias, $.dialect_attribute,
295                           $.builtin_attribute, $.dictionary_attribute),
297   // Attribute Value Aliases
298   //   attribute-alias-def ::= '#' alias-name '=' attribute-value
299   //   attribute-alias ::= '#' alias-name
300   attribute_alias_def : $ =>
301       seq('#', $._alias_or_dialect_id, '=', $.attribute_value),
302   attribute_alias : $ => seq('#', $._alias_or_dialect_id),
304   // Dialect Attribute Values
305   dialect_attribute : $ =>
306       seq('#', choice($.opaque_dialect_item, $.pretty_dialect_item)),
308   // Builtin Attribute Values
309   builtin_attribute : $ => choice(
310       // TODO
311       $.strided_layout, $.affine_map, $.affine_set),
312   strided_layout : $ => seq(token('strided'), '<', '[', $._dim_list_comma, ']',
313                             optional(seq(',', token('offset'), ':',
314                                          choice($.integer_literal, '?', '*'))),
315                             '>'),
316   _dim_list_comma : $ =>
317       seq($._dim_primitive, repeat(seq(',', $._dim_primitive))),
319   affine_map : $ =>
320       seq(token('affine_map'), '<', $._multi_dim_affine_expr_parens,
321           optional($._multi_dim_affine_expr_sq), token('->'),
322           $._multi_dim_affine_expr_parens, '>'),
323   affine_set : $ =>
324       seq(token('affine_set'), '<', $._multi_dim_affine_expr_parens,
325           optional($._multi_dim_affine_expr_sq), ':',
326           $._multi_dim_affine_expr_parens, '>'),
327   _multi_dim_affine_expr_parens : $ =>
328       seq('(', optional($._multi_dim_affine_expr), ')'),
329   _multi_dim_affine_expr_sq : $ =>
330       seq('[', optional($._multi_dim_affine_expr), ']'),
332   // affine-expr ::= `(` affine-expr `)`
333   //               | affine-expr `+` affine-expr
334   //               | affine-expr `-` affine-expr
335   //               | `-`? integer-literal `*` affine-expr
336   //               | affine-expr `ceildiv` integer-literal
337   //               | affine-expr `floordiv` integer-literal
338   //               | affine-expr `mod` integer-literal
339   //               | `-`affine-expr
340   //               | bare-id
341   //               | `-`? integer-literal
342   // multi-dim-affine-expr ::= `(` `)`
343   //                         | `(` affine-expr (`,` affine-expr)* `)`
345   // semi-affine-expr ::= `(` semi-affine-expr `)`
346   //                    | semi-affine-expr `+` semi-affine-expr
347   //                    | semi-affine-expr `-` semi-affine-expr
348   //                    | symbol-or-const `*` semi-affine-expr
349   //                    | semi-affine-expr `ceildiv` symbol-or-const
350   //                    | semi-affine-expr `floordiv` symbol-or-const
351   //                    | semi-affine-expr `mod` symbol-or-const
352   //                    | bare-id
353   //                    | `-`? integer-literal
354   // symbol-or-const ::= `-`? integer-literal | symbol-id
355   // multi-dim-semi-affine-expr ::= `(` semi-affine-expr (`,` semi-affine-expr)*
356   // `)`
358   // affine-constraint ::= affine-expr `>=` `affine-expr`
359   //                     | affine-expr `<=` `affine-expr`
360   //                     | affine-expr `==` `affine-expr`
361   // affine-constraint-conjunction ::= affine-constraint (`,`
362   // affine-constraint)*
364   _multi_dim_affine_expr : $ =>
365       seq($._affine_expr, repeat(seq(',', $._affine_expr))),
366   _affine_expr : $ => prec.right(choice(
367       seq('(', $._affine_expr, ')'), seq('-', $._affine_expr),
368       seq($._affine_expr, $._affine_token, $._affine_expr), $._affine_prim)),
369   _affine_prim : $ =>
370       choice($.integer_literal, $.value_use, $.bare_id,
371              seq('symbol', '(', $.value_use, ')'),
372              seq(choice('max', 'min'), '(', $._value_use_list, ')')),
373   _affine_token : $ => token(
374       choice('+', '-', '*', 'ceildiv', 'floordiv', 'mod', '==', '>=', '<=')),
376   func_return : $ => seq(token('->'), $.type_list_attr_parens),
377   func_arg_list : $ => seq(
378       '(', optional(choice($.variadic, $._value_id_and_type_attr_list)), ')'),
379   _value_id_and_type_attr_list : $ => seq(
380       $._value_id_and_type_attr, repeat(seq(',', $._value_id_and_type_attr)),
381       optional(seq(',', $.variadic))),
382   _value_id_and_type_attr : $ => seq($._function_arg, optional($.attribute)),
383   _function_arg : $ =>
384       choice(seq($.value_use, ':', $.type), $.value_use, $.type),
385   type_list_attr_parens : $ =>
386       choice($.type,
387              seq('(', $.type, optional($.attribute),
388                  repeat(seq(',', $.type, optional($.attribute))), ')'),
389              seq('(', ')')),
390   variadic : $ => token('...'),
392   // (func.func|llvm.func) takes arguments, an optional return type, and and
393   // optional body
394   _op_func : $ =>
395       seq(field('visibility', optional('private')),
396           field('name', $.symbol_ref_id), field('arguments', $.func_arg_list),
397           field('return', optional($.func_return)),
398           field('attributes', optional(seq(token('attributes'), $.attribute))),
399           field('body', optional($.region))),
401   // dim-use-list ::= `(` ssa-use-list? `)`
402   // symbol-use-list ::= `[` ssa-use-list? `]`
403   // dim-and-symbol-use-list ::= dim-use-list symbol-use-list?
404   _value_use_list_parens : $ => seq('(', optional($._value_use_list), ')'),
405   _dim_and_symbol_use_list : $ =>
406       seq($._value_use_list_parens, optional($._dense_idx_list)),
408   // assignment-list ::= assignment | assignment `,` assignment-list
409   // assignment ::= ssa-value `=` ssa-value
410   _value_assignment_list : $ => seq('(', optional($._value_assignment),
411                                     repeat(seq(',', $._value_assignment)), ')'),
412   _value_assignment : $ => seq($.value_use, '=', $.value_use),
414   _dense_idx_list : $ => seq(
415       '[',
416       optional(seq(choice($.integer_literal, $.value_use),
417                    repeat(seq(',', choice($.integer_literal, $.value_use))))),
418       ']'),
420   // lower-bound ::= `max`? affine-map-attribute dim-and-symbol-use-list |
421   // shorthand-bound
422   // upper-bound ::= `min`? affine-map-attribute dim-and-symbol-use-list |
423   // shorthand-bound
424   // shorthand-bound ::= ssa-id | `-`? integer-literal
425   _bound : $ =>
426       choice(seq($.attribute, $._dim_and_symbol_use_list), $._shorthand_bound),
427   _shorthand_bound : $ => choice($.value_use, $.integer_literal),
429   // Dialect-specific attributes
430   restrict_attr : $ => token('restrict'),
431   writable_attr : $ => token('writable'),
432   gather_dims_attr : $ =>
433       seq(token('gather_dims'), '(', $._dense_idx_list, ')'),
434   scatter_dims_attr : $ =>
435       seq(token('scatter_dims'), '(', $._dense_idx_list, ')'),
436   unique_attr : $ => token('unique'),
437   nofold_attr : $ => token('nofold'),
438   outer_dims_perm_attr : $ =>
439       seq(token('outer_dims_perm'), '=', $._dense_idx_list),
440   inner_dims_pos_attr : $ =>
441       seq(token('inner_dims_pos'), '=', $._dense_idx_list),
442   inner_tiles_attr : $ => seq(token('inner_tiles'), '=', $._dense_idx_list),
443   isWrite_attr : $ => token(choice('read', 'write')),
444   localityHint_attr : $ => seq(token('locality'), '<', $.integer_literal, '>'),
445   isDataCache_attr : $ => token(choice('data', 'instr')),
446   fastmath_attr : $ =>
447       seq(token('fastmath'), '<',
448           seq($._fastmath_flag, repeat(seq(',', $._fastmath_flag))), '>'),
449   _fastmath_flag : $ => token(choice('none', 'reassoc', 'nnan', 'ninf', 'nsz',
450                                      'arcp', 'contract', 'afn', 'fast')),
452   // Comment (standard BCPL)
453   comment : $ => token(seq('//', /.*/)),
455   // TODO: complete
456   custom_operation : $ =>
457       choice($.builtin_dialect, $.func_dialect, $.llvm_dialect, $.arith_dialect,
458              $.math_dialect, $.cf_dialect, $.scf_dialect, $.memref_dialect,
459              $.vector_dialect, $.tensor_dialect, $.bufferization_dialect,
460              $.affine_dialect, $.linalg_dialect)
463                module.exports = grammar({
464   name : 'mlir',
465   extras : $ => [/\s/, $.comment],
466   conflicts : $ => [[ $._static_dim_list, $._static_dim_list ],
467                     [ $.dictionary_attribute, $.region ]],
468   rules : Object.assign(common, builtin_dialect, func_dialect, llvm_dialect,
469                         arith_dialect, math_dialect, cf_dialect, scf_dialect,
470                         memref_dialect, vector_dialect, tensor_dialect,
471                         bufferization_dialect, affine_dialect, linalg_dialect)