Skip to content

Commit b72bff1

Browse files
committed
refactor lexer
1 parent 911a079 commit b72bff1

File tree

9 files changed

+766
-703
lines changed

9 files changed

+766
-703
lines changed

lib/bnf.ex

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ defmodule SQL.BNF do
4343
cond do
4444
String.ends_with?(r, "word>") == true ->
4545
e = if is_map_key(opts, r), do: e ++ opts[r], else: e
46-
{[{r, (for v <- e, v not in ["|", "AS"], do: {atom(v), quoted_match(v), quoted_guard(v)})} | keywords], operators, letters, digits, terminals}
46+
{[{r, (for v <- e, v not in ["|", "AS"], do: {atom(v), quoted_inline_match(v)})} | keywords], operators, letters, digits, terminals}
4747
String.ends_with?(r, "letter>") == true -> {keywords, operators, [{r, Enum.reject(e, &(&1 == "|"))}|letters], digits, terminals}
4848
String.ends_with?(r, "digit>") == true -> {keywords, operators, letters, [{r, Enum.reject(e, &(&1 == "|"))}|digits], terminals}
4949
String.ends_with?(r, "operator>") == true -> {keywords, [rule | operators], letters, digits, terminals}
@@ -201,7 +201,7 @@ defmodule SQL.BNF do
201201
@doc false
202202
def cast(<<?<, b, _::binary>> = expr) when b in ?a..?z or b in ?A..?Z, do: expr
203203
def cast(expr) when expr in ["|", "{", "}", "[", "]", :ignore, :self, "\u0020", "\u0009", "\u000D", "\u00A0", "\u00A0", "\u1680", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006", "\u2007", "\u2008", "\u2009", "\u200A", "\u202F", "\u205F", "\u3000", "\u180E", "\u200B", "\u200C", "\u200D", "\u2060", "\uFEFF", "\u000A", "\u000B", "\u000C", "\u000D", "\u0085", "\u2028", "\u2029"], do: expr
204-
def cast(expr) when is_binary(expr), do: {atom(expr), quoted_match(expr), quoted_guard(expr)}
204+
def cast(expr) when is_binary(expr), do: {atom(expr), quoted_inline_match(expr)}
205205
def cast(expr) when is_tuple(expr) or is_list(expr) or is_atom(expr), do: expr
206206

207207
@doc false
@@ -213,34 +213,18 @@ defmodule SQL.BNF do
213213
if String.match?(e, ~r/[^A-Za-z]/) do
214214
{String.to_atom(e), quoted_inline_match(e)}
215215
else
216-
{atom(e), quoted_match(e), quoted_guard(e)}
216+
{atom(e), quoted_inline_match(e)}
217217
end
218218
end
219219
end
220220

221-
@doc false
222-
def quoted_match(value), do: Enum.reduce(1..byte_size(value), [], fn n, acc -> [{:"b#{n}", [], Elixir}|acc] end)
223-
224221
@doc false
225222
def quoted_inline_match(value) do
226-
for <<k <- value>>, reduce: [] do
223+
for <<k <- String.downcase(value)>>, reduce: [] do
227224
acc -> [k|acc]
228225
end
229226
end
230227

231-
@doc false
232-
def quoted_guard(value, acc \\ []) do
233-
{value, _n} = for <<k <- String.downcase(value)>>, reduce: {acc, 1} do
234-
{[], n} -> {__guard__(k, n), n+1}
235-
{acc, n} -> {{:and, [context: Elixir, imports: [{2, Kernel}]], [acc,__guard__(k, n)]}, n+1}
236-
end
237-
value
238-
end
239-
240-
@doc false
241-
def __guard__(k, n) do
242-
{:in, [context: Elixir, imports: [{2, Kernel}]],[{:"b#{n}", [], Elixir},{:sigil_c, [delimiter: "\"", context: Elixir, imports: [{2, Kernel}]],[{:<<>>, [], ["#{<<k>>}#{String.upcase(<<k>>)}"]}, []]}]}
243-
end
244228

245229
@doc false
246230
def get_rules() do

lib/format.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ defmodule SQL.Format do
1111
@doc since: "0.4.0"
1212
def to_iodata(tokens, context, indent \\ 0), do: newline(to_iodata(tokens, context.binding, context.case, context.errors, indent, []), indent)
1313

14-
defp indention(acc, [{:preset, {_,0}},_,{:offset, {_,0,_,_}}|_], 0), do: acc
14+
defp indention(acc, [{:preset, {_,0}},_,{:offset, {_,0,_,_}}|_], _), do: acc
1515
defp indention(acc, [_,{:offset, {_,0}}|_], 0), do: acc
16+
defp indention(["\e[33m"|_]=acc, [_,{:offset, {_,0}}|_], _), do: acc
1617
defp indention(acc, _, 0), do: [?\s|acc]
1718
defp indention(acc, _, 1), do: [?\s,?\s|acc]
1819
defp indention(acc, _, 2), do: [?\s,?\s,?\s,?\s|acc]

lib/formatter.ex

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ defmodule SQL.MixFormatter do
1313
opts = Map.new(Keyword.merge([validate: nil], opts))
1414
{:ok, context, tokens} = SQL.Lexer.lex(source)
1515
{:ok, context, tokens} = SQL.Parser.parse(tokens, Map.merge(context, opts))
16-
iodata = SQL.Format.to_iodata(tokens, context)
17-
if context.errors != [], do: IO.warn([?\n, SQL.format_error(context.errors), " \n ", iodata, ?\n])
18-
IO.iodata_to_binary(iodata)
16+
if context.errors != [], do: IO.warn([?\n,SQL.format_error(context.errors)," \n ",SQL.Format.to_iodata(tokens, context, 1),?\n])
17+
IO.iodata_to_binary(SQL.Format.to_iodata(tokens, context))
1918
end
2019
end

lib/lexer.ex

Lines changed: 749 additions & 673 deletions
Large diffs are not rendered by default.

lib/sql.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,12 @@ defmodule SQL do
215215

216216
@doc false
217217
def __inspect__(tokens, context, stack) do
218-
inspect = IO.iodata_to_binary(["\e[0m", " ~SQL\"\"\""|[SQL.Format.to_iodata(tokens, context, 1)|~c"\n \"\"\""]])
218+
inspect = IO.iodata_to_binary(["\e[0m", "~SQL\"\"\""|[SQL.Format.to_iodata(tokens, context)|~c"\n\"\"\""]])
219219
case context.errors do
220220
[] -> inspect
221221
errors ->
222222
{:current_stacktrace, [_|t]} = Process.info(self(), :current_stacktrace)
223-
IO.warn([?\n,format_error(errors), inspect], [stack|t])
223+
IO.warn([?\n,format_error(errors), IO.iodata_to_binary(["\e[0m", " ~SQL\"\"\""|[SQL.Format.to_iodata(tokens, context, 1)|~c"\n \"\"\""]])], [stack|t])
224224
inspect
225225
end
226226
end

lib/token.ex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ defmodule SQL.Token do
9090
defp __to_iodata__({tag, [_,_,{:type, type}|_]=m, [left, right]}, format, case, acc) when type == :operator or tag in ~w[between cursor for to union except intersect]a do
9191
to_iodata(left, format, case, indention(to_iodata(tag, format, case, to_iodata(right, format, case, acc)), format, m))
9292
end
93+
defp __to_iodata__({:ident, m, value}=node, format, :upper, acc) do
94+
indention([:string.uppercase(value)|acc], format, m)
95+
end
9396
defp __to_iodata__({tag, m, value}=node, format, _case, acc) when tag in ~w[ident numeric special]a do
9497
indention([value|acc], format, m)
9598
end

test/adapters/mysql_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ defmodule SQL.Adapters.MySQLTest do
181181
assert "select \"db.users.id\"" == to_string(~SQL[select "db.users.id"])
182182
assert "select 'db.users'" == to_string(~SQL[select 'db.users'])
183183
assert "select \"db.users.id\", 'db.users'" == to_string(~SQL[select "db.users.id", 'db.users'])
184-
assert "select X'616263'" == to_string(~SQL[select X'616263'])
184+
assert "select x'616263'" == to_string(~SQL[select X'616263'])
185185
end
186186
end
187187

test/lexer_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ defmodule SQL.LexerTest do
99
assert {:ok, _, [{:colon, [{:span, {1, 9, 1, 9}}, {:offset, {0, 0}}|_], _}|_]} = SQL.Lexer.lex("SELECT 1;\nSELECT 2;")
1010
end
1111
test "U+000D cr" do
12-
assert {:ok, _, [{:colon, [{:span, {0, 19, 0, 19}}, {:offset, {0, 0}}|_], _}|_]} = SQL.Lexer.lex("SELECT 1;\rSELECT 2;")
12+
assert {:ok, _, [{:colon, [{:span, {1, 9, 1, 9}}, {:offset, {0, 0}}|_], _}|_]} = SQL.Lexer.lex("SELECT 1;\rSELECT 2;")
1313
end
1414
test "U+000D+000A crlf" do
15-
assert {:ok, _, [{:colon, [{:span, {1, 9, 1, 9}}, {:offset, {0, 0}}|_], _}|_]} = SQL.Lexer.lex("SELECT 1;\r\nSELECT 2;")
15+
assert {:ok, _, [{:colon, [{:span, {2, 9, 2, 9}}, {:offset, {0, 0}}|_], _}|_]} = SQL.Lexer.lex("SELECT 1;\r\nSELECT 2;")
1616
end
1717
test "U+0085 nel" do
1818
assert {:ok, _, [{:colon, [{:span, {1, 9, 1, 9}}, {:offset, {0, 0}}|_], _}|_]} = SQL.Lexer.lex("SELECT 1;\u0085SELECT 2;")

test/sql_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ defmodule SQLTest do
4747

4848

4949
test "inspect/1" do
50-
assert ~s(\e[0m ~SQL"""\n \e[35mselect\e[0m\n \e[33m+1000\e[0m\n """) == inspect(~SQL[select +1000])
50+
assert ~s(\e[0m~SQL\"\"\"\n\e[35mselect\e[0m\n \e[35m+\e[0m\e[33m1000\e[0m\n\"\"\") == inspect(~SQL[select +1000])
5151
end
5252

5353
test "to_sql/1" do

0 commit comments

Comments
 (0)