Files
n8n-openai-adapter/lib/eex/compiler.ex
T

94 lines
3.2 KiB
Elixir

defrecord EEx.State, engine: EEx.SmartEngine, dict: [], file: 'nofile', line: 1
defmodule EEx.Compiler do
@moduledoc false
@doc """
This is the compilation entry point. It glues the tokenizer
and the engine together by handling the tokens and invoking
the engine every time a full expression or text is received.
"""
def compile(source, options) do
line = Keyword.get(options, :line, 1)
tokens = EEx.Tokenizer.tokenize(source, line)
state = EEx.State.new(options)
generate_buffer(tokens, "", [], state)
end
# Generates the buffers by handling each expression from the tokenizer
defp generate_buffer([{ :text, _line, chars }|t], buffer, scope, state) do
buffer = state.engine.handle_text(buffer, chars)
generate_buffer(t, buffer, scope, state)
end
defp generate_buffer([{ :expr, line, mark, chars }|t], buffer, scope, state) do
expr = { :__block__, 0, Erlang.elixir_translator.forms(chars, line, state.file) }
buffer = state.engine.handle_expr(buffer, mark, expr)
generate_buffer(t, buffer, scope, state)
end
defp generate_buffer([{ :start_expr, line, mark, chars }|t], buffer, scope, state) do
{ contents, t } = generate_buffer(t, "", [chars|scope], state.dict([]).line(line))
buffer = state.engine.handle_expr(buffer, mark, contents)
generate_buffer(t, buffer, scope, state.dict([]))
end
defp generate_buffer([{ :middle_expr, line, _, chars }|t], buffer, [current|scope], state) do
{ wrapped, state } = wrap_expr(current, line, buffer, chars, state)
generate_buffer(t, "", [wrapped|scope], state)
end
defp generate_buffer([{ :end_expr, line, _, chars }|t], buffer, [current|_], state) do
{ wrapped, state } = wrap_expr(current, line, buffer, chars, state)
tuples = { :__block__, 0, Erlang.elixir_translator.forms(wrapped, state.line, state.file) }
buffer = insert_quotes(tuples, state.dict)
{ buffer, t }
end
defp generate_buffer([{ :end_expr, line, _, chars }|_], _buffer, [], _state) do
raise EEx.SyntaxError, message: "unexpected token: #{inspect chars} at line #{inspect line}"
end
defp generate_buffer([], buffer, [], _state) do
buffer
end
defp generate_buffer([], _buffer, _scope, _state) do
raise EEx.SyntaxError, message: "unexpected end of string. expecting a closing <% end %>."
end
# Creates a placeholder and wrap it inside the expression block
defp wrap_expr(current, line, buffer, chars, state) do
key = length(state.dict)
new_lines = List.duplicate(?\n, line - state.line)
placeholder = '__EEX__(' ++ integer_to_list(key) ++ ');'
{ current ++ new_lines ++ placeholder ++ chars, state.prepend_dict([{key, buffer}]) }
end
# Changes placeholder to real expression
defp insert_quotes({ :__EEX__, _, [key] }, dict) do
{ ^key, value } = List.keyfind dict, key, 1
value
end
defp insert_quotes({ left, line, right }, dict) do
{ insert_quotes(left, dict), line, insert_quotes(right, dict) }
end
defp insert_quotes({ left, right }, dict) do
{ insert_quotes(left, dict), insert_quotes(right, dict) }
end
defp insert_quotes(list, dict) when is_list(list) do
Enum.map list, insert_quotes(&1, dict)
end
defp insert_quotes(other, _dict) do
other
end
end