Skip to content

Commit 43027c7

Browse files
authored
Merge pull request #12 from Tubitv/master
Format and improvements
2 parents 69363d1 + 4ad79f1 commit 43027c7

File tree

12 files changed

+452
-259
lines changed

12 files changed

+452
-259
lines changed

.github/workflows/ci.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
name: Test suite
12+
runs-on: ubuntu-latest
13+
14+
strategy:
15+
matrix:
16+
combination:
17+
- { otp: "25", elixir: "1.14" }
18+
- { otp: "26", elixir: "1.16" }
19+
- { otp: "27", elixir: "1.18" }
20+
21+
env:
22+
MIX_ENV: test
23+
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- name: Set up Elixir
28+
uses: erlef/setup-beam@v1
29+
with:
30+
otp-version: ${{ matrix.combination.otp }}
31+
elixir-version: ${{ matrix.combination.elixir }}
32+
33+
- name: Install dependencies
34+
run: mix deps.get --only test
35+
36+
- name: Run tests
37+
run: mix test

.tool-versions

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
elixir 1.18.2-otp-27
2+
erlang 27.2.4

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ which results in the following captures:
149149

150150

151151
More elaborate examples can be found in [examples_test.exs](/test/examples_test.exs),
152-
including a parser for arithmatic expressions and a full JSON parser.
152+
including a parser for arithmetic expressions and a full JSON parser.
153153

154154

155155
## Grammars

lib/codegen.ex

Lines changed: 120 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ defmodule Xpeg.Codegen do
22
@moduledoc false
33

