// 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"],
    ],
    // 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"],
        ["&&", "AMPAMP"],
        ["||", "PIPEPIPE"],
        ["<<", "SHL"],
        [">>", "SHR"],
        ["<<=", "SHLEQ"],
        [">>=", "SHREQ"],
    ],
    keywords: [
        "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",
    ],
    tokens: [
        "ERROR",
        "IDENT",
        "UNDERSCORE",
        "WHITESPACE",
        "INT_NUMBER",
        "FLOAT_NUMBER",
        "LIFETIME",
        "CHAR",
        "BYTE",
        "STRING",
        "RAW_STRING",
        "BYTE_STRING",
        "RAW_BYTE_STRING",
        "COMMENT",
        "SHEBANG",
    ],
    nodes: [
        "SOURCE_FILE",

        "STRUCT_DEF",
        "ENUM_DEF",
        "FN_DEF",
        "RET_TYPE",
        "EXTERN_CRATE_ITEM",
        "MODULE",
        "USE_ITEM",
        "STATIC_DEF",
        "CONST_DEF",
        "TRAIT_DEF",
        "IMPL_ITEM",
        "TYPE_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",
        "TUPLE_STRUCT_PAT",
        "TUPLE_PAT",
        "SLICE_PAT",
        "RANGE_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_LIST",
        "POS_FIELD",
        "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",
    ],
    ast: {
        "SourceFile": (
            traits: [ "ModuleItemOwner", "FnDefOwner" ],
            collections: [
                ["modules", "Module"],
            ]
        ),
        "FnDef": (
            traits: [
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner",
                "DocCommentsOwner"
            ],
            options: [ "ParamList", ["body", "Block"], "RetType" ],
        ),
        "RetType": (),
        "StructDef": (
            traits: [
                "NameOwner",
                "TypeParamsOwner",
                "AttrsOwner",
                "DocCommentsOwner"
            ],
            collections: [
                ["fields", "NamedFieldDef"]
            ]
        ),
        "NamedFieldDef": ( traits: ["NameOwner", "AttrsOwner"] ),
        "EnumDef": ( traits: [
            "NameOwner",
            "TypeParamsOwner",
            "AttrsOwner",
            "DocCommentsOwner"
        ] ),
        "TraitDef": ( traits: ["NameOwner", "AttrsOwner", "DocCommentsOwner"] ),
        "Module": (
            traits: ["NameOwner", "AttrsOwner", "DocCommentsOwner" ],
            options: [ "ItemList" ]
        ),
        "ItemList": (
            traits: [ "FnDefOwner", "ModuleItemOwner" ],
        ),
        "ConstDef": ( traits: [
            "NameOwner",
            "TypeParamsOwner",
            "AttrsOwner",
            "DocCommentsOwner"
        ] ),
        "StaticDef": ( traits: [
            "NameOwner",
            "TypeParamsOwner",
            "AttrsOwner",
            "DocCommentsOwner"
        ] ),
        "TypeDef": ( traits: [
            "NameOwner",
            "TypeParamsOwner",
            "AttrsOwner",
            "DocCommentsOwner"
        ] ),
        "ImplItem": (),

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

        "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", "TypeDef", "ImplItem",
                   "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ]
        ),

        "TupleExpr": (),
        "ArrayExpr": (),
        "ParenExpr": (),
        "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": (),
        "Label": (),
        "BlockExpr": (
            options: [ "Block" ]
        ),
        "ReturnExpr": (),
        "MatchExpr": (
            options: [ "Expr", "MatchArmList" ],
        ),
        "MatchArmList": (
            collections: [ ["arms", "MatchArm"] ],
        ),
        "MatchArm": (
            options: [
                [ "guard", "MatchGuard" ],
                "Expr",
            ],
            collections: [ [ "pats", "Pat" ] ]
        ),
        "MatchGuard": (),
        "StructLit": (),
        "NamedFieldList": (),
        "NamedField": (),
        "CallExpr": (
            traits: ["ArgListOwner"],
            options: [ "Expr" ],
        ),
        "MethodCallExpr": (
            traits: ["ArgListOwner"],
            options: [ "Expr" ],
        ),
        "IndexExpr": (),
        "FieldExpr": (),
        "TryExpr": (),
        "CastExpr": (),
        "RefExpr": (),
        "PrefixExpr": (),
        "RangeExpr": (),
        "BinExpr": (),
        "String": (),
        "Byte": (),
        "ByteString": (),
        "Char": (),
        "Literal": (),

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

        "RefPat": (),
        "BindPat": ( traits: ["NameOwner"] ),
        "PlaceholderPat": (),
        "PathPat": (),
        "StructPat": (),
        "FieldPatList": (),
        "TupleStructPat": (),
        "TuplePat": (),
        "SlicePat": (),
        "RangePat": (),

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

        "Name": (),
        "NameRef": (),
        "Attr": ( options: [ ["value", "TokenTree"] ] ),
        "TokenTree": (),
        "TypeParamList": (
            collections: [
                ["type_params", "TypeParam" ],
                ["lifetime_params", "LifetimeParam" ],
            ]
        ),
        "TypeParam": ( traits: ["NameOwner"] ),
        "LifetimeParam": ( options: [ "Lifetime" ] ),
        "Lifetime": (),
        "WhereClause": (),
        "ExprStmt": (
            options: [ ["expr", "Expr"] ]
        ),
        "LetStmt": ( options: [
            ["pat", "Pat"],
            ["initializer", "Expr"],
        ]),
        "Condition": (
            options: [ "Pat", "Expr" ]
        ),
        "Stmt": (
            enum: ["ExprStmt", "LetStmt"],
        ),
        "Block": (
            options: [ "Expr" ],
            collections: [
                ["statements", "Stmt"],
            ]
        ),
        "ParamList": (
            options: [ "SelfParam" ],
            collections: [
                ["params", "Param"]
            ]
        ),
        "SelfParam": (),
        "Param": (
            options: [ "Pat" ],
        ),
        "UseItem": (
            options: [ "UseTree" ]
        ),
        "UseTree": (
            options: [ "Path", "UseTreeList" ]
        ),
        "UseTreeList": (
            collections: [["use_trees", "UseTree"]]
        ),
        "ExternCrateItem": (),
        "ArgList": (
            collections: [
                ["args", "Expr"]
            ]
        ),
        "Path": (
            options: [
                ["segment", "PathSegment"],
                ["qualifier", "Path"],
            ]
        ),
        "PathSegment": (
            options: [ "NameRef" ]
        ),
        "Comment": (),
        "Whitespace": (),
    },
)