Packages

Generate typed Gleam modules from a SQL schema file

Current section

Files

Jump to
glsql src glsql@parser.erl
Raw

src/glsql@parser.erl

-module(glsql@parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/glsql/parser.gleam").
-export([parse/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/glsql/parser.gleam", 98).
?DOC(" Consume tokens up to and including the next top-level `;`.\n").
-spec skip_statement(list(glsql@token:positioned())) -> list(glsql@token:positioned()).
skip_statement(Tokens) ->
case Tokens of
[] ->
[];
[{positioned, semicolon, _, _} | Rest] ->
Rest;
[_ | Rest@1] ->
skip_statement(Rest@1)
end.
-file("src/glsql/parser.gleam", 487).
-spec expect(list(glsql@token:positioned()), glsql@token:token(), binary()) -> {ok,
{integer(), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
expect(Tokens, Want, Label) ->
case Tokens of
[{positioned, T, Pos, _} | Rest] when T =:= Want ->
{ok, {Pos, Rest}};
[{positioned, T@1, Pos@1, _} | _] ->
{error,
{parse_error,
<<<<<<<<"Expected `"/utf8, Label/binary>>/binary,
"`, found `"/utf8>>/binary,
(glsql@token:to_string(T@1))/binary>>/binary,
"`"/utf8>>,
Pos@1,
none}};
[] ->
{error,
{parse_error,
<<<<"Unexpected end of file, expected `"/utf8,
Label/binary>>/binary,
"`"/utf8>>,
0,
none}}
end.
-file("src/glsql/parser.gleam", 446).
-spec identifier(list(glsql@token:positioned())) -> {ok,
{binary(), integer(), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
identifier(Tokens) ->
case Tokens of
[{positioned, {word, W}, Pos, _} | Rest] ->
{ok, {W, Pos, Rest}};
[{positioned, {quoted_ident, W@1}, Pos@1, _} | Rest@1] ->
{ok, {W@1, Pos@1, Rest@1}};
[{positioned, T, Pos@2, _} | _] ->
{error,
{parse_error,
<<<<"Expected a name, found `"/utf8,
(glsql@token:to_string(T))/binary>>/binary,
"`"/utf8>>,
Pos@2,
none}};
[] ->
{error,
{parse_error,
<<"Unexpected end of file, expected a name"/utf8>>,
0,
none}}
end.
-file("src/glsql/parser.gleam", 311).
-spec collect_names(list(glsql@token:positioned()), list(binary())) -> {ok,
{list(binary()), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
collect_names(Tokens, Acc) ->
gleam@result:'try'(
identifier(Tokens),
fun(_use0) ->
{Name, _, Rest} = _use0,
case Rest of
[{positioned, comma, _, _} | Rest@1] ->
collect_names(Rest@1, [Name | Acc]);
[{positioned, r_paren, _, _} | Rest@2] ->
{ok, {lists:reverse([Name | Acc]), Rest@2}};
[{positioned, T, Pos, _} | _] ->
{error,
{parse_error,
<<<<"Expected `,` or `)`, found `"/utf8,
(glsql@token:to_string(T))/binary>>/binary,
"`"/utf8>>,
Pos,
none}};
[] ->
{error,
{parse_error,
<<"Unexpected end of file in column list"/utf8>>,
0,
none}}
end
end
).
-file("src/glsql/parser.gleam", 302).
-spec optional_column_list(list(glsql@token:positioned())) -> {ok,
{list(binary()), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
optional_column_list(Tokens) ->
case Tokens of
[{positioned, l_paren, _, _} | Rest] ->
collect_names(Rest, []);
_ ->
{ok, {[], Tokens}}
end.
-file("src/glsql/parser.gleam", 433).
-spec qualified_name(list(glsql@token:positioned())) -> {ok,
{gleam@option:option(binary()),
binary(),
list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
qualified_name(Tokens) ->
gleam@result:'try'(
identifier(Tokens),
fun(_use0) ->
{First, _, Rest} = _use0,
case Rest of
[{positioned, dot, _, _} | Rest@1] ->
gleam@result:'try'(
identifier(Rest@1),
fun(_use0@1) ->
{Second, _, Rest@2} = _use0@1,
{ok, {{some, First}, Second, Rest@2}}
end
);
_ ->
{ok, {none, First, Rest}}
end
end
).
-file("src/glsql/parser.gleam", 364).
-spec join(binary(), binary()) -> binary().
join(Acc, Word) ->
case (Acc =:= <<""/utf8>>) orelse gleam_stdlib:string_ends_with(
Acc,
<<"("/utf8>>
) of
true ->
<<Acc/binary, Word/binary>>;
false ->
<<<<Acc/binary, " "/utf8>>/binary, Word/binary>>
end.
-file("src/glsql/parser.gleam", 332).
?DOC(
" Consume an expression to a balanced-paren boundary, stopping at a top-level\n"
" comma or closing paren. Retained as opaque source text — never interpreted.\n"
).
-spec take_expression(list(glsql@token:positioned()), binary(), integer()) -> {binary(),
list(glsql@token:positioned())}.
take_expression(Tokens, Acc, Depth) ->
case Tokens of
[] ->
{gleam@string:trim(Acc), []};
[{positioned, comma, _, _} | _] when Depth =:= 0 ->
{gleam@string:trim(Acc), Tokens};
[{positioned, r_paren, _, _} | _] when Depth =:= 0 ->
{gleam@string:trim(Acc), Tokens};
[{positioned, {word, W}, _, _} | Rest] when Depth =:= 0 ->
case gleam@list:contains(
[<<"not"/utf8>>,
<<"null"/utf8>>,
<<"primary"/utf8>>,
<<"unique"/utf8>>,
<<"default"/utf8>>,
<<"references"/utf8>>,
<<"check"/utf8>>,
<<"constraint"/utf8>>,
<<"foreign"/utf8>>,
<<"generated"/utf8>>,
<<"collate"/utf8>>],
string:lowercase(W)
) of
true ->
{gleam@string:trim(Acc), Tokens};
false ->
take_expression(Rest, join(Acc, W), Depth)
end;
[{positioned, l_paren, _, _} | Rest@1] ->
take_expression(Rest@1, <<Acc/binary, "("/utf8>>, Depth + 1);
[{positioned, r_paren, _, _} | Rest@2] ->
take_expression(Rest@2, <<Acc/binary, ")"/utf8>>, Depth - 1);
[{positioned, {word, W@1}, _, _} | Rest@3] ->
take_expression(Rest@3, join(Acc, W@1), Depth);
[{positioned, T, _, _} | Rest@4] ->
take_expression(
Rest@4,
<<Acc/binary, (glsql@token:to_string(T))/binary>>,
Depth
)
end.
-file("src/glsql/parser.gleam", 460).
-spec keyword(list(glsql@token:positioned()), binary()) -> {ok,
{integer(), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
keyword(Tokens, Want) ->
case Tokens of
[{positioned, {word, W}, Pos, _} | Rest] ->
case string:lowercase(W) =:= Want of
true ->
{ok, {Pos, Rest}};
false ->
{error,
{parse_error,
<<<<<<<<"Expected `"/utf8, Want/binary>>/binary,
"`, found `"/utf8>>/binary,
W/binary>>/binary,
"`"/utf8>>,
Pos,
none}}
end;
[{positioned, T, Pos@1, _} | _] ->
{error,
{parse_error,
<<<<<<<<"Expected `"/utf8, Want/binary>>/binary,
"`, found `"/utf8>>/binary,
(glsql@token:to_string(T))/binary>>/binary,
"`"/utf8>>,
Pos@1,
none}};
[] ->
{error,
{parse_error,
<<<<"Unexpected end of file, expected `"/utf8, Want/binary>>/binary,
"`"/utf8>>,
0,
none}}
end.
-file("src/glsql/parser.gleam", 172).
-spec parse_column_constraints(
list(glsql@token:positioned()),
list(glsql@ast:column_constraint())
) -> {ok, {list(glsql@ast:column_constraint()), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
parse_column_constraints(Tokens, Acc) ->
case Tokens of
[{positioned, comma, _, _} | _] ->
{ok, {Acc, Tokens}};
[{positioned, r_paren, _, _} | _] ->
{ok, {Acc, Tokens}};
[] ->
{ok, {Acc, Tokens}};
[{positioned, {word, W}, Pos, _} | Rest] ->
case string:lowercase(W) of
<<"not"/utf8>> ->
gleam@result:'try'(
keyword(Rest, <<"null"/utf8>>),
fun(_use0) ->
{_, Rest@1} = _use0,
parse_column_constraints(
Rest@1,
[{not_null, Pos} | Acc]
)
end
);
<<"null"/utf8>> ->
parse_column_constraints(Rest, [{nullable, Pos} | Acc]);
<<"primary"/utf8>> ->
gleam@result:'try'(
keyword(Rest, <<"key"/utf8>>),
fun(_use0@1) ->
{_, Rest@2} = _use0@1,
parse_column_constraints(
Rest@2,
[{primary_key, Pos} | Acc]
)
end
);
<<"unique"/utf8>> ->
parse_column_constraints(Rest, [{unique, Pos} | Acc]);
<<"default"/utf8>> ->
{Expr, Rest@3} = take_expression(Rest, <<""/utf8>>, 0),
parse_column_constraints(
Rest@3,
[{default, Expr, Pos} | Acc]
);
<<"check"/utf8>> ->
{Expr@1, Rest@4} = take_expression(Rest, <<""/utf8>>, 0),
parse_column_constraints(
Rest@4,
[{check, Expr@1, Pos} | Acc]
);
<<"references"/utf8>> ->
gleam@result:'try'(
qualified_name(Rest),
fun(_use0@2) ->
{_, Tbl, Rest@5} = _use0@2,
gleam@result:'try'(
optional_column_list(Rest@5),
fun(_use0@3) ->
{Cols, Rest@6} = _use0@3,
parse_column_constraints(
Rest@6,
[{references, Tbl, Cols, Pos} | Acc]
)
end
)
end
);
Other ->
{error,
{parse_error,
<<<<"Unknown column constraint `"/utf8, W/binary>>/binary,
"`"/utf8>>,
Pos,
glsql@suggest:closest(
Other,
[<<"not"/utf8>>,
<<"null"/utf8>>,
<<"primary"/utf8>>,
<<"unique"/utf8>>,
<<"default"/utf8>>,
<<"references"/utf8>>,
<<"check"/utf8>>,
<<"constraint"/utf8>>,
<<"foreign"/utf8>>,
<<"generated"/utf8>>,
<<"collate"/utf8>>]
)}}
end;
[{positioned, T, Pos@1, _} | _] ->
{error,
{parse_error,
<<<<"Unexpected `"/utf8, (glsql@token:to_string(T))/binary>>/binary,
"` in column definition"/utf8>>,
Pos@1,
none}}
end.
-file("src/glsql/parser.gleam", 402).
-spec parse_array_dims(list(glsql@token:positioned()), integer()) -> {integer(),
list(glsql@token:positioned())}.
parse_array_dims(Tokens, Count) ->
case Tokens of
[{positioned, l_bracket, _, _}, {positioned, r_bracket, _, _} | Rest] ->
parse_array_dims(Rest, Count + 1);
_ ->
{Count, Tokens}
end.
-file("src/glsql/parser.gleam", 385).
-spec collect_args(list(glsql@token:positioned()), list(binary())) -> {ok,
{list(binary()), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
collect_args(Tokens, Acc) ->
case Tokens of
[{positioned, {number, N}, _, _}, {positioned, comma, _, _} | Rest] ->
collect_args(Rest, [N | Acc]);
[{positioned, {number, N@1}, _, _},
{positioned, r_paren, _, _} |
Rest@1] ->
{ok, {lists:reverse([N@1 | Acc]), Rest@1}};
[{positioned, {word, W}, _, _}, {positioned, r_paren, _, _} | Rest@2] ->
{ok, {lists:reverse([W | Acc]), Rest@2}};
[{positioned, _, Pos, _} | _] ->
{error,
{parse_error, <<"Expected a type argument"/utf8>>, Pos, none}};
[] ->
{error,
{parse_error,
<<"Unexpected end of file in type arguments"/utf8>>,
0,
none}}
end.
-file("src/glsql/parser.gleam", 378).
-spec parse_type_args(list(glsql@token:positioned())) -> {ok,
{list(binary()), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
parse_type_args(Tokens) ->
case Tokens of
[{positioned, l_paren, _, _} | Rest] ->
collect_args(Rest, []);
_ ->
{ok, {[], Tokens}}
end.
-file("src/glsql/parser.gleam", 371).
-spec parse_type(list(glsql@token:positioned())) -> {ok,
{glsql@ast:sql_type(), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
parse_type(Tokens) ->
gleam@result:'try'(
identifier(Tokens),
fun(_use0) ->
{Name, Pos, Rest} = _use0,
gleam@result:'try'(
parse_type_args(Rest),
fun(_use0@1) ->
{Args, Rest@1} = _use0@1,
{Dims, Rest@2} = parse_array_dims(Rest@1, 0),
{ok, {{sql_type, Name, Args, Dims, Pos}, Rest@2}}
end
)
end
).
-file("src/glsql/parser.gleam", 157).
-spec parse_column(list(glsql@token:positioned())) -> {ok,
{glsql@ast:column(), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
parse_column(Tokens) ->
gleam@result:'try'(
identifier(Tokens),
fun(_use0) ->
{Name, Pos, Rest} = _use0,
gleam@result:'try'(
parse_type(Rest),
fun(_use0@1) ->
{Sql_type, Rest@1} = _use0@1,
gleam@result:'try'(
parse_column_constraints(Rest@1, []),
fun(_use0@2) ->
{Constraints, Rest@2} = _use0@2,
{ok,
{{column,
Name,
Sql_type,
lists:reverse(Constraints),
Pos},
Rest@2}}
end
)
end
)
end
).
-file("src/glsql/parser.gleam", 286).
-spec skip_constraint_name(list(glsql@token:positioned())) -> list(glsql@token:positioned()).
skip_constraint_name(Tokens) ->
case Tokens of
[{positioned, {word, W}, _, _} | Rest] ->
case string:lowercase(W) of
<<"constraint"/utf8>> ->
case Rest of
[{positioned, {word, _}, _, _} | Rest@1] ->
Rest@1;
[{positioned, {quoted_ident, _}, _, _} | Rest@2] ->
Rest@2;
_ ->
Rest
end;
_ ->
Tokens
end;
_ ->
Tokens
end.
-file("src/glsql/parser.gleam", 275).
-spec continue_table_constraints(
list(glsql@token:positioned()),
list(glsql@ast:table_constraint())
) -> {ok, {list(glsql@ast:table_constraint()), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
continue_table_constraints(Tokens, Acc) ->
case Tokens of
[{positioned, comma, _, _} | Rest] ->
parse_table_constraints(Rest, Acc);
_ ->
{ok, {lists:reverse(Acc), Tokens}}
end.
-file("src/glsql/parser.gleam", 226).
-spec parse_table_constraints(
list(glsql@token:positioned()),
list(glsql@ast:table_constraint())
) -> {ok, {list(glsql@ast:table_constraint()), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
parse_table_constraints(Tokens, Acc) ->
Tokens@1 = skip_constraint_name(Tokens),
case Tokens@1 of
[{positioned, {word, W}, Pos, _} | Rest] ->
case string:lowercase(W) of
<<"primary"/utf8>> ->
gleam@result:'try'(
keyword(Rest, <<"key"/utf8>>),
fun(_use0) ->
{_, Rest@1} = _use0,
gleam@result:'try'(
optional_column_list(Rest@1),
fun(_use0@1) ->
{Cols, Rest@2} = _use0@1,
continue_table_constraints(
Rest@2,
[{table_primary_key, Cols, Pos} | Acc]
)
end
)
end
);
<<"unique"/utf8>> ->
gleam@result:'try'(
optional_column_list(Rest),
fun(_use0@2) ->
{Cols@1, Rest@3} = _use0@2,
continue_table_constraints(
Rest@3,
[{table_unique, Cols@1, Pos} | Acc]
)
end
);
<<"foreign"/utf8>> ->
gleam@result:'try'(
keyword(Rest, <<"key"/utf8>>),
fun(_use0@3) ->
{_, Rest@4} = _use0@3,
gleam@result:'try'(
optional_column_list(Rest@4),
fun(_use0@4) ->
{Cols@2, Rest@5} = _use0@4,
gleam@result:'try'(
keyword(Rest@5, <<"references"/utf8>>),
fun(_use0@5) ->
{_, Rest@6} = _use0@5,
gleam@result:'try'(
qualified_name(Rest@6),
fun(_use0@6) ->
{_, Tbl, Rest@7} = _use0@6,
gleam@result:'try'(
optional_column_list(
Rest@7
),
fun(_use0@7) ->
{Ref, Rest@8} = _use0@7,
continue_table_constraints(
Rest@8,
[{table_foreign_key,
Cols@2,
Tbl,
Ref,
Pos} |
Acc]
)
end
)
end
)
end
)
end
)
end
);
<<"check"/utf8>> ->
{Expr, Rest@9} = take_expression(Rest, <<""/utf8>>, 0),
continue_table_constraints(
Rest@9,
[{table_check, Expr, Pos} | Acc]
);
Other ->
{error,
{parse_error,
<<<<"Unknown table constraint `"/utf8, W/binary>>/binary,
"`"/utf8>>,
Pos,
glsql@suggest:closest(
Other,
[<<"not"/utf8>>,
<<"null"/utf8>>,
<<"primary"/utf8>>,
<<"unique"/utf8>>,
<<"default"/utf8>>,
<<"references"/utf8>>,
<<"check"/utf8>>,
<<"constraint"/utf8>>,
<<"foreign"/utf8>>,
<<"generated"/utf8>>,
<<"collate"/utf8>>]
)}}
end;
[{positioned, T, Pos@1, _} | _] ->
{error,
{parse_error,
<<<<"Expected a table constraint, found `"/utf8,
(glsql@token:to_string(T))/binary>>/binary,
"`"/utf8>>,
Pos@1,
none}};
[] ->
{error,
{parse_error,
<<"Unexpected end of file in table constraints"/utf8>>,
0,
none}}
end.
-file("src/glsql/parser.gleam", 146).
-spec is_table_constraint(list(glsql@token:positioned())) -> boolean().
is_table_constraint(Tokens) ->
case Tokens of
[{positioned, {word, W}, _, _} | _] ->
case string:lowercase(W) of
<<"primary"/utf8>> ->
true;
<<"unique"/utf8>> ->
true;
<<"foreign"/utf8>> ->
true;
<<"check"/utf8>> ->
true;
<<"constraint"/utf8>> ->
true;
_ ->
false
end;
_ ->
false
end.
-file("src/glsql/parser.gleam", 126).
-spec parse_column_list(
list(glsql@token:positioned()),
list(glsql@ast:column())
) -> {ok,
{list(glsql@ast:column()),
list(glsql@ast:table_constraint()),
list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
parse_column_list(Tokens, Acc) ->
case is_table_constraint(Tokens) of
true ->
gleam@result:'try'(
parse_table_constraints(Tokens, []),
fun(_use0) ->
{Constraints, Rest} = _use0,
{ok, {Acc, Constraints, Rest}}
end
);
false ->
gleam@result:'try'(
parse_column(Tokens),
fun(_use0@1) ->
{Column, Rest@1} = _use0@1,
case Rest@1 of
[{positioned, comma, _, _} | Rest@2] ->
parse_column_list(Rest@2, [Column | Acc]);
_ ->
{ok, {[Column | Acc], [], Rest@1}}
end
end
)
end.
-file("src/glsql/parser.gleam", 413).
-spec skip_if_not_exists(list(glsql@token:positioned())) -> list(glsql@token:positioned()).
skip_if_not_exists(Tokens) ->
case Tokens of
[{positioned, {word, A}, _, _},
{positioned, {word, B}, _, _},
{positioned, {word, C}, _, _} |
Rest] ->
case {string:lowercase(A), string:lowercase(B), string:lowercase(C)} of
{<<"if"/utf8>>, <<"not"/utf8>>, <<"exists"/utf8>>} ->
Rest;
{_, _, _} ->
Tokens
end;
_ ->
Tokens
end.
-file("src/glsql/parser.gleam", 106).
-spec parse_create_table(list(glsql@token:positioned())) -> {ok,
{glsql@ast:table(), list(glsql@token:positioned())}} |
{error, glsql@error:error()}.
parse_create_table(Tokens) ->
gleam@result:'try'(
keyword(Tokens, <<"create"/utf8>>),
fun(_use0) ->
{Pos, Rest} = _use0,
gleam@result:'try'(
keyword(Rest, <<"table"/utf8>>),
fun(_use0@1) ->
{_, Rest@1} = _use0@1,
Rest@2 = skip_if_not_exists(Rest@1),
gleam@result:'try'(
qualified_name(Rest@2),
fun(_use0@2) ->
{Schema, Name, Rest@3} = _use0@2,
gleam@result:'try'(
expect(Rest@3, l_paren, <<"("/utf8>>),
fun(_use0@3) ->
{_, Rest@4} = _use0@3,
gleam@result:'try'(
parse_column_list(Rest@4, []),
fun(_use0@4) ->
{Columns, Constraints, Rest@5} = _use0@4,
gleam@result:'try'(
expect(
Rest@5,
r_paren,
<<")"/utf8>>
),
fun(_use0@5) ->
{_, Rest@6} = _use0@5,
{ok,
{{table,
Name,
Schema,
lists:reverse(
Columns
),
Constraints,
Pos},
Rest@6}}
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/glsql/parser.gleam", 39).
-spec parse_statements(list(glsql@token:positioned()), list(glsql@ast:table())) -> {ok,
list(glsql@ast:table())} |
{error, glsql@error:error()}.
parse_statements(Tokens, Acc) ->
case Tokens of
[] ->
{ok, Acc};
[{positioned, semicolon, _, _} | Rest] ->
parse_statements(Rest, Acc);
[{positioned, {word, W}, Pos, _} | Rest@1] ->
case string:lowercase(W) of
<<"create"/utf8>> ->
case Rest@1 of
[{positioned, {word, Obj}, Obj_pos, _} | After] ->
case string:lowercase(Obj) of
<<"table"/utf8>> ->
gleam@result:'try'(
parse_create_table(Tokens),
fun(_use0) ->
{Table, Rest@2} = _use0,
parse_statements(
Rest@2,
[Table | Acc]
)
end
);
Other ->
case gleam@list:contains(
[<<"index"/utf8>>,
<<"unique"/utf8>>,
<<"extension"/utf8>>,
<<"sequence"/utf8>>,
<<"view"/utf8>>,
<<"schema"/utf8>>,
<<"function"/utf8>>,
<<"trigger"/utf8>>,
<<"type"/utf8>>,
<<"domain"/utf8>>,
<<"materialized"/utf8>>,
<<"publication"/utf8>>,
<<"policy"/utf8>>,
<<"aggregate"/utf8>>,
<<"operator"/utf8>>,
<<"role"/utf8>>,
<<"database"/utf8>>],
Other
) of
true ->
parse_statements(
skip_statement(After),
Acc
);
false ->
{error,
{unknown_statement,
Obj,
Obj_pos,
glsql@suggest:closest(
Other,
[<<"table"/utf8>> |
[<<"index"/utf8>>,
<<"unique"/utf8>>,
<<"extension"/utf8>>,
<<"sequence"/utf8>>,
<<"view"/utf8>>,
<<"schema"/utf8>>,
<<"function"/utf8>>,
<<"trigger"/utf8>>,
<<"type"/utf8>>,
<<"domain"/utf8>>,
<<"materialized"/utf8>>,
<<"publication"/utf8>>,
<<"policy"/utf8>>,
<<"aggregate"/utf8>>,
<<"operator"/utf8>>,
<<"role"/utf8>>,
<<"database"/utf8>>]]
)}}
end
end;
_ ->
{error,
{parse_error,
<<"Unexpected end of file after `create`"/utf8>>,
Pos,
none}}
end;
Other@1 ->
case gleam@list:contains(
[<<"alter"/utf8>>,
<<"drop"/utf8>>,
<<"set"/utf8>>,
<<"comment"/utf8>>,
<<"grant"/utf8>>,
<<"revoke"/utf8>>,
<<"begin"/utf8>>,
<<"commit"/utf8>>,
<<"insert"/utf8>>,
<<"update"/utf8>>,
<<"delete"/utf8>>,
<<"select"/utf8>>,
<<"truncate"/utf8>>,
<<"analyze"/utf8>>,
<<"vacuum"/utf8>>,
<<"refresh"/utf8>>,
<<"reset"/utf8>>,
<<"with"/utf8>>],
Other@1
) of
true ->
parse_statements(skip_statement(Rest@1), Acc);
false ->
{error,
{unknown_statement,
W,
Pos,
glsql@suggest:closest(
Other@1,
[<<"create"/utf8>>,
<<"alter"/utf8>>,
<<"drop"/utf8>>,
<<"set"/utf8>>,
<<"comment"/utf8>>]
)}}
end
end;
[{positioned, T, Pos@1, _} | _] ->
{error,
{parse_error,
<<<<"Expected a statement, found `"/utf8,
(glsql@token:to_string(T))/binary>>/binary,
"`"/utf8>>,
Pos@1,
none}}
end.
-file("src/glsql/parser.gleam", 34).
-spec parse(list(glsql@token:positioned())) -> {ok, glsql@ast:schema_ast()} |
{error, glsql@error:error()}.
parse(Tokens) ->
gleam@result:'try'(
parse_statements(Tokens, []),
fun(Tables) -> {ok, {schema_ast, lists:reverse(Tables)}} end
).