1# This grammar is intended to be LL(k) at the token level.
2# In other words, whenever the parser is required to make a choice it must be
3# able to choose "correctly" with constant token lookahead. This means that the
4# handwritten recursive descent parser for this grammar can be implemented with
5# worst-case linear run time rather than worst-case exponential runtime.
6#
7# To ensure this property is upheld, care must be taken to avoid requiring
8# unbounded token lookahead in the grammar. To illustrate this, consider the
9# following examples requiring unbounded lookahead:
10#
11# This is rather subtle as it looks fine at first glance:
12#
13# SingleAssignExpr <- Expr (AssignOp Expr)?
14#
15# Consider the case where the AssignOp token matches but Expr after it does
16# not match. The parser would attempt to parse the Expr after the AssignOp,
17# fail, then backtrack and succeed the SingleAssignExpr rule matching only
18# the first Expr. This is an example of unbounded lookahead. The rule must
19# be rewritten so that if the AssignOp token is not followed by an Expr the
20# whole SingleAssignExpr rule fails to match:
21#
22# SingleAssignExpr <- Expr (AssignOp Expr / !AssignOp)
23#
24# The pattern is similar for e.g. the * operator. The following rule requires
25# unbounded lookahead:
26#
27# BoolOrExpr <- BoolAndExpr (OrOp BoolAndExpr)*
28#
29# and can be fixed to require only bounded lookahead by adding a !OrOp:
30#
31# BoolOrExpr <- BoolAndExpr (OrOp BoolAndExpr)* !OrOp
32#
33# Note also that the negative lookahead added with the ! operator must always be
34# for a constant maximum number of tokens.
35#
36# See this paper for analysis of how LL(k) grammars relate to PEGs:
37# https://arxiv.org/abs/1304.3177
38
39Root <- ContainerMembers skip eof
40
41# *** Top level ***
42ContainerMembers <- container_doc_comment? ContainerDecl* ContainerMembersRest
43ContainerMembersRest
44 <- !ContainerDeclPrefix ContainerField (COMMA ContainerMembersRest)?
45 / ContainerDecl*
46
47ContainerDecl <- TestDecl / ComptimeDecl / doc_comment? KEYWORD_pub? Decl
48
49ContainerDeclPrefix
50 <- KEYWORD_test
51 / KEYWORD_comptime LBRACE
52 / doc_comment? KEYWORD_pub? DeclPrefix
53
54TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block
55
56ComptimeDecl <- KEYWORD_comptime Block
57
58Decl
59 <- (KEYWORD_export / KEYWORD_inline / KEYWORD_noinline)? FnProto (SEMICOLON / Block)
60 / KEYWORD_extern STRINGLITERALSINGLE? FnProto SEMICOLON
61 / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? GlobalVarDecl
62
63DeclPrefix
64 <- (KEYWORD_export / KEYWORD_inline / KEYWORD_noinline)? KEYWORD_fn
65 / KEYWORD_extern STRINGLITERALSINGLE? KEYWORD_fn
66 / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? (KEYWORD_const / KEYWORD_var)
67
68FnProto <- KEYWORD_fn IDENTIFIER? ParamDeclList ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr
69
70VarDeclProto <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection?
71
72GlobalVarDecl <- VarDeclProto (EQUAL Expr)? SEMICOLON
73
74ContainerField <- doc_comment? KEYWORD_comptime? (IDENTIFIER COLON)? TypeExpr ByteAlign? (EQUAL Expr)?
75
76# *** Block Level ***
77BlockStatement
78 <- Statement
79 / KEYWORD_defer BlockExprStatement
80 / KEYWORD_errdefer BlockExprStatement
81 / !StatementPrefix KEYWORD_comptime? VarAssignStatement
82
83Statement
84 <- IfStatement
85 / LabeledStatement
86 / KEYWORD_nosuspend BlockExprStatement
87 / KEYWORD_comptime BlockExpr
88 / KEYWORD_suspend BlockExprStatement
89 / !StatementPrefix KEYWORD_comptime? AssignExpr SEMICOLON
90
91StatementPrefix
92 <- KEYWORD_if
93 / BlockLabel? (LBRACE / KEYWORD_inline? (KEYWORD_for / KEYWORD_while) / KEYWORD_switch)
94 / KEYWORD_nosuspend
95 / KEYWORD_comptime BlockExprPrefix
96
97IfStatement
98 <- IfPrefix BlockExpr (KEYWORD_else Payload? Statement / !KEYWORD_else)
99 / IfPrefix !BlockExprPrefix AssignExpr (SEMICOLON / KEYWORD_else Payload? Statement)
100
101LabeledStatement <- BlockLabel? (Block / LoopStatement / SwitchExpr)
102
103LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
104
105ForStatement
106 <- ForPrefix BlockExpr (KEYWORD_else Statement / !KEYWORD_else)
107 / ForPrefix !BlockExprPrefix AssignExpr (SEMICOLON / KEYWORD_else Statement)
108
109WhileStatement
110 <- WhilePrefix BlockExpr (KEYWORD_else Payload? Statement / !KEYWORD_else)
111 / WhilePrefix !BlockExprPrefix AssignExpr (SEMICOLON / KEYWORD_else Payload? Statement)
112
113BlockExprStatement
114 <- BlockExpr
115 / !BlockExprPrefix AssignExpr SEMICOLON
116
117BlockExprPrefix <- BlockLabel? LBRACE
118BlockExpr <- BlockLabel? Block
119
120# An assignment or a destructure whose LHS are all lvalue expressions or variable declarations.
121VarAssignStatement <- (VarDeclProto / Expr) (COMMA (VarDeclProto / Expr))* EQUAL Expr SEMICOLON
122
123# *** Expression Level ***
124
125# An assignment or a destructure whose LHS are all lvalue expressions.
126AssignExpr <- Expr (AssignOp Expr / (COMMA Expr)+ EQUAL Expr / !AssignOp !COMMA)
127
128SingleAssignExpr <- Expr (AssignOp Expr / !AssignOp)
129
130Expr <- BoolOrExpr
131
132BoolOrExpr <- BoolAndExpr (OrOp BoolAndExpr)* !OrOp
133
134BoolAndExpr <- CompareExpr (AndOp CompareExpr)* !AndOp
135
136CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? !CompareOp
137
138BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* !BitwiseOp
139
140BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)* !BitShiftOp
141
142AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)* !AdditionOp
143
144MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)* !MultiplyOp
145
146PrefixExpr <- PrefixOp* !PrefixOp PrimaryExpr
147
148PrimaryExpr
149 <- AsmExpr
150 / IfExpr
151 / KEYWORD_break BreakLabel? (Expr / !ExprPrefix)
152 / KEYWORD_comptime Expr
153 / KEYWORD_nosuspend Expr
154 / KEYWORD_continue BreakLabel? (Expr / !ExprPrefix)
155 / KEYWORD_resume Expr
156 / KEYWORD_return (Expr / !ExprPrefix)
157 / BlockLabel? LoopExpr
158 / Block
159 / CurlySuffixExpr
160
161IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr / !KEYWORD_else)
162
163Block <- LBRACE BlockStatement* RBRACE
164
165LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)
166
167ForExpr <- ForPrefix Expr (KEYWORD_else Expr / !KEYWORD_else)
168
169WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
170
171CurlySuffixExpr <- TypeExpr (InitList / !LBRACE)
172
173InitList
174 <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
175 / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
176 / LBRACE RBRACE
177
178TypeExpr <- PrefixTypeOp* !PrefixTypeOpPrefix ErrorUnionExpr
179
180ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr / !EXCLAMATIONMARK)
181
182SuffixExpr <- PrimaryTypeExpr SuffixOp* !SuffixOpPrefix
183
184PrimaryTypeExpr
185 <- BUILTINIDENTIFIER FnCallArguments
186 / CHAR_LITERAL
187 / ContainerType
188 / DOT IDENTIFIER
189 / DOT InitList
190 / ErrorSetDecl
191 / FnProto
192 / GroupedExpr
193 / LabeledTypeExpr
194 / IDENTIFIER
195 / IfTypeExpr
196 / KEYWORD_comptime TypeExpr
197 / KEYWORD_error DOT IDENTIFIER
198 / KEYWORD_anyframe
199 / KEYWORD_unreachable
200 / NUMBERLITERAL
201 / STRINGLITERAL
202
203ContainerType <- (KEYWORD_extern / KEYWORD_packed)? ContainerTypeAuto
204
205ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE
206
207GroupedExpr <- LPAREN Expr RPAREN
208
209IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr / !KEYWORD_else)
210
211LabeledTypeExpr
212 <- BlockLabel Block
213 / BlockLabel? LoopTypeExpr
214 / BlockLabel? SwitchExpr
215
216LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
217
218ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr / !KEYWORD_else)
219
220WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr / !KEYWORD_else)
221
222SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
223
224# *** Assembly ***
225AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN Expr AsmOutput? RPAREN
226
227AsmOutput <- COLON AsmOutputList AsmInput?
228
229AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERALSINGLE LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
230
231AsmInput <- COLON AsmInputList AsmClobbers?
232
233AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERALSINGLE LPAREN Expr RPAREN
234
235AsmClobbers <- COLON Expr
236
237# *** Helper grammar ***
238BreakLabel <- COLON IDENTIFIER
239
240BlockLabel <- IDENTIFIER COLON
241
242FieldInit <- DOT IDENTIFIER EQUAL Expr
243
244WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
245
246LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
247
248AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN
249
250# Fn specific
251CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
252
253ParamDecl <- doc_comment? (KEYWORD_noalias / KEYWORD_comptime?) (IDENTIFIER COLON)? ParamType
254
255ParamType
256 <- KEYWORD_anytype
257 / TypeExpr
258
259# Control flow prefixes
260IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
261
262WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
263
264ForPrefix <- KEYWORD_for LPAREN ForArgumentsList RPAREN PtrListPayload
265
266# Payloads
267Payload <- PIPE IDENTIFIER PIPE
268
269PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
270
271PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
272
273PtrListPayload <- PIPE ASTERISK? IDENTIFIER (COMMA ASTERISK? IDENTIFIER)* COMMA? PIPE
274
275# Switch specific
276SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? SingleAssignExpr
277
278SwitchCase
279 <- SwitchItem (COMMA SwitchItem)* COMMA?
280 / KEYWORD_else
281
282SwitchItem <- Expr (DOT3 Expr)?
283
284# For specific
285ForArgumentsList <- ForItem (COMMA ForItem)* COMMA?
286
287ForItem <- Expr (DOT2 (Expr / !ExprPrefix) / !DOT2)
288
289# Operators
290AssignOp
291 <- ASTERISKEQUAL
292 / ASTERISKPIPEEQUAL
293 / SLASHEQUAL
294 / PERCENTEQUAL
295 / PLUSEQUAL
296 / PLUSPIPEEQUAL
297 / MINUSEQUAL
298 / MINUSPIPEEQUAL
299 / LARROW2EQUAL
300 / LARROW2PIPEEQUAL
301 / RARROW2EQUAL
302 / AMPERSANDEQUAL
303 / CARETEQUAL
304 / PIPEEQUAL
305 / ASTERISKPERCENTEQUAL
306 / PLUSPERCENTEQUAL
307 / MINUSPERCENTEQUAL
308 / EQUAL
309
310OrOp <- pre_op_white KEYWORD_or post_op_white
311 / !pre_op_white KEYWORD_or !post_op_white
312
313AndOp <- pre_op_white KEYWORD_and post_op_white
314 / !pre_op_white KEYWORD_and !post_op_white
315
316CompareOp <- pre_op_white CompareOpTok post_op_white
317 / !pre_op_white CompareOpTok !post_op_white
318CompareOpTok
319 <- EQUALEQUAL
320 / EXCLAMATIONMARKEQUAL
321 / LARROW
322 / RARROW
323 / LARROWEQUAL
324 / RARROWEQUAL
325
326BitwiseOp <- pre_op_white BitwiseOpTok post_op_white
327 / !pre_op_white BitwiseOpTok !post_op_white
328 / pre_op_white KEYWORD_catch post_op_white Payload?
329 / !pre_op_white KEYWORD_catch !post_op_white Payload?
330BitwiseOpTok
331 <- AMPERSAND ![&]
332 / CARET
333 / PIPE
334 / KEYWORD_orelse
335
336BitShiftOp <- pre_op_white BitShiftOpTok post_op_white
337 / !pre_op_white BitShiftOpTok !post_op_white
338BitShiftOpTok
339 <- LARROW2
340 / RARROW2
341 / LARROW2PIPE
342
343AdditionOp <- pre_op_white AdditionOpTok post_op_white
344 / !pre_op_white AdditionOpTok !post_op_white
345AdditionOpTok
346 <- PLUS
347 / MINUS
348 / PLUS2
349 / PLUSPERCENT
350 / MINUSPERCENT
351 / PLUSPIPE
352 / MINUSPIPE
353
354MultiplyOp <- pre_op_white MultiplyOpTok post_op_white
355 / !pre_op_white MultiplyOpTok !post_op_white
356MultiplyOpTok
357 <- PIPE2
358 / ASTERISK
359 / SLASH
360 / PERCENT
361 / ASTERISKPERCENT
362 / ASTERISKPIPE
363
364PrefixOp
365 <- EXCLAMATIONMARK
366 / MINUS
367 / TILDE
368 / MINUSPERCENT
369 / AMPERSAND
370 / KEYWORD_try
371
372PrefixTypeOp
373 <- QUESTIONMARK
374 / KEYWORD_anyframe MINUSRARROW
375 / (ManyPtrTypeStart / SliceTypeStart) PtrMods
376 / SinglePtrTypeStart SinglePtrMods
377 / ArrayTypeStart
378
379# Forbid more than one align or addrspace pointer modifier since these
380# modifiers contain sub-expressions. This allows for a simpler AST data layout.
381# Allow duplicate single-token modifiers (allowzero/const/volatile) in the grammar
382# to avoid the combinatorial explosion of grammar rules necessary to forbid duplicates
383# while permitting arbitrary order. A compile error for duplicates single-token modifiers
384# is emitted during "AstGen" after parsing is complete.
385PtrMods
386 <- PtrMod* !KEYWORD_addrspace ByteAlign? PtrMod* AddrSpace? PtrMod*
387 / PtrMod* !KEYWORD_align AddrSpace? PtrMod* ByteAlign? PtrMod*
388
389SinglePtrMods
390 <- PtrMod* !KEYWORD_addrspace BitAlign? PtrMod* AddrSpace? PtrMod*
391 / PtrMod* !KEYWORD_align AddrSpace? PtrMod* BitAlign? PtrMod*
392
393PtrMod
394 <- KEYWORD_allowzero
395 / KEYWORD_const
396 / KEYWORD_volatile
397
398PrefixTypeOpPrefix
399 <- QUESTIONMARK
400 / KEYWORD_anyframe MINUSRARROW
401 / LBRACKET
402 / ASTERISK
403
404SuffixOp
405 <- LBRACKET Expr (DOT2 (Expr / !ExprPrefix) (COLON Expr)?)? RBRACKET
406 / DOT IDENTIFIER
407 / DOTASTERISK
408 / DOT QUESTIONMARK
409 / FnCallArguments
410
411SuffixOpPrefix
412 <- LBRACKET
413 / DOT IDENTIFIER
414 / DOTASTERISK
415 / DOT QUESTIONMARK
416 / LPAREN
417
418FnCallArguments <- LPAREN ExprList RPAREN
419
420# Ptr specific
421SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET
422
423SinglePtrTypeStart <- ASTERISK
424
425ManyPtrTypeStart <- LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET
426
427ArrayTypeStart <- LBRACKET !ASTERISK Expr (COLON Expr)? RBRACKET
428
429# ContainerType specific
430ContainerTypeAuto <- ContainerTypeKind LBRACE ContainerMembers RBRACE
431
432ContainerTypeKind
433 <- KEYWORD_struct (LPAREN Expr RPAREN)?
434 / KEYWORD_opaque
435 / KEYWORD_enum (LPAREN Expr RPAREN)?
436 / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
437
438# Alignment
439ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
440
441BitAlign <- KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN
442
443# Lists
444IdentifierList <- (doc_comment? IDENTIFIER (COMMA IdentifierList)?)?
445
446SwitchProngList <- (SwitchProng (COMMA SwitchProngList)?)?
447
448AsmOutputList <- (AsmOutputItem (COMMA AsmOutputList)?)?
449
450AsmInputList <- (AsmInputItem (COMMA AsmInputList)?)?
451
452ParamDeclList <- LPAREN ParamDeclListRest
453ParamDeclListRest
454 <- RPAREN
455 / DOT3 COMMA? RPAREN
456 / ParamDecl (COMMA ParamDeclListRest / RPAREN)
457
458ExprList <- Expr (COMMA ExprList)? / !ExprPrefix
459
460ExprPrefix <- ASTERISK
461
462# *** Tokens ***
463
464# https://en.wikipedia.org/wiki/Byte_order_mark
465byte_order_mark <- '\357\273\277'
466
467# Unfortunately, there is not a standard way to match the start of the file in PEG.
468# This rule definition is compatible with the original peg(1) tool but is not
469# portable. It is however trivial to implement an equivalent rule in hand written
470# parsers and other PEG tooling should have similar mechanisms.
471sof <- &{ (yy->__pos == 0) } byte_order_mark?
472eof <- !.
473
474ox80_oxBF <- [\200-\277]
475oxF4 <- '\364'
476ox80_ox8F <- [\200-\217]
477oxF1_oxF3 <- [\361-\363]
478oxF0 <- '\360'
479ox90_0xBF <- [\220-\277]
480oxEE_oxEF <- [\356-\357]
481oxED <- '\355'
482ox80_ox9F <- [\200-\237]
483oxE1_oxEC <- [\341-\354]
484oxE0 <- '\340'
485oxA0_oxBF <- [\240-\277]
486oxC2_oxDF <- [\302-\337]
487
488# From https://lemire.me/blog/2018/05/09/how-quickly-can-you-check-that-a-string-is-valid-unicode-utf-8/
489# First Byte Second Byte Third Byte Fourth Byte
490# [0x00,0x7F]
491# [0xC2,0xDF] [0x80,0xBF]
492# 0xE0 [0xA0,0xBF] [0x80,0xBF]
493# [0xE1,0xEC] [0x80,0xBF] [0x80,0xBF]
494# 0xED [0x80,0x9F] [0x80,0xBF]
495# [0xEE,0xEF] [0x80,0xBF] [0x80,0xBF]
496# 0xF0 [0x90,0xBF] [0x80,0xBF] [0x80,0xBF]
497# [0xF1,0xF3] [0x80,0xBF] [0x80,0xBF] [0x80,0xBF]
498# 0xF4 [0x80,0x8F] [0x80,0xBF] [0x80,0xBF]
499
500multibyte_utf8 <-
501 oxF4 ox80_ox8F ox80_oxBF ox80_oxBF
502 / oxF1_oxF3 ox80_oxBF ox80_oxBF ox80_oxBF
503 / oxF0 ox90_0xBF ox80_oxBF ox80_oxBF
504 / oxEE_oxEF ox80_oxBF ox80_oxBF
505 / oxED ox80_ox9F ox80_oxBF
506 / oxE1_oxEC ox80_oxBF ox80_oxBF
507 / oxE0 oxA0_oxBF ox80_oxBF
508 / oxC2_oxDF ox80_oxBF
509
510# Exclude \177 which is DEL
511non_control_ascii <- [\040-\176]
512non_control_utf8 <- [\040-\176\200-\377]
513
514# XXX: the Zig tokenizer doesn't yet perform UTF-8 validation
515# When the tokenizer is fixed, switch back to these definitions
516# that forbid invalid UTF-8:
517#
518# char_char
519# <- multibyte_utf8
520# / "\\\\"
521# / "\\'"
522# / !['] non_control_ascii
523# string_char
524# <- multibyte_utf8
525# / '\\\\'
526# / '\\"'
527# / !["] non_control_ascii
528
529char_char
530 <- "\\\\"
531 / "\\'"
532 / !['] non_control_utf8
533
534string_char
535 <- '\\\\'
536 / '\\"'
537 / !["] non_control_utf8
538
539
540container_doc_comment <- (skip '//!' non_control_utf8* newline)+
541# We forbid same-line doc comments to disambiguate the mapping to e.g. struct
542# fields for documentation generation tooling.
543doc_comment <- (sof / skip_require_newline) (skip '///' non_control_utf8* newline)+
544line_comment
545 <- '//' ![!/] non_control_utf8* newline
546 / '////' non_control_utf8* newline
547line_string <- '\\\\' non_control_utf8* newline
548
549# This uses a positive lookahead rather than consuming input to make e.g.
550# the newline terminating a multiline string literal or doc comment visible
551# to the pre_op_white non-terminal.
552newline <- &("\n" / "\r\n" / eof)
553skip <- sof? ([ \n\t\r] / line_comment)*
554skip_require_newline <- [ \t\r]* ([\n] / line_comment) skip
555pre_op_white <- ([ \n\t\r] / line_comment)+
556post_op_white <- [ \n\t\r] skip
557
558CHAR_LITERAL <- skip ['] char_char* [']
559
560digit <- [_0-9A-DF-OQ-Za-df-oq-z]
561digit_int <- digit / [eEpP]
562digit_float <- digit / [eEpP] [-+]?
563NUMBERLITERAL
564 <- skip [0-9] digit_int* '.' digit_float+
565 / skip [0-9] digit_float*
566
567
568string <- ["] string_char* ["]
569STRINGLITERALSINGLE <- skip string
570STRINGLITERAL
571 <- skip string
572 / (skip line_string)+
573IDENTIFIER
574 <- skip !keyword [A-Za-z_] [A-Za-z0-9_]*
575 / skip '@' string
576BUILTINIDENTIFIER <- skip '@'[A-Za-z_][A-Za-z0-9_]*
577
578
579AMPERSAND <- skip '&' ![=]
580AMPERSANDEQUAL <- skip '&='
581ASTERISK <- skip '*' ![%=|]
582ASTERISKEQUAL <- skip '*='
583ASTERISKPERCENT <- skip '*%' ![=]
584ASTERISKPERCENTEQUAL <- skip '*%='
585ASTERISKPIPE <- skip '*|' ![=]
586ASTERISKPIPEEQUAL <- skip '*|='
587CARET <- skip '^' ![=]
588CARETEQUAL <- skip '^='
589COLON <- skip ':'
590COMMA <- skip ','
591DOT <- skip '.' ![*.]
592DOT2 <- skip '..' ![.]
593DOT3 <- skip '...'
594DOTASTERISK <- skip '.*'
595EQUAL <- skip '=' ![>=]
596EQUALEQUAL <- skip '=='
597EQUALRARROW <- skip '=>'
598EXCLAMATIONMARK <- skip '!' ![=]
599EXCLAMATIONMARKEQUAL <- skip '!='
600LARROW <- skip '<' ![<=]
601LARROW2 <- skip '<<' ![=|]
602LARROW2EQUAL <- skip '<<='
603LARROW2PIPE <- skip '<<|' ![=]
604LARROW2PIPEEQUAL <- skip '<<|='
605LARROWEQUAL <- skip '<='
606LBRACE <- skip '{'
607LBRACKET <- skip '['
608LPAREN <- skip '('
609MINUS <- skip '-' ![%=>|]
610MINUSEQUAL <- skip '-='
611MINUSPERCENT <- skip '-%' ![=]
612MINUSPERCENTEQUAL <- skip '-%='
613MINUSPIPE <- skip '-|' ![=]
614MINUSPIPEEQUAL <- skip '-|='
615MINUSRARROW <- skip '->'
616PERCENT <- skip '%' ![=]
617PERCENTEQUAL <- skip '%='
618PIPE <- skip '|' ![|=]
619PIPE2 <- skip '||'
620PIPEEQUAL <- skip '|='
621PLUS <- skip '+' ![%+=|]
622PLUS2 <- skip '++'
623PLUSEQUAL <- skip '+='
624PLUSPERCENT <- skip '+%' ![=]
625PLUSPERCENTEQUAL <- skip '+%='
626PLUSPIPE <- skip '+|' ![=]
627PLUSPIPEEQUAL <- skip '+|='
628LETTERC <- skip 'c'
629QUESTIONMARK <- skip '?'
630RARROW <- skip '>' ![>=]
631RARROW2 <- skip '>>' ![=]
632RARROW2EQUAL <- skip '>>='
633RARROWEQUAL <- skip '>='
634RBRACE <- skip '}'
635RBRACKET <- skip ']'
636RPAREN <- skip ')'
637SEMICOLON <- skip ';'
638SLASH <- skip '/' ![=/]
639SLASHEQUAL <- skip '/='
640TILDE <- skip '~'
641
642end_of_word <- ![a-zA-Z0-9_]
643KEYWORD_addrspace <- skip 'addrspace' end_of_word
644KEYWORD_align <- skip 'align' end_of_word
645KEYWORD_allowzero <- skip 'allowzero' end_of_word
646KEYWORD_and <- skip 'and' end_of_word
647KEYWORD_anyframe <- skip 'anyframe' end_of_word
648KEYWORD_anytype <- skip 'anytype' end_of_word
649KEYWORD_asm <- skip 'asm' end_of_word
650KEYWORD_break <- skip 'break' end_of_word
651KEYWORD_callconv <- skip 'callconv' end_of_word
652KEYWORD_catch <- skip 'catch' end_of_word
653KEYWORD_comptime <- skip 'comptime' end_of_word
654KEYWORD_const <- skip 'const' end_of_word
655KEYWORD_continue <- skip 'continue' end_of_word
656KEYWORD_defer <- skip 'defer' end_of_word
657KEYWORD_else <- skip 'else' end_of_word
658KEYWORD_enum <- skip 'enum' end_of_word
659KEYWORD_errdefer <- skip 'errdefer' end_of_word
660KEYWORD_error <- skip 'error' end_of_word
661KEYWORD_export <- skip 'export' end_of_word
662KEYWORD_extern <- skip 'extern' end_of_word
663KEYWORD_fn <- skip 'fn' end_of_word
664KEYWORD_for <- skip 'for' end_of_word
665KEYWORD_if <- skip 'if' end_of_word
666KEYWORD_inline <- skip 'inline' end_of_word
667KEYWORD_noalias <- skip 'noalias' end_of_word
668KEYWORD_nosuspend <- skip 'nosuspend' end_of_word
669KEYWORD_noinline <- skip 'noinline' end_of_word
670KEYWORD_opaque <- skip 'opaque' end_of_word
671KEYWORD_or <- skip 'or' end_of_word
672KEYWORD_orelse <- skip 'orelse' end_of_word
673KEYWORD_packed <- skip 'packed' end_of_word
674KEYWORD_pub <- skip 'pub' end_of_word
675KEYWORD_resume <- skip 'resume' end_of_word
676KEYWORD_return <- skip 'return' end_of_word
677KEYWORD_linksection <- skip 'linksection' end_of_word
678KEYWORD_struct <- skip 'struct' end_of_word
679KEYWORD_suspend <- skip 'suspend' end_of_word
680KEYWORD_switch <- skip 'switch' end_of_word
681KEYWORD_test <- skip 'test' end_of_word
682KEYWORD_threadlocal <- skip 'threadlocal' end_of_word
683KEYWORD_try <- skip 'try' end_of_word
684KEYWORD_union <- skip 'union' end_of_word
685KEYWORD_unreachable <- skip 'unreachable' end_of_word
686KEYWORD_var <- skip 'var' end_of_word
687KEYWORD_volatile <- skip 'volatile' end_of_word
688KEYWORD_while <- skip 'while' end_of_word
689
690keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and
691 / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm
692 / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch
693 / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue / KEYWORD_defer
694 / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export
695 / KEYWORD_extern / KEYWORD_fn / KEYWORD_for / KEYWORD_if
696 / KEYWORD_inline / KEYWORD_noalias / KEYWORD_nosuspend / KEYWORD_noinline
697 / KEYWORD_opaque / KEYWORD_or / KEYWORD_orelse / KEYWORD_packed
698 / KEYWORD_pub / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
699 / KEYWORD_struct / KEYWORD_suspend / KEYWORD_switch / KEYWORD_test
700 / KEYWORD_threadlocal / KEYWORD_try / KEYWORD_union / KEYWORD_unreachable
701 / KEYWORD_var / KEYWORD_volatile / KEYWORD_while