summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibSQL/Parser.h
blob: 4d1c888e379c7327128ae99d6aab43895c7ac4d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * Copyright (c) 2021, Tim Flynn <trflynn89@pm.me>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/String.h>
#include <AK/StringView.h>
#include <LibSQL/AST.h>
#include <LibSQL/Lexer.h>
#include <LibSQL/Token.h>

namespace SQL {

class Parser {
    struct Position {
        size_t line { 0 };
        size_t column { 0 };
    };

    struct Error {
        String message;
        Position position;

        String to_string() const
        {
            return String::formatted("{} (line: {}, column: {})", message, position.line, position.column);
        }
    };

public:
    explicit Parser(Lexer lexer);

    NonnullRefPtr<Statement> next_statement();

    bool has_errors() const { return m_parser_state.m_errors.size(); }
    const Vector<Error>& errors() const { return m_parser_state.m_errors; }

protected:
    NonnullRefPtr<Expression> parse_expression(); // Protected for unit testing.

private:
    struct ParserState {
        explicit ParserState(Lexer);

        Lexer m_lexer;
        Token m_token;
        Vector<Error> m_errors;
    };

    NonnullRefPtr<Statement> parse_statement();
    NonnullRefPtr<Statement> parse_statement_with_expression_list(RefPtr<CommonTableExpressionList>);
    NonnullRefPtr<CreateTable> parse_create_table_statement();
    NonnullRefPtr<AlterTable> parse_alter_table_statement();
    NonnullRefPtr<DropTable> parse_drop_table_statement();
    NonnullRefPtr<Insert> parse_insert_statement(RefPtr<CommonTableExpressionList>);
    NonnullRefPtr<Update> parse_update_statement(RefPtr<CommonTableExpressionList>);
    NonnullRefPtr<Delete> parse_delete_statement(RefPtr<CommonTableExpressionList>);
    NonnullRefPtr<Select> parse_select_statement(RefPtr<CommonTableExpressionList>);
    NonnullRefPtr<CommonTableExpressionList> parse_common_table_expression_list();

    NonnullRefPtr<Expression> parse_primary_expression();
    NonnullRefPtr<Expression> parse_secondary_expression(NonnullRefPtr<Expression> primary);
    bool match_secondary_expression() const;
    Optional<NonnullRefPtr<Expression>> parse_literal_value_expression();
    Optional<NonnullRefPtr<Expression>> parse_column_name_expression(String with_parsed_identifier = {}, bool with_parsed_period = false);
    Optional<NonnullRefPtr<Expression>> parse_unary_operator_expression();
    Optional<NonnullRefPtr<Expression>> parse_binary_operator_expression(NonnullRefPtr<Expression> lhs);
    Optional<NonnullRefPtr<Expression>> parse_chained_expression();
    Optional<NonnullRefPtr<Expression>> parse_cast_expression();
    Optional<NonnullRefPtr<Expression>> parse_case_expression();
    Optional<NonnullRefPtr<Expression>> parse_exists_expression(bool invert_expression, TokenType opening_token = TokenType::Exists);
    Optional<NonnullRefPtr<Expression>> parse_collate_expression(NonnullRefPtr<Expression> expression);
    Optional<NonnullRefPtr<Expression>> parse_is_expression(NonnullRefPtr<Expression> expression);
    Optional<NonnullRefPtr<Expression>> parse_match_expression(NonnullRefPtr<Expression> lhs, bool invert_expression);
    Optional<NonnullRefPtr<Expression>> parse_null_expression(NonnullRefPtr<Expression> expression, bool invert_expression);
    Optional<NonnullRefPtr<Expression>> parse_between_expression(NonnullRefPtr<Expression> expression, bool invert_expression);
    Optional<NonnullRefPtr<Expression>> parse_in_expression(NonnullRefPtr<Expression> expression, bool invert_expression);

    NonnullRefPtr<ColumnDefinition> parse_column_definition();
    NonnullRefPtr<TypeName> parse_type_name();
    NonnullRefPtr<SignedNumber> parse_signed_number();
    NonnullRefPtr<CommonTableExpression> parse_common_table_expression();
    NonnullRefPtr<QualifiedTableName> parse_qualified_table_name();
    NonnullRefPtr<ReturningClause> parse_returning_clause();
    NonnullRefPtr<ResultColumn> parse_result_column();
    NonnullRefPtr<TableOrSubquery> parse_table_or_subquery();
    NonnullRefPtr<OrderingTerm> parse_ordering_term();
    void parse_schema_and_table_name(String& schema_name, String& table_name);
    ConflictResolution parse_conflict_resolution();

    template<typename ParseCallback>
    void parse_comma_separated_list(bool surrounded_by_parentheses, ParseCallback&& parse_callback)
    {
        if (surrounded_by_parentheses)
            consume(TokenType::ParenOpen);

        while (!has_errors() && !match(TokenType::Eof)) {
            parse_callback();

            if (!match(TokenType::Comma))
                break;

            consume(TokenType::Comma);
        };

        if (surrounded_by_parentheses)
            consume(TokenType::ParenClose);
    }

    Token consume();
    Token consume(TokenType type);
    bool consume_if(TokenType type);
    bool match(TokenType type) const;

    void expected(StringView what);
    void syntax_error(String message);

    Position position() const;

    ParserState m_parser_state;
};

}