Skip to content

Commit e56df8a

Browse files
author
José Valim
committed
Look text ahead on EEx do/end blocks instead of relying on buffers
1 parent 325c98c commit e56df8a

File tree

2 files changed

+24
-22
lines changed

2 files changed

+24
-22
lines changed

lib/eex/lib/eex/compiler.ex

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ defmodule EEx.Compiler do
2828
generate_buffer(t, buffer, scope, state)
2929
end
3030

31-
defp generate_buffer([{ :start_expr, line, mark, chars }|t], buffer, scope, state) do
32-
{ contents, t } = generate_buffer(t, "", [chars|scope], state.dict([]).line(line).start_line(line))
31+
defp generate_buffer([{ :start_expr, start_line, mark, chars }|t], buffer, scope, state) do
32+
{ contents, line, t } = look_ahead_text(t, start_line, chars)
33+
{ contents, t } = generate_buffer(t, "", [contents|scope], state.dict([]).line(line).start_line(start_line))
3334
buffer = state.engine.handle_expr(buffer, mark, contents)
3435
generate_buffer(t, buffer, scope, state)
3536
end
@@ -62,28 +63,27 @@ defmodule EEx.Compiler do
6263

6364
defp wrap_expr(current, line, buffer, chars, state) do
6465
new_lines = List.duplicate(?\n, line - state.line)
65-
66-
if state.dict == [] and empty?(buffer) do
67-
{ current ++ new_lines ++ chars, state }
68-
else
69-
key = length(state.dict)
70-
placeholder = '__EEX__(' ++ integer_to_list(key) ++ ');'
71-
{ current ++ placeholder ++ new_lines ++ chars, state.update_dict(&[{key, buffer}|&1]) }
72-
end
66+
key = length(state.dict)
67+
placeholder = '__EEX__(' ++ integer_to_list(key) ++ ');'
68+
{ current ++ placeholder ++ new_lines ++ chars, state.update_dict(&[{key, buffer}|&1]) }
7369
end
7470

75-
# Check if the syntax node represents an empty string
71+
# Look text ahead on expressions
7672

77-
defp empty?(bin) when is_binary(bin) do
78-
for(<<c <- bin>>, not c in [?\s, ?\t, ?\r, ?\n], into: "", do: <<c>>) == ""
73+
defp look_ahead_text([{ :text, text }, { :middle_expr, line, _, chars }|t]=list, start, contents) do
74+
if only_spaces?(text) do
75+
{ contents ++ text ++ chars, line, t }
76+
else
77+
{ contents, start, list }
78+
end
7979
end
8080

81-
defp empty?({ :<>, _, [left, right] }) do
82-
empty?(left) and empty?(right)
81+
defp look_ahead_text(t, start, contents) do
82+
{ contents, start, t }
8383
end
8484

85-
defp empty?(_) do
86-
false
85+
defp only_spaces?(chars) do
86+
Enum.all?(chars, &(&1 in [?\s, ?\t, ?\r, ?\n]))
8787
end
8888

8989
# Changes placeholder to real expression

lib/eex/lib/eex/tokenizer.ex

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ defmodule EEx.Tokenizer do
55
Tokenizes the given char list or binary.
66
It returns 4 different types of tokens as result:
77
8-
* { :text, line, contents }
8+
* { :text, contents }
99
* { :expr, line, marker, contents }
1010
* { :start_expr, line, marker, contents }
11+
* { :middle_expr, line, marker, contents }
1112
* { :end_expr, line, marker, contents }
1213
1314
"""
@@ -140,12 +141,13 @@ defmodule EEx.Tokenizer do
140141
end
141142

142143
defp check_spaces(string, token) do
143-
if only_spaces?(string), do: token, else: :expr
144+
if Enum.all?(string, &(&1 in [?\s, ?\t])) do
145+
token
146+
else
147+
:expr
148+
end
144149
end
145150

146-
defp only_spaces?([h|t]) when h in [?\s, ?\t], do: only_spaces?(t)
147-
defp only_spaces?(other), do: other == []
148-
149151
# Tokenize the buffered text by appending
150152
# it to the given accumulator.
151153

0 commit comments

Comments
 (0)