// Stores definitions which must be used in multiple places
// See `cargo xtask codegen` (defined in xtasks/src/main.rs)
Grammar(
    punct: [
        (";", "SEMI"),
        (",", "COMMA"),
        ("(", "L_PAREN"),
        (")", "R_PAREN"),
        ("{", "L_CURLY"),
        ("}", "R_CURLY"),
        ("[", "L_BRACK"),
        ("]", "R_BRACK"),
        ("<", "L_ANGLE"),
        (">", "R_ANGLE"),
        ("@", "AT"),
        ("#", "POUND"),
        ("~", "TILDE"),
        ("?", "QUESTION"),
        ("$", "DOLLAR"),
        ("&", "AMP"),
        ("|", "PIPE"),
        ("+", "PLUS"),
        ("*", "STAR"),
        ("/", "SLASH"),
        ("^", "CARET"),
        ("%", "PERCENT"),
        ("_", "UNDERSCORE"),
        (".", "DOT"),
        ("..", "DOTDOT"),
        ("...", "DOTDOTDOT"),
        ("..=", "DOTDOTEQ"),
        (":", "COLON"),
        ("::", "COLONCOLON"),
        ("=", "EQ"),
        ("==", "EQEQ"),
        ("=>", "FAT_ARROW"),
        ("!", "EXCL"),
        ("!=", "NEQ"),
        ("-", "MINUS"),
        ("->", "THIN_ARROW"),
        ("<=", "LTEQ"),
        (">=", "GTEQ"),
        ("+=", "PLUSEQ"),
        ("-=", "MINUSEQ"),
        ("|=", "PIPEEQ"),
        ("&=", "AMPEQ"),
        ("^=", "CARETEQ"),
        ("/=", "SLASHEQ"),
        ("*=", "STAREQ"),
        ("%=", "PERCENTEQ"),
        ("&&", "AMPAMP"),
        ("||", "PIPEPIPE"),
        ("<<", "SHL"),
        (">>", "SHR"),
        ("<<=", "SHLEQ"),
        (">>=", "SHREQ"),
    ],
    keywords: [
        "async",
        "use",
        "fn",
        "struct",
        "enum",
        "trait",
        "impl",
        "dyn",
        "true",
        "false",
        "as",
        "extern",
        "crate",
        "mod",
        "pub",
        "self",
        "super",
        "in",
        "where",
        "for",
        "loop",
        "while",
        "continue",
        "break",
        "if",
        "else",
        "match",
        "const",
        "static",
        "mut",
        "unsafe",
        "type",
        "ref",
        "let",
        "move",
        "return",
        "try",
        "box",
        "await",
        "macro"
    ],
    contextual_keywords: [
        "auto",
        "default",
        "existential",
        "union",
    ],
    literals: [
        "INT_NUMBER",
        "FLOAT_NUMBER",
        "CHAR",
        "BYTE",
        "STRING",
        "RAW_STRING",
        "BYTE_STRING",
        "RAW_BYTE_STRING",
    ],
    tokens: [
        "ERROR",
        "IDENT",
        "WHITESPACE",
        "LIFETIME",
        "COMMENT",
        "SHEBANG",
        "L_DOLLAR",
        "R_DOLLAR",
    ],
    nodes: [
        "SOURCE_FILE",

        "STRUCT_DEF",
        "UNION_DEF",
        "ENUM_DEF",
        "FN_DEF",
        "RET_TYPE",
        "EXTERN_CRATE_ITEM",
        "MODULE",
        "USE_ITEM",
        "STATIC_DEF",
        "CONST_DEF",
        "TRAIT_DEF",
        "IMPL_BLOCK",
        "TYPE_ALIAS_DEF",
        "MACRO_CALL",
        "TOKEN_TREE",
        "MACRO_DEF",

        "PAREN_TYPE",
        "TUPLE_TYPE",
        "NEVER_TYPE",
        "PATH_TYPE",
        "POINTER_TYPE",
        "ARRAY_TYPE",
        "SLICE_TYPE",
        "REFERENCE_TYPE",
        "PLACEHOLDER_TYPE",
        "FN_POINTER_TYPE",
        "FOR_TYPE",
        "IMPL_TRAIT_TYPE",
        "DYN_TRAIT_TYPE",

        "REF_PAT",
        "BOX_PAT",
        "BIND_PAT",
        "PLACEHOLDER_PAT",
        "DOT_DOT_PAT",
        "PATH_PAT",
        "RECORD_PAT",
        "RECORD_FIELD_PAT_LIST",
        "RECORD_FIELD_PAT",
        "TUPLE_STRUCT_PAT",
        "TUPLE_PAT",
        "SLICE_PAT",
        "RANGE_PAT",
        "LITERAL_PAT",

        // atoms
        "TUPLE_EXPR",
        "ARRAY_EXPR",
        "PAREN_EXPR",
        "PATH_EXPR",
        "LAMBDA_EXPR",
        "IF_EXPR",
        "WHILE_EXPR",
        "CONDITION",
        "LOOP_EXPR",
        "FOR_EXPR",
        "CONTINUE_EXPR",
        "BREAK_EXPR",
        "LABEL",
        "BLOCK_EXPR",
        "RETURN_EXPR",
        "MATCH_EXPR",
        "MATCH_ARM_LIST",
        "MATCH_ARM",
        "MATCH_GUARD",
        "RECORD_LIT",
        "RECORD_FIELD_LIST",
        "RECORD_FIELD",
        "TRY_BLOCK_EXPR",
        "BOX_EXPR",

        // postfix
        "CALL_EXPR",
        "INDEX_EXPR",
        "METHOD_CALL_EXPR",
        "FIELD_EXPR",
        "AWAIT_EXPR",
        "TRY_EXPR",
        "CAST_EXPR",

        // unary
        "REF_EXPR",
        "PREFIX_EXPR",

        "RANGE_EXPR", // just weird
        "BIN_EXPR",

        "BLOCK",
        "EXTERN_BLOCK",
        "EXTERN_ITEM_LIST",
        "ENUM_VARIANT",
        "RECORD_FIELD_DEF_LIST",
        "RECORD_FIELD_DEF",
        "TUPLE_FIELD_DEF_LIST",
        "TUPLE_FIELD_DEF",
        "ENUM_VARIANT_LIST",
        "ITEM_LIST",
        "ATTR",
        "META_ITEM", // not an item actually
        "USE_TREE",
        "USE_TREE_LIST",
        "PATH",
        "PATH_SEGMENT",
        "LITERAL",
        "ALIAS",
        "VISIBILITY",
        "WHERE_CLAUSE",
        "WHERE_PRED",
        "ABI",
        "NAME",
        "NAME_REF",

        "LET_STMT",
        "EXPR_STMT",

        "TYPE_PARAM_LIST",
        "LIFETIME_PARAM",
        "TYPE_PARAM",
        "CONST_PARAM",
        "TYPE_ARG_LIST",
        "LIFETIME_ARG",
        "TYPE_ARG",
        "ASSOC_TYPE_ARG",

        "PARAM_LIST",
        "PARAM",
        "SELF_PARAM",
        "ARG_LIST",
        "TYPE_BOUND",
        "TYPE_BOUND_LIST",

        // macro related
        "MACRO_ITEMS",
        "MACRO_STMTS",
    ],
    ast: {
        "SourceFile": (
            traits: [ "ModuleItemOwner", "FnDefOwner" ],
            collections: [
                ("modules", "Module"),
            ]
        ),
        "FnDef": (
            traits: [
                "VisibilityOwner",
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner",
                "DocCommentsOwner"
            ],
            options: [ "ParamList", ["body", "BlockExpr"], "RetType" ],
        ),
        "RetType": (options: ["TypeRef"]),
        "StructDef": (
            traits: [
                "VisibilityOwner",
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner",
                "DocCommentsOwner"
            ]
        ),
        "UnionDef": (
            traits: [
                "VisibilityOwner",
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner",
                "DocCommentsOwner"
            ],
            options: ["RecordFieldDefList"],
        ),
        "RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]),
        "RecordFieldDef": (
            traits: [
                "VisibilityOwner",
                "NameOwner",
                "AttrsOwner",
                "DocCommentsOwner",
                "TypeAscriptionOwner"
            ]
        ),
        "TupleFieldDefList": (collections: [("fields", "TupleFieldDef")]),
        "TupleFieldDef": ( traits: ["VisibilityOwner", "AttrsOwner"], options: ["TypeRef"]),
        "EnumDef": ( traits: [
            "VisibilityOwner",
            "NameOwner",
            "TypeParamsOwner",
            "AttrsOwner",
            "DocCommentsOwner"
        ], options: [["variant_list", "EnumVariantList"]] ),
        "EnumVariantList": ( collections: [("variants", "EnumVariant")] ),
        "EnumVariant": ( traits: ["NameOwner", "DocCommentsOwner", "AttrsOwner"], options: ["Expr"] ),
        "TraitDef": (
            traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner", "TypeParamsOwner", "TypeBoundsOwner"],
            options: ["ItemList"]
        ),
        "Module": (
            traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner" ],
            options: [ "ItemList" ]
        ),
        "ItemList": (
            collections: [("impl_items", "ImplItem")],
            traits: [ "FnDefOwner", "ModuleItemOwner" ],
        ),
        "ConstDef": (
            traits: [
                "VisibilityOwner",
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner",
                "DocCommentsOwner",
                "TypeAscriptionOwner",
            ],
            options: [ ["body","Expr"]],
        ),
        "StaticDef": (
            traits: [
                "VisibilityOwner",
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner",
                "DocCommentsOwner",
                "TypeAscriptionOwner",
            ],
            options: [ ["body","Expr"]],
        ),
        "TypeAliasDef": (
            traits: [
                "VisibilityOwner",
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner",
                "DocCommentsOwner",
                "TypeBoundsOwner",
            ],
            options: ["TypeRef"]
        ),
        "ImplBlock": (options: ["ItemList"], traits: ["TypeParamsOwner", "AttrsOwner"]),

        "ParenType": (options: ["TypeRef"]),
        "TupleType": ( collections: [("fields", "TypeRef")] ),
        "NeverType": (),
        "PathType": (options: ["Path"]),
        "PointerType": (options: ["TypeRef"]),
        "ArrayType": ( options: ["TypeRef", "Expr"] ),
        "SliceType": ( options: ["TypeRef"] ),
        "ReferenceType": (options: ["TypeRef"]),
        "PlaceholderType": (),
        "FnPointerType": (options: ["ParamList", "RetType"]),
        "ForType": (options: ["TypeRef"]),
        "ImplTraitType": (
            traits: ["TypeBoundsOwner"],
        ),
        "DynTraitType": (
            traits: ["TypeBoundsOwner"],
        ),

        "TypeRef": ( enum: [
            "ParenType",
            "TupleType",
            "NeverType",
            "PathType",
            "PointerType",
            "ArrayType",
            "SliceType",
            "ReferenceType",
            "PlaceholderType",
            "FnPointerType",
            "ForType",
            "ImplTraitType",
            "DynTraitType",
        ]),

        "NominalDef": (
            enum: ["StructDef", "EnumDef", "UnionDef"],
            traits: [
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner"
            ],
        ),
        "ModuleItem": (
            enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock",
                   "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ],
            traits: ["AttrsOwner", "VisibilityOwner"],
        ),
        "ImplItem": (
            enum: ["FnDef", "TypeAliasDef", "ConstDef"],
            traits: ["AttrsOwner"]
        ),

        "TupleExpr": (
            collections: [("exprs", "Expr")]
        ),
        "ArrayExpr": (
            collections: [("exprs", "Expr")]
        ),
        "ParenExpr": (options: ["Expr"]),
        "PathExpr": (options: ["Path"]),
        "LambdaExpr": (
            options: [
                "ParamList", "RetType",
                ["body", "Expr"],
            ]
        ),
        "IfExpr": (
            options: [ "Condition" ]
        ),
        "LoopExpr": (
            traits: ["LoopBodyOwner"],
        ),
        "TryBlockExpr": (
            options: [["body", "BlockExpr"]],
        ),
        "ForExpr": (
            traits: ["LoopBodyOwner"],
            options: [
                "Pat",
                ["iterable", "Expr"],
            ]
        ),
        "WhileExpr": (
            traits: ["LoopBodyOwner"],
            options: [ "Condition" ]
        ),
        "ContinueExpr": (),
        "BreakExpr": (options: ["Expr"]),
        "Label": (),
        "BlockExpr": (
            options: [ "Block" ]
        ),
        "ReturnExpr": (options: ["Expr"]),
        "MatchExpr": (
            options: [ "Expr", "MatchArmList" ],
        ),
        "MatchArmList": (
            collections: [ ("arms", "MatchArm") ],
            traits: [ "AttrsOwner" ]
        ),
        "MatchArm": (
            options: [
                [ "guard", "MatchGuard" ],
                "Expr",
            ],
            collections: [ ("pats", "Pat") ],
            traits: [ "AttrsOwner" ]
        ),
        "MatchGuard": (options: ["Expr"]),
        "RecordLit": (options: ["Path", "RecordFieldList"]),
        "RecordFieldList": (
            collections: [ ("fields", "RecordField") ],
            options: [["spread", "Expr"]]
        ),
        "RecordField": (options: ["NameRef", "Expr"]),
        "CallExpr": (
            traits: ["ArgListOwner"],
            options: [ "Expr" ],
        ),
        "MethodCallExpr": (
            traits: ["ArgListOwner"],
            options: [ "Expr", "NameRef", "TypeArgList" ],
        ),
        "IndexExpr": (),
        "FieldExpr": (options: ["Expr", "NameRef"]),
        "AwaitExpr": (options: ["Expr"]),
        "TryExpr": (options: ["Expr"]),
        "CastExpr": (options: ["Expr", "TypeRef"]),
        "RefExpr": (options: ["Expr"]),
        "PrefixExpr": (options: ["Expr"]),
        "BoxExpr": (options: ["Expr"]),
        "RangeExpr": (),
        "BinExpr": (),

        "Literal": (),

        "Expr": (
            enum: [
                "TupleExpr",
                "ArrayExpr",
                "ParenExpr",
                "PathExpr",
                "LambdaExpr",
                "IfExpr",
                "LoopExpr",
                "ForExpr",
                "WhileExpr",
                "ContinueExpr",
                "BreakExpr",
                "Label",
                "BlockExpr",
                "ReturnExpr",
                "MatchExpr",
                "RecordLit",
                "CallExpr",
                "IndexExpr",
                "MethodCallExpr",
                "FieldExpr",
                "AwaitExpr",
                "TryExpr",
                "TryBlockExpr",
                "CastExpr",
                "RefExpr",
                "PrefixExpr",
                "RangeExpr",
                "BinExpr",
                "Literal",
                "MacroCall",
                "BoxExpr",
            ],
        ),

        "RefPat": ( options: [ "Pat" ]),
        "BoxPat": ( options: [ "Pat" ]),
        "BindPat": (
            options: [ "Pat" ],
            traits: ["NameOwner"]
        ),
        "PlaceholderPat": (),
        "DotDotPat": (),
        "PathPat": ( options: [ "Path" ] ),
        "RecordPat": ( options: ["RecordFieldPatList", "Path"] ),
        "RecordFieldPatList": (
            collections: [
                ("record_field_pats", "RecordFieldPat"),
                ("bind_pats", "BindPat"),
            ]
        ),
        "RecordFieldPat": (
            traits: ["NameOwner"],
            options: ["Pat"]
        ),
        "TupleStructPat": (
            options: ["Path"],
            collections: [("args", "Pat")],
        ),
        "TuplePat": ( collections: [("args", "Pat")] ),
        "SlicePat": (),
        "RangePat": (),
        "LiteralPat": (options: ["Literal"]),

        "Pat": (
            enum: [
                "RefPat",
                "BoxPat",
                "BindPat",
                "PlaceholderPat",
                "DotDotPat",
                "PathPat",
                "RecordPat",
                "TupleStructPat",
                "TuplePat",
                "SlicePat",
                "RangePat",
                "LiteralPat",
            ],
        ),

        "Visibility": (),
        "Name": (),
        "NameRef": (),
        "MacroCall": (
            traits: [ "NameOwner", "AttrsOwner","DocCommentsOwner" ],
            options: [ "TokenTree", "Path" ],
        ),
        "AttrInput": ( enum: [ "Literal", "TokenTree" ] ),
        "Attr": ( options: [ "Path", [ "input", "AttrInput" ] ] ),
        "TokenTree": (),
        "TypeParamList": (
            collections: [
                ("type_params", "TypeParam" ),
                ("lifetime_params", "LifetimeParam" ),
            ]
        ),
        "TypeParam": (
            options: [("default_type", "TypeRef")],
            traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner"],
        ),
        "ConstParam": (
            options: [("default_val", "Expr")],
            traits: ["NameOwner", "AttrsOwner", "TypeAscriptionOwner"],
        ),
        "LifetimeParam": (
            traits: ["AttrsOwner"],
        ),
        "TypeBound": (
            options: [
                "TypeRef",
            ]
        ),
        "TypeBoundList": (
            collections: [
                ("bounds", "TypeBound"),
            ]
        ),
        "WherePred": (
            options: [
                "TypeRef",
            ],
            traits: [
                "TypeBoundsOwner",
            ],
        ),
        "WhereClause": (
            collections: [
                ("predicates", "WherePred"),
            ],
        ),
        "ExprStmt": (
            options: [ ["expr", "Expr"] ]
        ),
        "LetStmt": (
            options: [
                ["pat", "Pat"],
                ["initializer", "Expr"],
            ],
            traits: [
                "TypeAscriptionOwner",
            ]
        ),
        "Condition": (
            options: [ "Pat", "Expr" ]
        ),
        "Stmt": (
            enum: ["ExprStmt", "LetStmt"],
        ),
        "Block": (
            options: [ "Expr" ],
            collections: [
                ("statements", "Stmt"),
            ],
            traits: [
                "AttrsOwner",
                "ModuleItemOwner",
            ]
        ),
        "ParamList": (
            options: [ "SelfParam" ],
            collections: [
                ("params", "Param"),
            ]
        ),
        "SelfParam": (
            traits: [
                "TypeAscriptionOwner",
                "AttrsOwner",
            ]
        ),
        "Param": (
            options: [ "Pat" ],
            traits: [
                "TypeAscriptionOwner",
                "AttrsOwner",
            ]
        ),
        "UseItem": (
            traits: ["AttrsOwner", "VisibilityOwner"],
            options: [ "UseTree" ],
        ),
        "UseTree": (
            options: [ "Path", "UseTreeList", "Alias" ]
        ),
        "Alias": (
            traits: ["NameOwner"],
        ),
        "UseTreeList": (
            collections: [("use_trees", "UseTree")]
        ),
        "ExternCrateItem": (
            traits: ["AttrsOwner", "VisibilityOwner"],
            options: ["NameRef", "Alias"],
        ),
        "ArgList": (
            collections: [
                ("args", "Expr"),
            ]
        ),
        "Path": (
            options: [
                ["segment", "PathSegment"],
                ["qualifier", "Path"],
            ]
        ),
        "PathSegment": (
            options: [ "NameRef", "TypeArgList", "ParamList", "RetType", "PathType" ]
        ),
        "TypeArgList": (collections: [
            ("type_args", "TypeArg"),
            ("lifetime_args", "LifetimeArg"),
            ("assoc_type_args", "AssocTypeArg"),
        ]),
        "TypeArg": (options: ["TypeRef"]),
        "AssocTypeArg": (options: ["NameRef", "TypeRef"]),
        "LifetimeArg": (),

        "MacroItems": (
            traits: [ "ModuleItemOwner", "FnDefOwner" ],
        ),

        "MacroStmts" : (
            options: [ "Expr" ],
            collections: [
                ("statements", "Stmt"),
            ],
        )
    },
)
