// Stores definitions which must be used in multiple places
// See `cargo gen-syntax` (defined in crates/tools/src/main.rs)
Grammar(
    single_byte_tokens: [
        [";", "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"],
    ],
    // Tokens for which the longest match must be chosen (e.g. `..` is a DOTDOT, but `.` is a DOT)
    multi_byte_tokens: [
        [".", "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",
    ],
    contextual_keywords: [
        "auto",
        "default",
        "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",
        "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",

        "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",
        "BIND_PAT",
        "PLACEHOLDER_PAT",
        "PATH_PAT",
        "STRUCT_PAT",
        "FIELD_PAT_LIST",
        "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",
        "STRUCT_LIT",
        "NAMED_FIELD_LIST",
        "NAMED_FIELD",

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

        // unary
        "REF_EXPR",
        "PREFIX_EXPR",

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

        "BLOCK",
        "EXTERN_BLOCK",
        "EXTERN_ITEM_LIST",
        "ENUM_VARIANT",
        "NAMED_FIELD_DEF_LIST",
        "NAMED_FIELD_DEF",
        "POS_FIELD_DEF_LIST",
        "POS_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",
        "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", "Block"], "RetType" ],
        ),
        "RetType": (options: ["TypeRef"]),
        "StructDef": (
            traits: [
                "VisibilityOwner",
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner",
                "DocCommentsOwner"
            ]
        ),
        "NamedFieldDefList": (collections: [["fields", "NamedFieldDef"]]),
        "NamedFieldDef": (
            traits: [
                "VisibilityOwner",
                "NameOwner",
                "AttrsOwner",
                "DocCommentsOwner",
                "TypeAscriptionOwner"
            ]
        ),
        "PosFieldDefList": (collections: [["fields", "PosFieldDef"]]),
        "PosFieldDef": ( 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"],
            traits: [
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner"
            ],
        ),
        "ModuleItem": (
            enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock",
                   "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ]
        ),
        "ImplItem": (
            enum: ["FnDef", "TypeAliasDef", "ConstDef"]
        ),

        "TupleExpr": (
            collections: [["exprs", "Expr"]]
        ),
        "ArrayExpr": (
            collections: [["exprs", "Expr"]]
        ),
        "ParenExpr": (options: ["Expr"]),
        "PathExpr": (options: ["Path"]),
        "LambdaExpr": (
            options: [
                "ParamList",
                ["body", "Expr"],
            ]
        ),
        "IfExpr": (
            options: [ "Condition" ]
        ),
        "LoopExpr": (
            traits: ["LoopBodyOwner"],
        ),
        "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"]),
        "StructLit": (options: ["Path", "NamedFieldList"]),
        "NamedFieldList": (
            collections: [ ["fields", "NamedField"] ],
            options: [["spread", "Expr"]]
        ),
        "NamedField": (options: ["NameRef", "Expr"]),
        "CallExpr": (
            traits: ["ArgListOwner"],
            options: [ "Expr" ],
        ),
        "MethodCallExpr": (
            traits: ["ArgListOwner"],
            options: [ "Expr", "NameRef", "TypeArgList" ],
        ),
        "IndexExpr": (),
        "FieldExpr": (options: ["Expr", "NameRef"]),
        "TryExpr": (options: ["Expr"]),
        "CastExpr": (options: ["Expr", "TypeRef"]),
        "RefExpr": (options: ["Expr"]),
        "PrefixExpr": (options: ["Expr"]),
        "RangeExpr": (),
        "BinExpr": (),

        "Literal": (),

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

        "RefPat": ( options: [ "Pat" ]),
        "BindPat": (
            options: [ "Pat" ],
            traits: ["NameOwner"]
        ),
        "PlaceholderPat": (),
        "PathPat": ( options: [ "Path" ] ),
        "StructPat": ( options: ["FieldPatList", "Path"] ),
        "FieldPatList": (
            collections: [
                ["field_pats", "FieldPat"],
                ["bind_pats", "BindPat"],
            ]
        ),
        "FieldPat": (
            traits: ["NameOwner"],
            options: ["Pat"]
        ),
        "TupleStructPat": (
            options: ["Path"],
            collections: [["args", "Pat"]],
        ),
        "TuplePat": ( collections: [["args", "Pat"]] ),
        "SlicePat": (),
        "RangePat": (),
        "LiteralPat": (options: ["Literal"]),

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

        "Visibility": (),
        "Name": (),
        "NameRef": (),
        "MacroCall": (
            traits: [ "NameOwner", "AttrsOwner","DocCommentsOwner" ],
            options: [ "TokenTree", "Path" ],
        ),
        "Attr": ( options: [ ["value", "TokenTree"] ] ),
        "TokenTree": (),
        "TypeParamList": (
            collections: [
                ["type_params", "TypeParam" ],
                ["lifetime_params", "LifetimeParam" ],
            ]
        ),
        "TypeParam": ( traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner", "DefaultTypeParamOwner"] ),
        "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",
            ]
        ),
        "ParamList": (
            options: [ "SelfParam" ],
            collections: [
                ["params", "Param"]
            ]
        ),
        "SelfParam": (
            traits: [
                "TypeAscriptionOwner",
            ]
        ),
        "Param": (
            options: [ "Pat" ],
            traits: [
                "TypeAscriptionOwner",
            ]
        ),
        "UseItem": (
            traits: ["AttrsOwner"],
            options: [ "UseTree" ],
        ),
        "UseTree": (
            options: [ "Path", "UseTreeList", "Alias" ]
        ),
        "Alias": (
            traits: ["NameOwner"],
        ),
        "UseTreeList": (
            collections: [["use_trees", "UseTree"]]
        ),
        "ExternCrateItem": (
            options: ["NameRef", "Alias"],
        ),
        "ArgList": (
            collections: [
                ["args", "Expr"]
            ]
        ),
        "Path": (
            options: [
                ["segment", "PathSegment"],
                ["qualifier", "Path"],
            ]
        ),
        "PathSegment": (
            options: [ "NameRef", "TypeArgList" ]
        ),
        "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"],
            ],
        )
    },
)