function tryReadPrimitiveType()

in src/powerquery-parser/parser/parsers/naive.ts [2350:2458]


function tryReadPrimitiveType(state: ParseState, parser: Parser): TriedReadPrimitiveType {
    const nodeKind: Ast.NodeKind.PrimitiveType = Ast.NodeKind.PrimitiveType;

    const trace: Trace = state.traceManager.entry(NaiveTraceConstant.Parse, tryReadPrimitiveType.name, {
        [NaiveTraceConstant.TokenIndex]: state.tokenIndex,
    });

    ParseStateUtils.startContext(state, nodeKind);

    const checkpoint: ParseStateCheckpoint = parser.createCheckpoint(state);

    const expectedTokenKinds: ReadonlyArray<Token.TokenKind> = [
        Token.TokenKind.Identifier,
        Token.TokenKind.KeywordType,
        Token.TokenKind.NullLiteral,
    ];

    const maybeError: ParseError.ExpectedAnyTokenKindError | undefined = ParseStateUtils.testIsOnAnyTokenKind(
        state,
        expectedTokenKinds,
    );

    if (maybeError) {
        const error: ParseError.ExpectedAnyTokenKindError = maybeError;

        trace.exit({
            [NaiveTraceConstant.TokenIndex]: state.tokenIndex,
            [TraceConstant.IsError]: true,
        });

        return ResultUtils.boxError(error);
    }

    let primitiveTypeKind: Constant.PrimitiveTypeConstant;

    if (ParseStateUtils.isOnTokenKind(state, Token.TokenKind.Identifier)) {
        const currentTokenData: string = state.lexerSnapshot.tokens[state.tokenIndex].data;

        switch (currentTokenData) {
            case Constant.PrimitiveTypeConstant.Action:
            case Constant.PrimitiveTypeConstant.Any:
            case Constant.PrimitiveTypeConstant.AnyNonNull:
            case Constant.PrimitiveTypeConstant.Binary:
            case Constant.PrimitiveTypeConstant.Date:
            case Constant.PrimitiveTypeConstant.DateTime:
            case Constant.PrimitiveTypeConstant.DateTimeZone:
            case Constant.PrimitiveTypeConstant.Duration:
            case Constant.PrimitiveTypeConstant.Function:
            case Constant.PrimitiveTypeConstant.List:
            case Constant.PrimitiveTypeConstant.Logical:
            case Constant.PrimitiveTypeConstant.None:
            case Constant.PrimitiveTypeConstant.Number:
            case Constant.PrimitiveTypeConstant.Record:
            case Constant.PrimitiveTypeConstant.Table:
            case Constant.PrimitiveTypeConstant.Text:
            case Constant.PrimitiveTypeConstant.Time:
                primitiveTypeKind = currentTokenData;
                readToken(state);
                break;

            default: {
                const token: Token.Token = ParseStateUtils.assertGetTokenAt(state, state.tokenIndex);
                parser.restoreCheckpoint(state, checkpoint);

                return ResultUtils.boxError(
                    new ParseError.InvalidPrimitiveTypeError(
                        state.locale,
                        token,
                        state.lexerSnapshot.graphemePositionStartFrom(token),
                    ),
                );
            }
        }
    } else if (ParseStateUtils.isOnTokenKind(state, Token.TokenKind.KeywordType)) {
        primitiveTypeKind = Constant.PrimitiveTypeConstant.Type;
        readToken(state);
    } else if (ParseStateUtils.isOnTokenKind(state, Token.TokenKind.NullLiteral)) {
        primitiveTypeKind = Constant.PrimitiveTypeConstant.Null;
        readToken(state);
    } else {
        const details: { tokenKind: Token.TokenKind | undefined } = { tokenKind: state.maybeCurrentTokenKind };
        parser.restoreCheckpoint(state, checkpoint);

        trace.exit({
            [NaiveTraceConstant.TokenIndex]: state.tokenIndex,
            [TraceConstant.IsError]: true,
        });

        return ResultUtils.boxError(
            new CommonError.InvariantError(`unknown currentTokenKind, not found in [${expectedTokenKinds}]`, details),
        );
    }

    const primitiveType: Ast.PrimitiveType = {
        ...ParseStateUtils.assertGetContextNodeMetadata(state),
        kind: nodeKind,
        isLeaf: true,
        primitiveTypeKind,
    };

    ParseStateUtils.endContext(state, primitiveType);

    trace.exit({
        [NaiveTraceConstant.TokenIndex]: state.tokenIndex,
        [TraceConstant.IsError]: false,
    });

    return ResultUtils.boxOk(primitiveType);
}