Skip to main content

cairo_lang_syntax_codegen/
cairo_spec.rs

1use crate::spec::{EnumBuilder, Node, NodesAggregator, StructBuilder};
2
3/// The syntax specification of Cairo.
4pub fn get_spec() -> Vec<Node> {
5    NodesAggregator::default()
6    .add_list("Trivia", "Trivium")
7    .add_enum(
8        EnumBuilder::new("Trivium")
9            .node_with_explicit_kind("SingleLineComment", "TokenSingleLineComment")
10            .node_with_explicit_kind("SingleLineDocComment", "TokenSingleLineDocComment")
11            .node_with_explicit_kind("SingleLineInnerComment", "TokenSingleLineInnerComment")
12            .node_with_explicit_kind("Whitespace", "TokenWhitespace")
13            .node_with_explicit_kind("Newline", "TokenNewline")
14            .node_with_explicit_kind("Skipped", "TokenSkipped")
15            .node("SkippedNode"),
16    )
17    // --- Expressions ---
18    .add_enum(EnumBuilder::new("Expr")
19        .include_missing()
20        .node("Path")
21        .node_with_explicit_kind("Literal", "TerminalLiteralNumber")
22        .node_with_explicit_kind("ShortString", "TerminalShortString")
23        .node_with_explicit_kind("String", "TerminalString")
24        .node_with_explicit_kind("False", "TerminalFalse")
25        .node_with_explicit_kind("True", "TerminalTrue")
26        .node("Parenthesized")
27        .node("Unary")
28        .node("Binary")
29        .node_with_explicit_kind("Tuple", "ExprListParenthesized")
30        .node("FunctionCall")
31        .node("StructCtorCall")
32        .node("Block")
33        .node("Match")
34        .node("If")
35        .node("Loop")
36        .node("While")
37        .node("For")
38        .node("Closure")
39        .node("ErrorPropagate")
40        .node("FieldInitShorthand")
41        .node("Indexed")
42        .node("InlineMacro")
43        .node("FixedSizeArray")
44        .node_with_explicit_kind("Underscore", "TerminalUnderscore")
45    )
46    .add_separated_list("ExprList", "Expr", "TerminalComma")
47    .add_struct(StructBuilder::new("Arg")
48        .node("modifiers", "ModifierList")
49        .node("arg_clause", "ArgClause")
50    )
51    .add_enum(EnumBuilder::new("ArgClause")
52        .node("Unnamed")
53        .node("Named")
54        .node("FieldInitShorthand")
55    )
56    .add_struct(StructBuilder::new("ArgClauseNamed")
57        .node("name", "TerminalIdentifier")
58        .node("colon", "TerminalColon")
59        .node("value", "Expr")
60    )
61    .add_struct(StructBuilder::new("ArgClauseUnnamed")
62        .node("value", "Expr")
63    )
64    .add_struct(StructBuilder::new("ArgClauseFieldInitShorthand")
65        .node("colon", "TerminalColon")
66        .node("name", "ExprFieldInitShorthand")
67    )
68    .add_struct(StructBuilder::new("ExprFieldInitShorthand")
69        .node("name", "TerminalIdentifier")
70    )
71    .add_separated_list("ArgList", "Arg", "TerminalComma")
72    .add_enum(EnumBuilder::new("PathSegment")
73        .node("Simple")
74        .node("WithGenericArgs")
75    )
76    .add_struct(StructBuilder::new("PathSegmentSimple").node("ident", "TerminalIdentifier"))
77    .add_option("TerminalColonColon")
78    .add_struct(StructBuilder::new("PathSegmentWithGenericArgs")
79        .node("ident", "TerminalIdentifier")
80        .node("separator", "OptionTerminalColonColon")
81        .node("generic_args", "GenericArgs")
82    )
83    .add_struct(StructBuilder::new("ExprPath")
84        .node("dollar", "OptionTerminalDollar")
85        .node("segments", "ExprPathInner")
86    )
87    .add_option("TerminalDollar")
88    .add_separated_list("ExprPathInner", "PathSegment", "TerminalColonColon")
89    .add_struct(StructBuilder::new("ExprParenthesized")
90        .node("lparen", "TerminalLParen")
91        .node("expr", "Expr")
92        .node("rparen", "TerminalRParen")
93    )
94    .add_struct(StructBuilder::new("ExprUnary").node("op", "UnaryOperator").node("expr", "Expr"))
95    .add_enum(EnumBuilder::new("UnaryOperator")
96        .node_with_explicit_kind("Not", "TerminalNot")
97        .node_with_explicit_kind("BitNot", "TerminalBitNot")
98        .node_with_explicit_kind("Minus", "TerminalMinus")
99        .node_with_explicit_kind("At", "TerminalAt")
100        .node_with_explicit_kind("Desnap", "TerminalMul")
101        .node_with_explicit_kind("Reference", "TerminalAnd")
102    )
103    .add_struct(StructBuilder::new("ExprBinary")
104        .node("lhs", "Expr")
105        .node("op", "BinaryOperator")
106        .node("rhs", "Expr")
107    )
108    .add_enum(EnumBuilder::new("BinaryOperator")
109        .node_with_explicit_kind("Dot", "TerminalDot")
110        .node_with_explicit_kind("Not", "TerminalNot")
111        .node_with_explicit_kind("Mul", "TerminalMul")
112        .node_with_explicit_kind("MulEq", "TerminalMulEq")
113        .node_with_explicit_kind("Div", "TerminalDiv")
114        .node_with_explicit_kind("DivEq", "TerminalDivEq")
115        .node_with_explicit_kind("Mod", "TerminalMod")
116        .node_with_explicit_kind("ModEq", "TerminalModEq")
117        .node_with_explicit_kind("Plus", "TerminalPlus")
118        .node_with_explicit_kind("PlusEq", "TerminalPlusEq")
119        .node_with_explicit_kind("Minus", "TerminalMinus")
120        .node_with_explicit_kind("MinusEq", "TerminalMinusEq")
121        .node_with_explicit_kind("EqEq", "TerminalEqEq")
122        .node_with_explicit_kind("Neq", "TerminalNeq")
123        .node_with_explicit_kind("Eq", "TerminalEq")
124        .node_with_explicit_kind("And", "TerminalAnd")
125        .node_with_explicit_kind("AndAnd", "TerminalAndAnd")
126        .node_with_explicit_kind("Or", "TerminalOr")
127        .node_with_explicit_kind("OrOr", "TerminalOrOr")
128        .node_with_explicit_kind("Xor", "TerminalXor")
129        .node_with_explicit_kind("LE", "TerminalLE")
130        .node_with_explicit_kind("GE", "TerminalGE")
131        .node_with_explicit_kind("LT", "TerminalLT")
132        .node_with_explicit_kind("GT", "TerminalGT")
133        .node_with_explicit_kind("DotDot", "TerminalDotDot")
134        .node_with_explicit_kind("DotDotEq", "TerminalDotDotEq")
135    )
136    .add_struct(StructBuilder::new("ExprListParenthesized")
137        .node("lparen", "TerminalLParen")
138        .node("expressions", "ExprList")
139        .node("rparen", "TerminalRParen")
140    )
141    .add_struct(StructBuilder::new("ExprFunctionCall")
142        .node("path", "ExprPath")
143        .node("arguments", "ArgListParenthesized")
144    )
145    .add_struct(StructBuilder::new("ArgListParenthesized")
146        .node("lparen", "TerminalLParen")
147        .node("arguments", "ArgList")
148        .node("rparen", "TerminalRParen")
149    )
150    .add_option("ArgListParenthesized")
151    .add_struct(StructBuilder::new("ExprStructCtorCall")
152        .node("path", "ExprPath")
153        .node("arguments", "StructArgListBraced")
154    )
155    .add_struct(StructBuilder::new("StructArgListBraced")
156        .node("lbrace", "TerminalLBrace")
157        .node("arguments", "StructArgList")
158        .node("rbrace", "TerminalRBrace")
159    )
160    .add_struct(StructBuilder::new("ExprBlock")
161        .node("lbrace", "TerminalLBrace")
162        .node("statements", "StatementList")
163        .node("rbrace", "TerminalRBrace")
164    )
165    .add_struct(StructBuilder::new("ExprMatch")
166        .node("match_kw", "TerminalMatch")
167        // TODO(yuval): change to SimpleExpr
168        .node("expr", "Expr")
169        .node("lbrace", "TerminalLBrace")
170        .node("arms", "MatchArms")
171        .node("rbrace", "TerminalRBrace")
172    )
173    .add_separated_list("MatchArms", "MatchArm", "TerminalComma")
174    .add_struct(StructBuilder::new("MatchArm")
175        .node("patterns", "PatternListOr")
176        .node("arrow", "TerminalMatchArrow")
177        .node("expression", "Expr")
178    )
179    .add_struct(StructBuilder::new("ExprIf")
180        .node("if_kw", "TerminalIf")
181        .node("conditions", "ConditionListAnd")
182        .node("if_block", "ExprBlock")
183        .node("else_clause", "OptionElseClause")
184    )
185    .add_separated_list("ConditionListAnd", "Condition", "TerminalAndAnd")
186    .add_enum(EnumBuilder::new("Condition")
187        .node("Let")
188        .node("Expr")
189    )
190    .add_struct(StructBuilder::new("ConditionLet")
191        .node("let_kw", "TerminalLet")
192        .node("patterns", "PatternListOr")
193        .node("eq", "TerminalEq")
194        .node("expr", "Expr")
195    )
196    .add_struct(StructBuilder::new("ConditionExpr")
197        .node("expr", "Expr")
198    )
199    .add_enum(EnumBuilder::new("BlockOrIf")
200        .node_with_explicit_kind("Block", "ExprBlock")
201        .node_with_explicit_kind("If", "ExprIf")
202    )
203    .add_struct(StructBuilder::new("ExprLoop")
204        .node("loop_kw", "TerminalLoop")
205        .node("body", "ExprBlock")
206    )
207    .add_struct(StructBuilder::new("ExprWhile")
208        .node("while_kw", "TerminalWhile")
209        .node("conditions", "ConditionListAnd")
210        .node("body", "ExprBlock")
211    )
212    .add_struct(StructBuilder::new("ExprFor")
213        .node("for_kw", "TerminalFor")
214        .key_node("pattern", "Pattern")
215        .key_node("identifier", "TerminalIdentifier")
216        .node("expr", "Expr")
217        .node("body", "ExprBlock")
218    )
219    .add_struct(StructBuilder::new("ElseClause")
220        .node("else_kw", "TerminalElse")
221        .node("else_block_or_if", "BlockOrIf")
222    )
223    .add_option("ElseClause")
224    .add_struct(StructBuilder::new("ExprErrorPropagate").node("expr", "Expr").node("op", "TerminalQuestionMark"))
225    .add_struct(StructBuilder::new("ExprIndexed")
226        .node("expr", "Expr")
227        .node("lbrack", "TerminalLBrack")
228        .node("index_expr", "Expr")
229        .node("rbrack", "TerminalRBrack")
230    )
231    .add_struct(StructBuilder::new("ExprFixedSizeArray")
232        .node("lbrack", "TerminalLBrack")
233        .node("exprs", "ExprList")
234        .node("size", "OptionFixedSizeArraySize")
235        .node("rbrack", "TerminalRBrack")
236    )
237    .add_struct(StructBuilder::new("FixedSizeArraySize")
238        .node("semicolon", "TerminalSemicolon")
239        .node("size", "Expr")
240    )
241    .add_option("FixedSizeArraySize")
242    .add_struct(StructBuilder::new("ExprClosure")
243        .node("params", "ClosureParams")
244        .node("ret_ty", "OptionReturnTypeClause")
245        .node("optional_no_panic", "OptionTerminalNoPanic")
246        .node("expr", "Expr")
247    )
248    .add_struct(StructBuilder::new("ClosureParams")
249        .node("leftor","TerminalOr")
250        .node("params", "ParamList")
251        .node("rightor", "TerminalOr")
252    )
253    // --- Struct ctor ---
254    .add_struct(StructBuilder::new("StructArgExpr")
255        .node("colon", "TerminalColon")
256        .node("expr", "Expr")
257    )
258    .add_option("StructArgExpr")
259    .add_struct(StructBuilder::new("StructArgSingle")
260        .key_node("identifier", "TerminalIdentifier")
261        .node("arg_expr", "OptionStructArgExpr")
262    )
263    .add_struct(StructBuilder::new("StructArgTail")
264        .node("dotdot", "TerminalDotDot")
265        .node("expression", "Expr")
266    )
267    .add_enum(EnumBuilder::new("StructArg")
268        .node_with_explicit_kind("StructArgSingle", "StructArgSingle")
269        .node_with_explicit_kind("StructArgTail", "StructArgTail")
270    )
271    .add_separated_list("StructArgList", "StructArg", "TerminalComma")
272    .add_struct(StructBuilder::new("ArgListBraced")
273        .node("lbrace", "TerminalLBrace")
274        .node("arguments", "ArgList")
275        .node("rbrace", "TerminalRBrace")
276    )
277    .add_struct(StructBuilder::new("ArgListBracketed")
278        .node("lbrack", "TerminalLBrack")
279        .node("arguments", "ArgList")
280        .node("rbrack", "TerminalRBrack")
281    )
282    .add_enum(EnumBuilder::new("WrappedArgList")
283        .include_missing()
284        .node_with_explicit_kind("BracketedArgList", "ArgListBracketed")
285        .node_with_explicit_kind("ParenthesizedArgList", "ArgListParenthesized")
286        .node_with_explicit_kind("BracedArgList", "ArgListBraced")
287    )
288    // ---Patterns ---
289    .add_enum(EnumBuilder::new("Pattern")
290        .node_with_explicit_kind("Underscore", "TerminalUnderscore")
291        .node_with_explicit_kind("Literal", "TerminalLiteralNumber")
292        .node_with_explicit_kind("False", "TerminalFalse")
293        .node_with_explicit_kind("True", "TerminalTrue")
294        .node_with_explicit_kind("ShortString", "TerminalShortString")
295        .node_with_explicit_kind("String", "TerminalString")
296        .node("Identifier")
297        .node("Struct")
298        .node("Tuple")
299        .node("Enum")
300        .node("FixedSizeArray")
301        .node_with_explicit_kind("Path", "ExprPath")
302    )
303    .add_struct(StructBuilder::new("PatternIdentifier")
304        .node("modifiers", "ModifierList")
305        .key_node("name", "TerminalIdentifier")
306    )
307    .add_struct(StructBuilder::new("PatternStruct")
308        // TODO(spapini): Use SimplePath instead - which is not an expr.
309        .node("path", "ExprPath")
310        .node("lbrace", "TerminalLBrace")
311        .node("params", "PatternStructParamList")
312        .node("rbrace", "TerminalRBrace")
313    )
314    .add_separated_list("PatternStructParamList", "PatternStructParam", "TerminalComma")
315    .add_struct(StructBuilder::new("PatternTuple")
316        .node("lparen", "TerminalLParen")
317        .node("patterns", "PatternList")
318        .node("rparen", "TerminalRParen")
319    )
320    .add_struct(StructBuilder::new("PatternFixedSizeArray")
321        .node("lbrack", "TerminalLBrack")
322        .node("patterns", "PatternList")
323        .node("rbrack", "TerminalRBrack"))
324    .add_separated_list("PatternList", "Pattern", "TerminalComma")
325    .add_separated_list("PatternListOr", "Pattern", "TerminalOr")
326    .add_enum(EnumBuilder::new("PatternStructParam")
327        .node_with_explicit_kind("Single", "PatternIdentifier")
328        .node("WithExpr")
329        .node_with_explicit_kind("Tail", "TerminalDotDot")
330    )
331    .add_struct(StructBuilder::new("PatternStructParamWithExpr")
332        .node("modifiers", "ModifierList")
333        .node("name", "TerminalIdentifier")
334        .node("colon", "TerminalColon")
335        .node("pattern", "Pattern")
336    )
337    .add_struct(StructBuilder::new("PatternEnum")
338        .node("path", "ExprPath")
339        .node("pattern", "OptionPatternEnumInnerPattern")
340    )
341    .add_struct(StructBuilder::new("PatternEnumInnerPattern")
342        .node("lparen", "TerminalLParen")
343        .node("pattern", "Pattern")
344        .node("rparen", "TerminalRParen")
345    )
346    .add_option("PatternEnumInnerPattern")
347    // --- Type clauses ---
348    // TODO(yuval): support SimpleExpr instead of Expr
349    .add_struct(StructBuilder::new("TypeClause").node("colon", "TerminalColon").node("ty", "Expr"))
350    .add_option("TypeClause")
351    .add_struct(StructBuilder::new("ReturnTypeClause")
352        .node("arrow", "TerminalArrow")
353        .node("ty", "Expr")
354    )
355    .add_option("ReturnTypeClause")
356    // --- Statements ---
357    .add_enum(EnumBuilder::new("Statement")
358        .include_missing()
359        .node("Let")
360        .node("Expr")
361        .node("Continue")
362        .node("Return")
363        .node("Break")
364        .node("Item")
365    )
366    .add_list("StatementList", "Statement")
367    .add_struct(StructBuilder::new("StatementLet")
368        .node("attributes" ,"AttributeList")
369        .node("let_kw", "TerminalLet")
370        .key_node("pattern", "Pattern")
371        .node("type_clause", "OptionTypeClause")
372        .node("eq", "TerminalEq")
373        .node("rhs", "Expr")
374        .node("let_else_clause", "OptionLetElseClause")
375        .node("semicolon", "TerminalSemicolon")
376    )
377    .add_struct(StructBuilder::new("LetElseClause")
378        .node("else_kw", "TerminalElse")
379        .node("else_block", "ExprBlock")
380    )
381    .add_option("LetElseClause")
382    .add_option("TerminalSemicolon")
383    .add_struct(StructBuilder::new("StatementExpr")
384        .node("attributes" ,"AttributeList")
385        .node("expr", "Expr")
386        .node("semicolon", "OptionTerminalSemicolon")
387    )
388    .add_struct(StructBuilder::new("StatementContinue")
389        .node("attributes" ,"AttributeList")
390        .node("continue_kw", "TerminalContinue")
391        .node("semicolon", "TerminalSemicolon")
392    )
393    .add_struct(StructBuilder::new("ExprClause")
394        .node("expr", "Expr"))
395    .add_option("ExprClause")
396    .add_struct(StructBuilder::new("StatementReturn")
397        .node("attributes" ,"AttributeList")
398        .node("return_kw", "TerminalReturn")
399        .node("expr_clause", "OptionExprClause")
400        .node("semicolon", "TerminalSemicolon")
401    )
402    .add_struct(StructBuilder::new("StatementBreak")
403        .node("attributes" ,"AttributeList")
404        .node("break_kw", "TerminalBreak")
405        .node("expr_clause", "OptionExprClause")
406        .node("semicolon", "TerminalSemicolon")
407    )
408    .add_struct(StructBuilder::new("StatementItem")
409        .node("item", "ModuleItem")
410    )
411    // --- Functions ---
412    .add_struct(StructBuilder::new("Param")
413        .node("modifiers", "ModifierList")
414        .key_node("name", "TerminalIdentifier")
415        .node("type_clause", "OptionTypeClause")
416    )
417    .add_list("ModifierList", "Modifier")
418    .add_enum(EnumBuilder::new("Modifier")
419        .node_with_explicit_kind("Ref", "TerminalRef")
420        .node_with_explicit_kind("Mut", "TerminalMut")
421    )
422    .add_separated_list("ParamList", "Param", "TerminalComma")
423    .add_struct(StructBuilder::new("ImplicitsClause")
424        .node("implicits_kw", "TerminalImplicits")
425        .node("lparen", "TerminalLParen")
426        .node("implicits", "ImplicitsList")
427        .node("rparen", "TerminalRParen")
428    )
429    .add_separated_list("ImplicitsList", "ExprPath", "TerminalComma")
430    .add_option("ImplicitsClause")
431    .add_option("TerminalNoPanic")
432    .add_option("TerminalConst")
433    // TODO(spapini): Add generic params.
434    // This is an unnamed signature, e.g. "() -> Type".
435    .add_struct(StructBuilder::new("FunctionSignature")
436        .node("lparen", "TerminalLParen")
437        .node("parameters", "ParamList")
438        .node("rparen", "TerminalRParen")
439        .node("ret_ty", "OptionReturnTypeClause")
440        .node("implicits_clause", "OptionImplicitsClause")
441        .node("optional_no_panic", "OptionTerminalNoPanic")
442    )
443    // --- Struct Members ---
444    // Struct member and enum variant have the same structure.
445    .add_struct(StructBuilder::new("Member")
446        .node("attributes" ,"AttributeList")
447        .node("visibility", "Visibility")
448        .key_node("name", "TerminalIdentifier")
449        .node("type_clause", "TypeClause")
450    )
451    .add_separated_list("MemberList", "Member", "TerminalComma")
452    .add_struct(StructBuilder::new("Variant")
453        .node("attributes" ,"AttributeList")
454        .key_node("name", "TerminalIdentifier")
455        .node("type_clause", "OptionTypeClause")
456    )
457    .add_separated_list("VariantList", "Variant", "TerminalComma")
458    // --- Items ---
459    .add_enum(EnumBuilder::new("ModuleItem")
460        .include_missing()
461        .node_with_explicit_kind("Constant", "ItemConstant")
462        .node_with_explicit_kind("Module", "ItemModule")
463        .node_with_explicit_kind("Use", "ItemUse")
464        .node_with_explicit_kind("FreeFunction", "FunctionWithBody")
465        .node_with_explicit_kind("ExternFunction", "ItemExternFunction")
466        .node_with_explicit_kind("ExternType", "ItemExternType")
467        .node_with_explicit_kind("Trait", "ItemTrait")
468        .node_with_explicit_kind("Impl", "ItemImpl")
469        .node_with_explicit_kind("ImplAlias", "ItemImplAlias")
470        .node_with_explicit_kind("Struct", "ItemStruct")
471        .node_with_explicit_kind("Enum", "ItemEnum")
472        .node_with_explicit_kind("TypeAlias", "ItemTypeAlias")
473        .node_with_explicit_kind("InlineMacro", "ItemInlineMacro")
474        .node_with_explicit_kind("MacroDeclaration", "ItemMacroDeclaration")
475        .node_with_explicit_kind("HeaderDoc", "ItemHeaderDoc")
476    )
477    .add_list("ModuleItemList", "ModuleItem")
478    .add_struct(StructBuilder::new("Attribute")
479        .node("hash", "TerminalHash")
480        .node("lbrack", "TerminalLBrack")
481        .node("attr", "ExprPath")
482        .node("arguments", "OptionArgListParenthesized")
483        .node("rbrack", "TerminalRBrack")
484    )
485    .add_list("AttributeList", "Attribute")
486    .add_struct(StructBuilder::new("VisibilityDefault"))
487    .add_struct(StructBuilder::new("VisibilityPubArgumentClause")
488        .node("lparen", "TerminalLParen")
489        .node("argument", "TerminalIdentifier")
490        .node("rparen", "TerminalRParen")
491    )
492    .add_option("VisibilityPubArgumentClause")
493    .add_struct(StructBuilder::new("VisibilityPub")
494        .node("pub_kw", "TerminalPub")
495        .node("argument_clause", "OptionVisibilityPubArgumentClause")
496    )
497    .add_enum(EnumBuilder::new("Visibility")
498        .node("Default")
499        .node("Pub")
500    )
501    .add_struct(StructBuilder::new("ItemModule")
502        .node("attributes" ,"AttributeList")
503        .node("visibility", "Visibility")
504        .node("module_kw", "TerminalModule")
505        .key_node("name", "TerminalIdentifier")
506        .node("body", "MaybeModuleBody")
507    )
508    .add_enum(EnumBuilder::new("MaybeModuleBody")
509        .node_with_explicit_kind("Some", "ModuleBody")
510        .node_with_explicit_kind("None", "TerminalSemicolon")
511    )
512    .add_struct(StructBuilder::new("ModuleBody")
513        .node("lbrace", "TerminalLBrace")
514        .node("items", "ModuleItemList")
515        .node("rbrace", "TerminalRBrace")
516    )
517    .add_struct(StructBuilder::new("FunctionDeclaration")
518        .node("optional_const", "OptionTerminalConst")
519        .node("function_kw", "TerminalFunction")
520        .key_node("name", "TerminalIdentifier")
521        .node("generic_params", "OptionWrappedGenericParamList")
522        .node("signature", "FunctionSignature")
523    )
524    .add_struct(StructBuilder::new("ItemConstant")
525        .node("attributes" ,"AttributeList")
526        .node("visibility", "Visibility")
527        .node("const_kw", "TerminalConst")
528        .key_node("name", "TerminalIdentifier")
529        .node("type_clause", "TypeClause")
530        .node("eq", "TerminalEq")
531        .node("value", "Expr")
532        .node("semicolon", "TerminalSemicolon")
533    )
534    .add_struct(StructBuilder::new("FunctionWithBody")
535        .node("attributes" ,"AttributeList")
536        .node("visibility", "Visibility")
537         // TODO(ilya): Use only the name as key node.
538        .key_node("declaration", "FunctionDeclaration")
539        .node("body", "ExprBlock")
540    )
541    .add_struct(StructBuilder::new("ItemExternFunction")
542        .node("attributes" ,"AttributeList")
543        .node("visibility", "Visibility")
544        .node("extern_kw", "TerminalExtern")
545         // TODO(ilya): Use only the name as key node.
546        .key_node("declaration", "FunctionDeclaration")
547        .node("semicolon", "TerminalSemicolon")
548    )
549    .add_struct(StructBuilder::new("ItemExternType")
550        .node("attributes" ,"AttributeList")
551        .node("visibility", "Visibility")
552        .node("extern_kw", "TerminalExtern")
553        .node("type_kw", "TerminalType")
554        .key_node("name", "TerminalIdentifier")
555        .node("generic_params", "OptionWrappedGenericParamList")
556        .node("semicolon", "TerminalSemicolon")
557    )
558    .add_struct(StructBuilder::new("ItemTrait")
559        .node("attributes" ,"AttributeList")
560        .node("visibility", "Visibility")
561        .node("trait_kw", "TerminalTrait")
562        .key_node("name", "TerminalIdentifier")
563        .node("generic_params", "OptionWrappedGenericParamList")
564        .node("body", "MaybeTraitBody")
565    )
566    .add_enum(EnumBuilder::new("MaybeTraitBody")
567        .node_with_explicit_kind("Some", "TraitBody")
568        .node_with_explicit_kind("None", "TerminalSemicolon")
569    )
570    .add_struct(StructBuilder::new("TraitBody")
571        .node("lbrace", "TerminalLBrace")
572        .node("items", "TraitItemList")
573        .node("rbrace", "TerminalRBrace")
574    )
575    .add_list("TraitItemList", "TraitItem")
576    .add_enum(EnumBuilder::new("TraitItem")
577        .include_missing()
578        .node("Function")
579        .node("Type")
580        .node("Constant")
581        .node("Impl")
582    )
583    .add_struct(StructBuilder::new("TraitItemFunction")
584        .node("attributes" ,"AttributeList")
585         // TODO(ilya): Use only the name as key node.
586        .key_node("declaration", "FunctionDeclaration")
587        .node("body", "MaybeTraitFunctionBody")
588    )
589    .add_struct(StructBuilder::new("TraitItemType")
590        .node("attributes" ,"AttributeList")
591        .node("type_kw", "TerminalType")
592        .key_node("name", "TerminalIdentifier")
593        .node("generic_params", "OptionWrappedGenericParamList")
594        .node("semicolon", "TerminalSemicolon")
595    )
596    .add_struct(StructBuilder::new("TraitItemConstant")
597        .node("attributes" ,"AttributeList")
598        .node("const_kw", "TerminalConst")
599        .key_node("name", "TerminalIdentifier")
600        .node("type_clause", "TypeClause")
601        .node("semicolon", "TerminalSemicolon")
602    )
603    .add_struct(StructBuilder::new("TraitItemImpl")
604        .node("attributes" ,"AttributeList")
605        .node("impl_kw", "TerminalImpl")
606        .key_node("name", "TerminalIdentifier")
607        .node("colon", "TerminalColon")
608        .node("trait_path", "ExprPath")
609        .node("semicolon", "TerminalSemicolon")
610    )
611    .add_enum(EnumBuilder::new("MaybeTraitFunctionBody")
612        .node_with_explicit_kind("Some", "ExprBlock")
613        .node_with_explicit_kind("None", "TerminalSemicolon")
614    )
615    .add_struct(StructBuilder::new("ItemImpl")
616        .node("attributes" ,"AttributeList")
617        .node("visibility", "Visibility")
618        .node("impl_kw", "TerminalImpl")
619        .key_node("name", "TerminalIdentifier")
620        .node("generic_params", "OptionWrappedGenericParamList")
621        .node("of_kw", "TerminalOf")
622        .node("trait_path", "ExprPath")
623        .node("body", "MaybeImplBody")
624    )
625    // Empty struct, which is used for separating the first comments in a file or module from the
626    // rest of the items. This is needed to prevent the first comments from being moved by the
627    // formatter.
628    .add_struct(StructBuilder::new("ItemHeaderDoc")
629        .node("empty", "TerminalEmpty"))
630    .add_enum(EnumBuilder::new("MaybeImplBody")
631        .node_with_explicit_kind("Some", "ImplBody")
632        .node_with_explicit_kind("None", "TerminalSemicolon")
633    )
634    .add_struct(StructBuilder::new("ImplBody")
635            .node("lbrace", "TerminalLBrace")
636            .node("items", "ImplItemList")
637            .node("rbrace", "TerminalRBrace")
638    )
639    .add_list("ImplItemList", "ImplItem")
640    .add_enum(EnumBuilder::new("ImplItem")
641        .include_missing()
642        .node_with_explicit_kind("Function", "FunctionWithBody")
643        .node_with_explicit_kind("Type", "ItemTypeAlias")
644        .node_with_explicit_kind("Constant", "ItemConstant")
645        .node_with_explicit_kind("Impl", "ItemImplAlias")
646        // These are not supported semantically.
647        .node_with_explicit_kind("Module", "ItemModule")
648        .node_with_explicit_kind("Use", "ItemUse")
649        .node_with_explicit_kind("ExternFunction", "ItemExternFunction")
650        .node_with_explicit_kind("ExternType", "ItemExternType")
651        .node_with_explicit_kind("Trait", "ItemTrait")
652        .node_with_explicit_kind("Struct", "ItemStruct")
653        .node_with_explicit_kind("Enum", "ItemEnum")
654    )
655    .add_struct(StructBuilder::new("ItemImplAlias")
656        .node("attributes" ,"AttributeList")
657        .node("visibility", "Visibility")
658        .node("impl_kw", "TerminalImpl")
659        .key_node("name", "TerminalIdentifier")
660        .node("generic_params", "OptionWrappedGenericParamList")
661        .node("eq", "TerminalEq")
662        .node("impl_path", "ExprPath")
663        .node("semicolon", "TerminalSemicolon")
664    )
665    .add_struct(StructBuilder::new("ItemStruct")
666        .node("attributes" ,"AttributeList")
667        .node("visibility", "Visibility")
668        .node("struct_kw", "TerminalStruct")
669        .key_node("name", "TerminalIdentifier")
670        .node("generic_params", "OptionWrappedGenericParamList")
671        .node("lbrace", "TerminalLBrace")
672        .node("members", "MemberList")
673        .node("rbrace", "TerminalRBrace")
674    )
675    .add_struct(StructBuilder::new("ItemEnum")
676        .node("attributes" ,"AttributeList")
677        .node("visibility", "Visibility")
678        .node("enum_kw", "TerminalEnum")
679        .key_node("name", "TerminalIdentifier")
680        .node("generic_params", "OptionWrappedGenericParamList")
681        .node("lbrace", "TerminalLBrace")
682        .node("variants", "VariantList")
683        .node("rbrace", "TerminalRBrace")
684    )
685    .add_struct(StructBuilder::new("ItemTypeAlias")
686        .node("attributes" ,"AttributeList")
687        .node("visibility", "Visibility")
688        .node("type_kw", "TerminalType")
689        .key_node("name", "TerminalIdentifier")
690        .node("generic_params", "OptionWrappedGenericParamList")
691        .node("eq", "TerminalEq")
692        .node("ty", "Expr")
693        .node("semicolon", "TerminalSemicolon")
694    )
695    .add_struct(StructBuilder::new("ItemUse")
696        .node("attributes" ,"AttributeList")
697        .node("visibility", "Visibility")
698        .node("use_kw", "TerminalUse")
699        .node("dollar", "OptionTerminalDollar")
700        .key_node("use_path", "UsePath")
701        .node("semicolon", "TerminalSemicolon")
702    )
703    .add_enum(
704        EnumBuilder::new("UsePath")
705        .node("Leaf")
706        .node("Single")
707        .node("Multi")
708        .node("Star")
709    )
710    .add_struct(StructBuilder::new("UsePathLeaf")
711        .key_node("ident", "PathSegment")
712        .key_node("alias_clause", "OptionAliasClause")
713    )
714    .add_struct(StructBuilder::new("UsePathSingle")
715        .node("ident", "PathSegment")
716        .node("colon_colon", "TerminalColonColon")
717        .node("use_path", "UsePath")
718    )
719    .add_struct(StructBuilder::new("UsePathMulti")
720        .node("lbrace", "TerminalLBrace")
721        .node("use_paths", "UsePathList")
722        .node("rbrace", "TerminalRBrace")
723    )
724    .add_struct(StructBuilder::new("UsePathStar")
725        .node("star", "TerminalMul")
726    )
727    .add_separated_list("UsePathList", "UsePath", "TerminalComma")
728    .add_struct(StructBuilder::new("AliasClause")
729        .node("as_kw", "TerminalAs")
730        .key_node("alias", "TerminalIdentifier")
731    )
732    .add_option("AliasClause")
733    // --- Generics ---
734    .add_enum(
735        EnumBuilder::new("GenericArg")
736        .node("Unnamed")
737        .node("Named")
738    )
739    .add_struct(StructBuilder::new("GenericArgNamed")
740        .node("name", "TerminalIdentifier")
741        .node("colon", "TerminalColon")
742        .node("value", "Expr")
743    )
744    .add_struct(StructBuilder::new("GenericArgUnnamed")
745        .node("value", "Expr")
746    )
747    .add_struct(StructBuilder::new("GenericArgs")
748        .node("langle", "TerminalLT")
749        .node("generic_args", "GenericArgList")
750        .node("rangle", "TerminalGT")
751    )
752    .add_separated_list("GenericArgList", "GenericArg", "TerminalComma")
753    .add_struct(
754        StructBuilder::new("AssociatedItemConstraint")
755        .node("item","TerminalIdentifier")
756        .node("colon","TerminalColon")
757        .node("value","Expr")
758    )
759    .add_struct(StructBuilder::new("AssociatedItemConstraints")
760        .node("lbrack", "TerminalLBrack")
761        .node("associated_item_constraints", "AssociatedItemConstraintList")
762        .node("rbrack", "TerminalRBrack")
763    )
764    .add_separated_list("AssociatedItemConstraintList", "AssociatedItemConstraint", "TerminalComma")
765    .add_option("AssociatedItemConstraints")
766    .add_option("WrappedGenericParamList")
767    .add_struct(StructBuilder::new("WrappedGenericParamList")
768        .node("langle", "TerminalLT")
769        .node("generic_params", "GenericParamList")
770        .node("rangle", "TerminalGT")
771    )
772    .add_separated_list("GenericParamList", "GenericParam", "TerminalComma")
773    // TODO(spapini): Remove this indirection.
774    .add_enum(EnumBuilder::new("GenericParam")
775        .node("Type")
776        .node("Const")
777        .node("ImplNamed")
778        .node("ImplAnonymous")
779        .node("NegativeImpl")
780    )
781    .add_struct(StructBuilder::new("GenericParamType")
782        .key_node("name", "TerminalIdentifier")
783    )
784    .add_struct(StructBuilder::new("GenericParamConst")
785        .node("const_kw", "TerminalConst")
786        .key_node("name", "TerminalIdentifier")
787        .node("colon", "TerminalColon")
788        .node("ty", "Expr")
789    )
790    .add_struct(StructBuilder::new("GenericParamImplNamed")
791        .node("impl_kw", "TerminalImpl")
792        .key_node("name", "TerminalIdentifier")
793        .node("colon", "TerminalColon")
794        .node("trait_path", "ExprPath")
795        .node("type_constrains", "OptionAssociatedItemConstraints")
796    )
797    .add_struct(StructBuilder::new("GenericParamImplAnonymous")
798        .node("plus", "TerminalPlus")
799        .node("trait_path", "ExprPath")
800        .node("type_constrains", "OptionAssociatedItemConstraints")
801    )
802    .add_struct(StructBuilder::new("GenericParamNegativeImpl")
803        .node("minus", "TerminalMinus")
804        .node("trait_path", "ExprPath")
805    )
806    // --- Macros ---
807    // The structure of a token tree is:
808    // TokenTree: TokenNode | WrappedTokenTree
809    // Where WrappedTokenTree is:
810    // WrappedTokenTree: (TokenTree*) | {TokenTree*} | [TokenTree*]
811    // TokenTree* is represented as TokenList.
812    .add_list("TokenList", "TokenTree")
813    .add_struct(StructBuilder::new("TokenTreeLeaf")
814        .node("leaf", "TokenNode")
815    )
816    .add_struct(StructBuilder::new("TokenTreeNode")
817        .node("subtree", "WrappedTokenTree")
818    )
819    // TODO(Dean): Remove TokenTreeRepetition and TokenTreeParam (it's redundant).
820    .add_struct(StructBuilder::new("TokenTreeRepetition")
821        .node("dollar", "TerminalDollar")
822        .node("lparen", "TerminalLParen")
823        .node("elements", "TokenList")
824        .node("rparen", "TerminalRParen")
825        .node("separator", "OptionTerminalComma")
826        .node("operator", "MacroRepetitionOperator")
827    )
828    .add_struct(StructBuilder::new("TokenTreeParam")
829        .node("dollar", "TerminalDollar")
830        .node("name", "TerminalIdentifier")
831    )
832    .add_enum(EnumBuilder::new("TokenTree")
833        .include_missing()
834        .node_with_explicit_kind("Token", "TokenTreeLeaf")
835        .node_with_explicit_kind("Subtree", "TokenTreeNode")
836        .node_with_explicit_kind("Repetition", "TokenTreeRepetition")
837        .node_with_explicit_kind("Param", "TokenTreeParam")
838    )
839    .add_enum(EnumBuilder::new("WrappedTokenTree")
840        .include_missing()
841        .node_with_explicit_kind("Parenthesized", "ParenthesizedTokenTree")
842        .node_with_explicit_kind("Braced", "BracedTokenTree")
843        .node_with_explicit_kind("Bracketed", "BracketedTokenTree")
844    )
845    .add_struct(StructBuilder::new("ParenthesizedTokenTree")
846        .node("lparen", "TerminalLParen")
847        .node("tokens", "TokenList")
848        .node("rparen", "TerminalRParen")
849    )
850    .add_struct(StructBuilder::new("BracedTokenTree")
851        .node("lbrace", "TerminalLBrace")
852        .node("tokens", "TokenList")
853        .node("rbrace", "TerminalRBrace")
854    )
855    .add_struct(StructBuilder::new("BracketedTokenTree")
856        .node("lbrack", "TerminalLBrack")
857        .node("tokens", "TokenList")
858        .node("rbrack", "TerminalRBrack")
859    )
860    .add_struct(StructBuilder::new("ExprInlineMacro")
861        .node("path", "ExprPath")
862        .node("bang", "TerminalNot")
863        .node("arguments", "TokenTreeNode")
864    )
865    .add_struct(StructBuilder::new("ItemInlineMacro")
866    .node("attributes" ,"AttributeList")
867    .node("path", "ExprPath")
868    .node("bang", "TerminalNot")
869    .node("arguments", "TokenTreeNode")
870    .node("semicolon", "TerminalSemicolon"))
871    .add_struct(StructBuilder::new("ItemMacroDeclaration")
872        .node("attributes" ,"AttributeList")
873        .node("visibility", "Visibility")
874        .node("macro_kw", "TerminalMacro")
875        .key_node("name", "TerminalIdentifier")
876        .node("lbrace", "TerminalLBrace")
877        .node("rules", "MacroRulesList")
878        .node("rbrace", "TerminalRBrace")
879    )
880    .add_list("MacroRulesList", "MacroRule")
881    .add_struct(StructBuilder::new("MacroRule")
882        .node("lhs", "WrappedMacro")
883        .node("fat_arrow", "TerminalMatchArrow")
884        .node("rhs", "BracedMacro")
885        .node("semicolon", "TerminalSemicolon")
886    )
887    .add_struct(StructBuilder::new("ParamKind")
888        .node("colon", "TerminalColon")
889        .node("kind", "MacroParamKind")
890    )
891    .add_option("ParamKind")
892    .add_struct(StructBuilder::new("MacroParam")
893        .node("dollar", "TerminalDollar")
894        .node("name", "TerminalIdentifier")
895        .node("kind", "OptionParamKind")
896    )
897    .add_struct(StructBuilder::new("MacroRepetition")
898        .node("dollar", "TerminalDollar")
899        .node("lparen", "TerminalLParen")
900        .node("elements", "MacroElements")
901        .node("rparen", "TerminalRParen")
902        // TODO(Dean): Add support for more kinds of separators.
903        .node("separator", "OptionTerminalComma")
904        .node("operator", "MacroRepetitionOperator")
905    )
906    .add_option("TerminalComma")
907    .add_enum(EnumBuilder::new("MacroRepetitionOperator")
908        .node_with_explicit_kind("ZeroOrOne", "TerminalQuestionMark")
909        .node_with_explicit_kind("OneOrMore", "TerminalPlus")
910        .node_with_explicit_kind("ZeroOrMore", "TerminalMul")
911        .include_missing()
912    )
913    // TODO(Gil): Add support for more kinds of macro rule parameters.
914    .add_struct(StructBuilder::new("ParamIdent")
915        .node("ident", "TerminalIdentifier")
916    )
917    .add_struct(StructBuilder::new("ParamExpr")
918        .node("expr", "TerminalIdentifier")
919    )
920    .add_enum(EnumBuilder::new("MacroParamKind")
921        .node_with_explicit_kind("Identifier", "ParamIdent")
922        .node_with_explicit_kind("Expr", "ParamExpr")
923        .include_missing()
924    )
925    .add_enum(EnumBuilder::new("MacroElement")
926        .node_with_explicit_kind("Token", "TokenTreeLeaf")
927        .node_with_explicit_kind("Param", "MacroParam")
928        .node_with_explicit_kind("Subtree", "MacroWrapper")
929        .node_with_explicit_kind("Repetition", "MacroRepetition")
930    )
931    .add_list("MacroElements", "MacroElement")
932    .add_struct(StructBuilder::new("MacroWrapper")
933        .node("subtree", "WrappedMacro")
934    )
935    .add_enum(EnumBuilder::new("WrappedMacro")
936        .node_with_explicit_kind("Parenthesized", "ParenthesizedMacro")
937        .node_with_explicit_kind("Braced", "BracedMacro")
938        .node_with_explicit_kind("Bracketed", "BracketedMacro")
939    )
940    .add_struct(StructBuilder::new("ParenthesizedMacro")
941        .node("lparen", "TerminalLParen")
942        .node("elements", "MacroElements")
943        .node("rparen", "TerminalRParen")
944    )
945    .add_struct(StructBuilder::new("BracedMacro")
946        .node("lbrace", "TerminalLBrace")
947        .node("elements", "MacroElements")
948        .node("rbrace", "TerminalRBrace")
949    )
950    .add_struct(StructBuilder::new("BracketedMacro")
951        .node("lbrack", "TerminalLBrack")
952        .node("elements", "MacroElements")
953        .node("rbrack", "TerminalRBrack")
954    )
955    .add_struct(StructBuilder::new("LegacyExprInlineMacro")
956        .node("path", "ExprPath")
957        .node("bang", "TerminalNot")
958        .node("arguments", "WrappedArgList")
959    )
960    .add_struct(StructBuilder::new("LegacyItemInlineMacro")
961        .node("attributes" ,"AttributeList")
962        .node("path", "ExprPath")
963        .node("bang", "TerminalNot")
964        .node("arguments", "WrappedArgList")
965        .node("semicolon", "TerminalSemicolon"))
966    // --- Skipped nodes ---
967    // A wrapper for the skipped node enum as the enum nodes (Trivium) can't have enum as a child directly.
968    .add_struct(StructBuilder::new("TriviumSkippedNode")
969        .node("node", "SkippedNode")
970    )
971    // An enum of all nodes that can be skipped while parsing, new nodes can be added here if needed to be skipped.
972    .add_enum(EnumBuilder::new("SkippedNode")
973        .node_with_explicit_kind("AttributeList", "AttributeList")
974        .node_with_explicit_kind("VisibilityPub", "VisibilityPub")
975        .node_with_explicit_kind("ExprPath", "ExprPath")
976    )
977    // --- Tokens + Terminals ---
978    .add_token_and_terminal("Identifier")
979    .add_token_and_terminal("LiteralNumber")
980    .add_token_and_terminal("ShortString")
981    .add_token_and_terminal("String")
982    .add_keyword_token_and_terminal("As")
983    .add_keyword_token_and_terminal("Const")
984    .add_keyword_token_and_terminal("Else")
985    .add_keyword_token_and_terminal("Enum")
986    .add_keyword_token_and_terminal("Extern")
987    .add_keyword_token_and_terminal("False")
988    .add_keyword_token_and_terminal("Function")
989    .add_keyword_token_and_terminal("If")
990    .add_keyword_token_and_terminal("While")
991    .add_keyword_token_and_terminal("For")
992    .add_keyword_token_and_terminal("Loop")
993    .add_keyword_token_and_terminal("Impl")
994    .add_keyword_token_and_terminal("Implicits")
995    .add_keyword_token_and_terminal("Let")
996    .add_keyword_token_and_terminal("Macro")
997    .add_keyword_token_and_terminal("Match")
998    .add_keyword_token_and_terminal("Module")
999    .add_keyword_token_and_terminal("Mut")
1000    .add_keyword_token_and_terminal("NoPanic")
1001    .add_keyword_token_and_terminal("Of")
1002    .add_keyword_token_and_terminal("Ref")
1003    .add_keyword_token_and_terminal("Continue")
1004    .add_keyword_token_and_terminal("Return")
1005    .add_keyword_token_and_terminal("Break")
1006    .add_keyword_token_and_terminal("Struct")
1007    .add_keyword_token_and_terminal("Trait")
1008    .add_keyword_token_and_terminal("True")
1009    .add_keyword_token_and_terminal("Type")
1010    .add_keyword_token_and_terminal("Use")
1011    .add_keyword_token_and_terminal("Pub")
1012    .add_token_and_terminal("And")
1013    .add_token_and_terminal("AndAnd")
1014    .add_token_and_terminal("Arrow")
1015    .add_token_and_terminal("At")
1016    .add_token_and_terminal("BadCharacters")
1017    .add_token_and_terminal("Colon")
1018    .add_token_and_terminal("ColonColon")
1019    .add_token_and_terminal("Comma")
1020    .add_token_and_terminal("Div")
1021    .add_token_and_terminal("DivEq")
1022    .add_token_and_terminal("Dollar")
1023    .add_token_and_terminal("Dot")
1024    .add_token_and_terminal("DotDot")
1025    .add_token_and_terminal("DotDotEq")
1026    .add_token_and_terminal("EndOfFile")
1027    .add_token_and_terminal("Eq")
1028    .add_token_and_terminal("EqEq")
1029    .add_token_and_terminal("GE")
1030    .add_token_and_terminal("GT")
1031    .add_token_and_terminal("Hash")
1032    .add_token_and_terminal("LBrace")
1033    .add_token_and_terminal("LBrack")
1034    .add_token_and_terminal("LE")
1035    .add_token_and_terminal("LParen")
1036    .add_token_and_terminal("LT")
1037    .add_token_and_terminal("MatchArrow")
1038    .add_token_and_terminal("Minus")
1039    .add_token_and_terminal("MinusEq")
1040    .add_token_and_terminal("Mod")
1041    .add_token_and_terminal("ModEq")
1042    .add_token_and_terminal("Mul")
1043    .add_token_and_terminal("MulEq")
1044    .add_token_and_terminal("Neq")
1045    .add_token_and_terminal("Not")
1046    .add_token_and_terminal("BitNot")
1047    .add_token_and_terminal("Or")
1048    .add_token_and_terminal("OrOr")
1049    .add_token_and_terminal("Plus")
1050    .add_token_and_terminal("PlusEq")
1051    .add_token_and_terminal("QuestionMark")
1052    .add_token_and_terminal("RBrace")
1053    .add_token_and_terminal("RBrack")
1054    .add_token_and_terminal("RParen")
1055    .add_token_and_terminal("Semicolon")
1056    .add_token_and_terminal("Underscore")
1057    .add_token_and_terminal("Xor")
1058    // --- Meta ---
1059    .add_struct(StructBuilder::new("SyntaxFile")
1060        .node("items", "ModuleItemList")
1061        .node("eof", "TerminalEndOfFile")
1062    )
1063    .add_token_and_terminal("Empty")
1064    .add_token("SingleLineComment")
1065    .add_token("SingleLineInnerComment")
1066    .add_token("SingleLineDocComment")
1067    .add_token("Whitespace")
1068    .add_token("Newline")
1069    .add_token("Missing")
1070    .add_token("Skipped")
1071    .add_all_tokens_enum("TokenNode")
1072    .get()
1073}