summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2021-04-23 12:33:32 -0400
committerAndreas Kling <kling@serenityos.org>2021-04-23 22:36:07 +0200
commit418884ab64e7dabe539b629ec284529798309a43 (patch)
tree2226666b42a4d87a4fe00a0e65200aeaf2f39462
parent6a69b8efa79d6637ffa49cb3bd62b0c02c08987d (diff)
downloadserenity-418884ab64e7dabe539b629ec284529798309a43.zip
LibSQL: Add Parser::parse_comma_separated_list helper
A quite common semantic emerged for parsing comma-separated expressions: consume(TokenType::ParenOpen); do { // do something if (!match(TokenType::Comma)) break; consume(TokenType::Comma); } while (!match(TokenType::Eof)); consume(TokenType::ParenClose); Add a helper to do the bulk of the while loop.
-rw-r--r--Userland/Libraries/LibSQL/Parser.cpp119
-rw-r--r--Userland/Libraries/LibSQL/Parser.h19
2 files changed, 41 insertions, 97 deletions
diff --git a/Userland/Libraries/LibSQL/Parser.cpp b/Userland/Libraries/LibSQL/Parser.cpp
index 7ed51e7f7e..7752a62e6a 100644
--- a/Userland/Libraries/LibSQL/Parser.cpp
+++ b/Userland/Libraries/LibSQL/Parser.cpp
@@ -86,19 +86,10 @@ NonnullRefPtr<CreateTable> Parser::parse_create_table_statement()
// FIXME: Parse "AS select-stmt".
NonnullRefPtrVector<ColumnDefinition> column_definitions;
- consume(TokenType::ParenOpen);
- do {
- column_definitions.append(parse_column_definition());
-
- if (match(TokenType::ParenClose))
- break;
-
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
+ parse_comma_separated_list(true, [&]() { column_definitions.append(parse_column_definition()); });
// FIXME: Parse "table-constraint".
- consume(TokenType::ParenClose);
consume(TokenType::SemiColon);
return create_ast_node<CreateTable>(move(schema_name), move(table_name), move(column_definitions), is_temporary, is_error_if_table_exists);
@@ -161,23 +152,12 @@ NonnullRefPtr<Select> Parser::parse_select_statement(RefPtr<CommonTableExpressio
consume_if(TokenType::All); // ALL is the default, so ignore it if specified.
NonnullRefPtrVector<ResultColumn> result_column_list;
- do {
- result_column_list.append(parse_result_column());
- if (!match(TokenType::Comma))
- break;
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
+ parse_comma_separated_list(false, [&]() { result_column_list.append(parse_result_column()); });
NonnullRefPtrVector<TableOrSubquery> table_or_subquery_list;
if (consume_if(TokenType::From)) {
// FIXME: Parse join-clause.
-
- do {
- table_or_subquery_list.append(parse_table_or_subquery());
- if (!match(TokenType::Comma))
- break;
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
+ parse_comma_separated_list(false, [&]() { table_or_subquery_list.append(parse_table_or_subquery()); });
}
RefPtr<Expression> where_clause;
@@ -189,18 +169,15 @@ NonnullRefPtr<Select> Parser::parse_select_statement(RefPtr<CommonTableExpressio
consume(TokenType::By);
NonnullRefPtrVector<Expression> group_by_list;
- do {
- group_by_list.append(parse_expression());
- if (!match(TokenType::Comma))
- break;
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
-
- RefPtr<Expression> having_clause;
- if (consume_if(TokenType::Having))
- having_clause = parse_expression();
-
- group_by_clause = create_ast_node<GroupByClause>(move(group_by_list), move(having_clause));
+ parse_comma_separated_list(false, [&]() { group_by_list.append(parse_expression()); });
+
+ if (!group_by_list.is_empty()) {
+ RefPtr<Expression> having_clause;
+ if (consume_if(TokenType::Having))
+ having_clause = parse_expression();
+
+ group_by_clause = create_ast_node<GroupByClause>(move(group_by_list), move(having_clause));
+ }
}
// FIXME: Parse 'WINDOW window-name AS window-defn'.
@@ -209,13 +186,7 @@ NonnullRefPtr<Select> Parser::parse_select_statement(RefPtr<CommonTableExpressio
NonnullRefPtrVector<OrderingTerm> ordering_term_list;
if (consume_if(TokenType::Order)) {
consume(TokenType::By);
-
- do {
- ordering_term_list.append(parse_ordering_term());
- if (!match(TokenType::Comma))
- break;
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
+ parse_comma_separated_list(false, [&]() { ordering_term_list.append(parse_ordering_term()); });
}
RefPtr<LimitClause> limit_clause;
@@ -246,13 +217,7 @@ NonnullRefPtr<CommonTableExpressionList> Parser::parse_common_table_expression_l
bool recursive = consume_if(TokenType::Recursive);
NonnullRefPtrVector<CommonTableExpression> common_table_expression;
- do {
- common_table_expression.append(parse_common_table_expression());
- if (!match(TokenType::Comma))
- break;
-
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
+ parse_comma_separated_list(false, [&]() { common_table_expression.append(parse_common_table_expression()); });
return create_ast_node<CommonTableExpressionList>(recursive, move(common_table_expression));
}
@@ -504,17 +469,7 @@ Optional<NonnullRefPtr<Expression>> Parser::parse_chained_expression()
return {};
NonnullRefPtrVector<Expression> expressions;
- consume(TokenType::ParenOpen);
-
- do {
- expressions.append(parse_expression());
- if (match(TokenType::ParenClose))
- break;
-
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
-
- consume(TokenType::ParenClose);
+ parse_comma_separated_list(true, [&]() { expressions.append(parse_expression()); });
return create_ast_node<ChainedExpression>(move(expressions));
}
@@ -669,16 +624,8 @@ Optional<NonnullRefPtr<Expression>> Parser::parse_in_expression(NonnullRefPtr<Ex
// FIXME: Consolidate this with parse_chained_expression(). That method consumes the opening paren as
// well, and also requires at least one expression (whereas this allows for an empty chain).
NonnullRefPtrVector<Expression> expressions;
-
- if (!match(TokenType::ParenClose)) {
- do {
- expressions.append(parse_expression());
- if (match(TokenType::ParenClose))
- break;
-
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
- }
+ if (!match(TokenType::ParenClose))
+ parse_comma_separated_list(false, [&]() { expressions.append(parse_expression()); });
consume(TokenType::ParenClose);
@@ -763,17 +710,8 @@ NonnullRefPtr<CommonTableExpression> Parser::parse_common_table_expression()
auto table_name = consume(TokenType::Identifier).value();
Vector<String> column_names;
- if (consume_if(TokenType::ParenOpen)) {
- do {
- column_names.append(consume(TokenType::Identifier).value());
- if (match(TokenType::ParenClose))
- break;
-
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
-
- consume(TokenType::ParenClose);
- }
+ if (match(TokenType::ParenOpen))
+ parse_comma_separated_list(true, [&]() { column_names.append(consume(TokenType::Identifier).value()); });
consume(TokenType::As);
consume(TokenType::ParenOpen);
@@ -818,8 +756,7 @@ NonnullRefPtr<ReturningClause> Parser::parse_returning_clause()
return create_ast_node<ReturningClause>();
Vector<ReturningClause::ColumnClause> columns;
-
- do {
+ parse_comma_separated_list(false, [&]() {
auto expression = parse_expression();
String column_alias;
@@ -827,11 +764,7 @@ NonnullRefPtr<ReturningClause> Parser::parse_returning_clause()
column_alias = consume(TokenType::Identifier).value();
columns.append({ move(expression), move(column_alias) });
- if (!match(TokenType::Comma))
- break;
-
- consume(TokenType::Comma);
- } while (!match(TokenType::Eof));
+ });
return create_ast_node<ReturningClause>(move(columns));
}
@@ -888,18 +821,10 @@ NonnullRefPtr<TableOrSubquery> Parser::parse_table_or_subquery()
return create_ast_node<TableOrSubquery>(move(schema_name), move(table_name), move(table_alias));
}
- consume(TokenType::ParenOpen);
// FIXME: Parse join-clause.
NonnullRefPtrVector<TableOrSubquery> subqueries;
- while (!has_errors() && !match(TokenType::Eof)) {
- subqueries.append(parse_table_or_subquery());
- if (!match(TokenType::Comma))
- break;
- consume(TokenType::Comma);
- }
-
- consume(TokenType::ParenClose);
+ parse_comma_separated_list(true, [&]() { subqueries.append(parse_table_or_subquery()); });
return create_ast_node<TableOrSubquery>(move(subqueries));
}
diff --git a/Userland/Libraries/LibSQL/Parser.h b/Userland/Libraries/LibSQL/Parser.h
index 8e0419371c..827d60c37c 100644
--- a/Userland/Libraries/LibSQL/Parser.h
+++ b/Userland/Libraries/LibSQL/Parser.h
@@ -85,6 +85,25 @@ private:
NonnullRefPtr<TableOrSubquery> parse_table_or_subquery();
NonnullRefPtr<OrderingTerm> parse_ordering_term();
+ 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);