44
defp emit_inst(ip, inst, options) do
5-
65
case inst do
76
{:nop} ->
87
quote location: :keep do
98
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
10-
parse(unquote(ip+1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
9+
parse(unquote(ip + 1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
1110
end
1211
end
1312

@@ -16,42 +15,100 @@ defmodule Xpeg.Codegen do
1615
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
1716
parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures, unquote(n))
1817
end
18+
1919
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures, n) do
2020
case {s, n} do
21-
{[_|s2], 1} -> parse(unquote(ip+1), s2, si+1, ctx, back_stack, ret_stack, cap_stack, captures)
22-
{[_|s2], m} -> parse(unquote(ip), s2, si+1, ctx, back_stack, ret_stack, cap_stack, captures, m-1)
23-
{[], _} -> parse(:fail, [], si, ctx, back_stack, ret_stack, cap_stack, captures)
21+
{[_ | s2], 1} ->
22+
parse(
23+
unquote(ip + 1),
24+
s2,
25+
si + 1,
26+
ctx,
27+
back_stack,
28+
ret_stack,
29+
cap_stack,
30+
captures
31+
)
32+
33+
{[_ | s2], m} ->
34+
parse(
35+
unquote(ip),
36+
s2,
37+
si + 1,
38+
ctx,
39+
back_stack,
40+
ret_stack,
41+
cap_stack,
42+
captures,
43+
m - 1
44+
)
45+
46+
{[], _} ->
47+
parse(:fail, [], si, ctx, back_stack, ret_stack, cap_stack, captures)
2448
end
2549
end
2650
end
2751

2852
{:chr, cmatch} ->
2953
quote location: :keep do
30-
def parse(unquote(ip), s=[c|s2], si, ctx, back_stack, ret_stack, cap_stack, captures) when c == unquote(cmatch) do
31-
parse(unquote(ip+1), s2, si+1, ctx, back_stack, ret_stack, cap_stack, captures)
54+
def parse(
55+
unquote(ip),
56+
s = [c | s2],
57+
si,
58+
ctx,
59+
back_stack,
60+
ret_stack,
61+
cap_stack,
62+
captures
63+
)
64+
when c == unquote(cmatch) do
65+
parse(unquote(ip + 1), s2, si + 1, ctx, back_stack, ret_stack, cap_stack, captures)
3266
end
67+
3368
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
3469
parse(:fail, s, si, ctx, back_stack, ret_stack, cap_stack, captures)
3570
end
3671
end
3772

3873
{:set, cs} ->
3974
quote location: :keep do
40-
def parse(unquote(ip), s=[c|s2], si, ctx, back_stack, ret_stack, cap_stack, captures) when c in unquote(cs) do
41-
parse(unquote(ip+1), s2, si+1, ctx, back_stack, ret_stack, cap_stack, captures)
75+
def parse(
76+
unquote(ip),
77+
s = [c | s2],
78+
si,
79+
ctx,
80+
back_stack,
81+
ret_stack,
82+
cap_stack,
83+
captures
84+
)
85+
when c in unquote(cs) do
86+
parse(unquote(ip + 1), s2, si + 1, ctx, back_stack, ret_stack, cap_stack, captures)
4287
end
88+
4389
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
4490
parse(:fail, s, si, ctx, back_stack, ret_stack, cap_stack, captures)
4591
end
4692
end
4793

4894
{:span, cs} ->
4995
quote location: :keep do
50-
def parse(unquote(ip), s=[c|s2], si, ctx, back_stack, ret_stack, cap_stack, captures) when c in unquote(cs) do
51-
parse(unquote(ip), s2, si+1, ctx, back_stack, ret_stack, cap_stack, captures)
96+
def parse(
97+
unquote(ip),
98+
s = [c | s2],
99+
si,
100+
ctx,
101+
back_stack,
102+
ret_stack,
103+
cap_stack,
104+
captures
105+
)
106+
when c in unquote(cs) do
107+
parse(unquote(ip), s2, si + 1, ctx, back_stack, ret_stack, cap_stack, captures)
52108
end
109+
53110
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
54-
parse(unquote(ip+1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
111+
parse(unquote(ip + 1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
55112
end
56113
end
57114

@@ -61,6 +118,7 @@ defmodule Xpeg.Codegen do
61118
case ret_stack do
62119
[ip | ret_stack] ->
63120
parse(ip, s, si, ctx, back_stack, ret_stack, cap_stack, captures)
121+
64122
[] ->
65123
{ctx, s, si, :ok, cap_stack, captures}
66124
end
@@ -70,25 +128,25 @@ defmodule Xpeg.Codegen do
70128
{:choice, ip_back, ip_commit} ->
71129
quote location: :keep do
72130
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
73-
frame = { unquote(ip_back), unquote(ip_commit), ret_stack, cap_stack, s, si }
131+
frame = {unquote(ip_back), unquote(ip_commit), ret_stack, cap_stack, s, si}
74132
back_stack = [frame | back_stack]
75-
parse(unquote(ip+1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
133+
parse(unquote(ip + 1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
76134
end
77135
end
78136

79137
{:commit} ->
80138
quote location: :keep do
81139
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
82140
[frame | back_stack] = back_stack
83-
{ _, ip, _, _, _, _ } = frame
141+
{_, ip, _, _, _, _} = frame
84142
parse(ip, s, si, ctx, back_stack, ret_stack, cap_stack, captures)
85143
end
86144
end
87145

88146
{:call, addr} ->
89147
quote location: :keep do
90148
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
91-
ret_stack = [unquote(ip+1) | ret_stack]
149+
ret_stack = [unquote(ip + 1) | ret_stack]
92150
parse(unquote(addr), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
93151
end
94152
end
@@ -104,15 +162,15 @@ defmodule Xpeg.Codegen do
104162
quote location: :keep do
105163
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
106164
cap_stack = [{:open, s, si} | cap_stack]
107-
parse(unquote(ip+1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
165+
parse(unquote(ip + 1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
108166
end
109167
end
110168

111169
{:capclose, type} ->
112-
quote location: :keep do
170+
quote location: :keep do
113171
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
114172
cap_stack = [{:close, s, si, unquote(type)} | cap_stack]
115-
parse(unquote(ip+1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
173+
parse(unquote(ip + 1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
116174
end
117175
end
118176

@@ -121,11 +179,14 @@ defmodule Xpeg.Codegen do
121179
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
122180
{cap_stack, captures} = Xpeg.collect_captures(cap_stack, captures)
123181
func = unquote(code)
124-
{captures, ctx} = case unquote(options[:userdata]) do
125-
true -> func.(captures, ctx)
126-
_ -> {func.(captures), ctx}
127-
end
128-
parse(unquote(ip+1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
182+
183+
{captures, ctx} =
184+
case unquote(options[:userdata]) do
185+
true -> func.(captures, ctx)
186+
_ -> {func.(captures), ctx}
187+
end
188+
189+
parse(unquote(ip + 1), s, si, ctx, back_stack, ret_stack, cap_stack, captures)
129190
end
130191
end
131192

@@ -134,8 +195,9 @@ defmodule Xpeg.Codegen do
134195
def parse(unquote(ip), s, si, ctx, back_stack, ret_stack, cap_stack, captures) do
135196
case back_stack do
136197
[frame | back_stack] ->
137-
{ ip, _, ret_stack, cap_stack, s, si } = frame
198+
{ip, _, ret_stack, cap_stack, s, si} = frame
138199
parse(ip, s, si, ctx, back_stack, ret_stack, cap_stack, captures)
200+
139201
[] ->
140202
{ctx, s, si, :error, cap_stack, captures}
141203
end
@@ -144,50 +206,59 @@ defmodule Xpeg.Codegen do
144206
end
145207
end
146208

147-
148209
def add_trace(options, ast, ip, inst) do
149210
if options[:trace] do
150-
{ast, _} = Macro.prewalk(ast, false, fn
151-
{:do, body}, false ->
152-
body = quote do
153-
Xpeg.trace(unquote(ip), unquote(inspect(inst)), s)
154-
unquote(body)
155-
end
156-
{{:do, body}, true}
157-
e, done -> {e, done}
158-
end)
211+
{ast, _} =
212+
Macro.prewalk(ast, false, fn
213+
{:do, body}, false ->
214+
body =
215+
quote do
216+
Xpeg.trace(unquote(ip), unquote(inspect(inst)), s)
217+
unquote(body)
218+
end
219+
220+
{{:do, body}, true}
221+
222+
e, done ->
223+
{e, done}
224+
end)
225+
159226
ast
160227
else
161228
ast
162229
end
163230
end
164231

165-
166232
def emit(program, options \\ []) do
233+
ast =
234+
Enum.reduce(program.instructions, [], fn {ip, inst}, defs ->
235+
ast = emit_inst(ip, inst, options)
167236

168-
ast = Enum.reduce(program.instructions, [], fn {ip, inst}, defs ->
169-
ast = emit_inst(ip, inst, options)
170-
case ast do
171-
{:__block__, _, subs} ->
172-
Enum.map(subs, &add_trace(options, &1, ip, inst)) ++ defs
173-
_ -> [add_trace(options, ast, ip, inst) | defs]
174-
end
175-
end)
237+
case ast do
238+
{:__block__, _, subs} ->
239+
Enum.map(subs, &add_trace(options, &1, ip, inst)) ++ defs
240+
241+
_ ->
242+
[add_trace(options, ast, ip, inst) | defs]
243+
end
244+
end)
176245

177246
ast = {
178-
:__block__, [], [quote do
179-
require Xpeg
180-
end ] ++ ast
247+
:__block__,
248+
[],
249+
[
250+
quote do
251+
require Xpeg
252+
end
253+
] ++ ast
181254
}
182255

183256
if options[:dump_code] do
184257
IO.puts(Macro.to_string(ast))
185258
end
186259

187260
Macro.escape(ast)
188-
189261
end
190-
191262
end
192263

193264
# set ft=elixir

0 commit comments

Comments
 (0)