Skip to content

Commit 9d03032

Browse files
committed
Add line and column to EEx tokenizer
1 parent 3c4c68b commit 9d03032

File tree

3 files changed

+90
-67
lines changed

3 files changed

+90
-67
lines changed

lib/eex/lib/eex/compiler.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ defmodule EEx.Compiler do
4141
# Generates the buffers by handling each expression from the tokenizer.
4242
# It returns Macro.t/0 or it raises.
4343

44-
defp generate_buffer([{:text, chars} | rest], buffer, scope, state) do
44+
defp generate_buffer([{:text, _line, _column, chars} | rest], buffer, scope, state) do
4545
buffer = state.engine.handle_text(buffer, IO.chardata_to_string(chars))
4646
generate_buffer(rest, buffer, scope, state)
4747
end
@@ -179,7 +179,7 @@ defmodule EEx.Compiler do
179179
# Look middle expressions that immediately follow a start_expr
180180

181181
defp look_ahead_middle(
182-
[{:text, text}, {:middle_expr, line, _column, _, chars} | rest] = tokens,
182+
[{:text, _, _, text}, {:middle_expr, line, _, _, chars} | rest] = tokens,
183183
start,
184184
contents
185185
) do

lib/eex/lib/eex/tokenizer.ex

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ defmodule EEx.Tokenizer do
66
@type column :: non_neg_integer
77
@type marker :: '=' | '/' | '|' | ''
88
@type token ::
9-
{:text, content}
9+
{:text, line, column, content}
1010
| {:expr | :start_expr | :middle_expr | :end_expr, line, column, marker, content}
1111
| {:eof, line, column}
1212

@@ -17,7 +17,7 @@ defmodule EEx.Tokenizer do
1717
1818
It returns {:ok, list} with the following tokens:
1919
20-
* `{:text, content}`
20+
* `{:text, line, column, content}`
2121
* `{:expr, line, column, marker, content}`
2222
* `{:start_expr, line, column, marker, content}`
2323
* `{:middle_expr, line, column, marker, content}`
@@ -36,8 +36,11 @@ defmodule EEx.Tokenizer do
3636
def tokenize(list, line, column, opts)
3737
when is_list(list) and is_integer(line) and line >= 0 and is_integer(column) and column >= 0 do
3838
column = opts.indentation + column
39-
{list, line, column} = (opts.trim && trim_init(list, line, column)) || {list, line, column}
40-
tokenize(list, line, column, opts, [], [])
39+
40+
{list, line, column} =
41+
(opts.trim && trim_init(list, line, column, opts)) || {list, line, column}
42+
43+
tokenize(list, line, column, opts, [{line, column}], [])
4144
end
4245

4346
defp tokenize('<%%' ++ t, line, column, opts, buffer, acc) do
@@ -53,7 +56,8 @@ defmodule EEx.Tokenizer do
5356
{rest, new_line, new_column, buffer} =
5457
trim_if_needed(rest, new_line, new_column, opts, buffer)
5558

56-
tokenize(rest, new_line, new_column, opts, buffer, acc)
59+
acc = tokenize_text(buffer, acc)
60+
tokenize(rest, new_line, new_column, opts, [{new_line, new_column}], acc)
5761
end
5862
end
5963

@@ -76,7 +80,7 @@ defmodule EEx.Tokenizer do
7680

7781
acc = tokenize_text(buffer, acc)
7882
final = {key, line, column, marker, expr}
79-
tokenize(rest, new_line, new_column, opts, [], [final | acc])
83+
tokenize(rest, new_line, new_column, opts, [{new_line, new_column}], [final | acc])
8084
end
8185
end
8286

@@ -164,49 +168,67 @@ defmodule EEx.Tokenizer do
164168
# Tokenize the buffered text by appending
165169
# it to the given accumulator.
166170

167-
defp tokenize_text([], acc) do
171+
defp tokenize_text([{_line, _column}], acc) do
168172
acc
169173
end
170174

171175
defp tokenize_text(buffer, acc) do
172-
[{:text, Enum.reverse(buffer)} | acc]
176+
[{line, column} | buffer] = Enum.reverse(buffer)
177+
[{:text, line, column, buffer} | acc]
173178
end
174179

175180
defp trim_if_needed(rest, line, column, opts, buffer) do
176181
if opts.trim do
177182
buffer = trim_left(buffer, 0)
178-
{rest, line, column} = trim_right(rest, line, column, 0)
183+
{rest, line, column} = trim_right(rest, line, column, 0, opts)
179184
{rest, line, column, buffer}
180185
else
181186
{rest, line, column, buffer}
182187
end
183188
end
184189

185-
defp trim_init([h | t], line, column) when h in @spaces, do: trim_init(t, line, column + 1)
186-
defp trim_init([?\r, ?\n | t], line, _column), do: trim_init(t, line + 1, 1)
187-
defp trim_init([?\n | t], line, _column), do: trim_init(t, line + 1, 1)
188-
defp trim_init([?<, ?% | _] = rest, line, column), do: {rest, line, column}
189-
defp trim_init(_, _, _), do: false
190+
defp trim_init([h | t], line, column, opts) when h in @spaces,
191+
do: trim_init(t, line, column + 1, opts)
192+
193+
defp trim_init([?\r, ?\n | t], line, _column, opts),
194+
do: trim_init(t, line + 1, opts.indentation + 1, opts)
195+
196+
defp trim_init([?\n | t], line, _column, opts),
197+
do: trim_init(t, line + 1, opts.indentation + 1, opts)
198+
199+
defp trim_init([?<, ?% | _] = rest, line, column, _opts),
200+
do: {rest, line, column}
201+
202+
defp trim_init(_, _, _, _), do: false
190203

191204
defp trim_left(buffer, count) do
192-
case trim_whitespace(buffer) do
193-
[?\n, ?\r | rest] -> trim_left(rest, count + 1)
194-
[?\n | rest] -> trim_left(rest, count + 1)
205+
case trim_whitespace(buffer, 0) do
206+
{[?\n, ?\r | rest], _} -> trim_left(rest, count + 1)
207+
{[?\n | rest], _} -> trim_left(rest, count + 1)
195208
_ when count > 0 -> [?\n | buffer]
196209
_ -> buffer
197210
end
198211
end
199212

200-
defp trim_right(rest, line, column, count) do
201-
case trim_whitespace(rest) do
202-
[?\r, ?\n | rest] -> trim_right(rest, line + 1, 1, count + 1)
203-
[?\n | rest] -> trim_right(rest, line + 1, 1, count + 1)
204-
[] -> {[], line, column + length(rest)}
205-
_ when count > 0 -> {[?\n | rest], line - 1, column}
206-
_ -> {rest, line, column}
213+
defp trim_right(rest, line, column, last_column, opts) do
214+
case trim_whitespace(rest, column) do
215+
{[?\r, ?\n | rest], column} ->
216+
trim_right(rest, line + 1, opts.indentation + 1, column + 1, opts)
217+
218+
{[?\n | rest], column} ->
219+
trim_right(rest, line + 1, opts.indentation + 1, column, opts)
220+
221+
{[], column} ->
222+
{[], line, column}
223+
224+
_ when last_column > 0 ->
225+
{[?\n | rest], line - 1, last_column}
226+
227+
_ ->
228+
{rest, line, column}
207229
end
208230
end
209231

210-
defp trim_whitespace([h | t]) when h in @spaces, do: trim_whitespace(t)
211-
defp trim_whitespace(list), do: list
232+
defp trim_whitespace([h | t], column) when h in @spaces, do: trim_whitespace(t, column + 1)
233+
defp trim_whitespace(list, column), do: {list, column}
212234
end

0 commit comments

Comments
 (0)