# SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2025 DBVisor defmodule SQL.Lexer do @moduledoc false require Unicode.Set @zero "illegal zero width character" @bidi "illegal bidi character" @cgj "illegal cgj character" @context %{file: "nofile", binding: 0, types: [], aliases: [], errors: [], module: nil, format: :static, case: :lower, validate: nil, description: nil, columns: nil} def lex(binary, <> \\ "nofile") do case lex(binary, %{@context | file: file}, 0, 0, 0, 0, []) do {:error, error} -> raise TokenMissingError, [{:snippet, binary} | error] {:error, :zero_width, l, c} -> raise SyntaxError, [description: @zero, file: file, line: l, column: c] {:error, :bidi, l, c} -> raise SyntaxError, [description: @bidi, file: file, line: l, column: c] {:error, :cgj, l, c} -> raise SyntaxError, [description: @cgj, file: file, line: l, column: c] {_, _, context, acc} -> {:ok, context, acc} end end defp lex(rest, context, line, column, ol, oc, acc) do case rest do <<226, 129, 166, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 167, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 168, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 169, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 170, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 171, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 172, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 173, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 174, _::binary>> -> {:error, :bidi, line, column} <<239, 187, 191, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 141, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 140, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 139, _::binary>> -> {:error, :zero_width, line, column} <<226, 129, 160, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 181, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 180, _::binary>> -> {:error, :zero_width, line, column} <<225, 160, 142, _::binary>> -> {:error, :zero_width, line, column} <<205, 143, _::binary>> -> {:error, :cgj, line, column} <<9, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<32, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<194, 160, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<225, 154, 128, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<226, 128, 130, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<226, 128, 131, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<226, 128, 137, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<226, 128, 175, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<226, 129, 159, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<227, 128, 128, rest::binary>> -> lex(rest, context, line, column+1, ol, oc, acc) <<194, 133, rest::binary>> -> lex(rest, context, line+1, 0, ol, oc, acc) <<226, 128, 168, rest::binary>> -> lex(rest, context, line+1, 0, ol, oc, acc) <<226, 128, 169, rest::binary>> -> lex(rest, context, line+1, 0, ol, oc, acc) <<10, rest::binary>> -> lex(rest, context, line+1, 0, ol, oc, acc) <<11, rest::binary>> -> lex(rest, context, line+1, 0, ol, oc, acc) <<12, rest::binary>> -> lex(rest, context, line+1, 0, ol, oc, acc) <<13, rest::binary>> -> lex(rest, context, line+1, 0, ol, oc, acc) <> -> case acc do [{t, _, _}|_] when t in ~w[ident double_quote bracket]a -> end_column=column+1 lex(rest, context, line, end_column, line, end_column, node(:dot, :operator, line, column, line, end_column, ol, oc, context, [], acc)) _ -> num(rest, [?.], context, line, column, 1, ol, oc, acc) end <> -> end_column=column+1 lex(rest, context, line, end_column, line, end_column, node(:colon, :delimiter, line, column, line, column, ol, oc, context, [], acc)) <> -> end_column=column+1 lex(rest, context, line, end_column, line, end_column, node(:comma, :delimiter, line, column, line, end_column, ol, oc, context, [], acc)) <> -> comment(rest, [], line, column+2, context, line, column, ol, oc, acc) <> -> comments(rest, [], line, column+2, context, line, column, ol, oc, acc) <> -> double_brace(rest, [], line, column, 0, context, 0, 2, ol, oc, acc) <> when c in ~c"cC" and a in ~c"aA" and s in ~c"sS" and e in ~c"eE" -> case lex(rest, context, line, column, line, column, []) do {rest, context, end_line, end_column, ool, ooc, data} -> lex(rest, context, end_line, end_column, end_line, end_column, [{:case, [span: span(line, column, end_line, end_column, ol, oc, ool, ooc), type: :expression, file: context.file], data}|acc]) {end_line, end_column, _context, _acc} -> {:error, file: context.file, end_line: end_line, end_column: end_column, line: line, column: column, opening_delimiter: :case, expected_delimiter: :end} end <> when e in ~c"eE" and n in ~c"nN" and d in ~c"dD" -> {rest, context, line, column, ol, oc, acc} <> -> backtick(rest, [], line, column, context, 0, 1, ol, oc, acc) <> -> quote(rest, [], line, column, context, 0, 1, ol, oc, acc) <> -> double_quote(rest, [], line, column, context, 0, 1, ol, oc, acc) <> -> hex(rest, [?x, ?0], context, line, column, 2, ol, oc, acc) <> -> hex(rest, [?X, ?0], context, line, column, 2, ol, oc, acc) <> -> bin(rest, [?b, ?0], context, line, column, 2, ol, oc, acc) <> -> bin(rest, [?B, ?0], context, line, column, 2, ol, oc, acc) <> -> oct(rest, [?o, ?0], context, line, column, 2, ol, oc, acc) <> -> oct(rest, [?O, ?0], context, line, column, 2, ol, oc, acc) <> -> special(rest, [?!], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?#], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?$], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?%], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?&], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?*], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?+], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?-], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?/], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?:], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?<], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?=], context, line, column, 1, ol, oc, acc) <, rest::binary>> -> special(rest, [?>], context, line, column, 1, ol, oc, acc) <> -> special(rest, [??], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?@], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?^], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?|], context, line, column, 1, ol, oc, acc) <> -> special(rest, [?~], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?_], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?0], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?1], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?2], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?3], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?4], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?5], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?6], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?7], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?8], context, line, column, 1, ol, oc, acc) <> -> num(rest, [?9], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?a], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?b], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?c], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?d], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?e], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?f], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?g], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?h], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?i], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?j], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?k], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?l], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?m], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?n], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?o], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?p], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?q], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?r], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?s], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?t], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?u], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?v], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?w], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?x], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?y], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?z], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?a], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?b], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?c], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?d], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?e], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?f], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?g], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?h], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?i], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?j], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?k], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?l], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?m], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?n], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?o], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?p], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?q], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?r], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?s], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?t], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?u], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?v], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?w], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?x], context, line, column, 1, ol, oc, acc) <> -> ident(rest, [?y], context, line, column, 1, ol, oc, acc) <> -> case lex(rest, context, line, column, line, column, []) do {rest, context, end_line, end_column, ool, ooc, data} -> lex(rest, context, end_line, end_column, end_line, end_column, [{:paren, [span: span(line, column, end_line, end_column, ol, oc, ool, ooc), type: :expression, file: context.file], data}|acc]) {end_line, end_column, _context, _acc} -> {:error, file: context.file, end_line: end_line, end_column: end_column, line: line, column: column, opening_delimiter: :"(", expected_delimiter: :")"} end <> -> case lex(rest, context, line, column, line, column, []) do {rest, context, end_line, end_column, ool, ooc, data} -> lex(rest, context, end_line, end_column, end_line, end_column, [{:bracket, [span: span(line, column, end_line, end_column, ol, oc, ool, ooc), type: :expression, file: context.file], data}|acc]) {end_line, end_column, _context, _acc} -> {:error, file: context.file, end_line: end_line, end_column: end_column, line: line, column: column, opening_delimiter: :"[", expected_delimiter: :"]"} end <> -> ol = line-ol oc = column-oc case lex(rest, context, line, column, line, column, []) do {rest, context, end_line, end_column, ool, ooc, data} -> lex(rest, context, end_line, end_column, end_line, end_column, [{:brace, [span: span(line, column, end_line, end_column, ol, oc, ool, ooc), type: :expression, file: context.file], data}|acc]) {end_line, end_column, _context, _acc} -> {:error, file: context.file, end_line: end_line, end_column: end_column, line: line, column: column, opening_delimiter: :"{", expected_delimiter: :"}"} end <> -> {rest, context, line, column, ol, oc, acc} <> -> {rest, context, line, column, ol, oc, acc} <> -> {rest, context, line, column, ol, oc, acc} <> when Unicode.Set.match?(b, "[[:Lu:], [:Ll:], [:Lt:], [:Lm:], [:Lo:], [:Nl:]]") -> ident(rest, [b], context, line, column, 1, ol, oc, acc) "" -> {line, column, context, acc} end end {reserved, non_reserved, operators} = SQL.BNF.get_rules() suggestions = Enum.map(operators, &to_string(elem(&1, 0))) def suggest_operator(value) do Enum.sort(Enum.filter(unquote(suggestions), &(String.jaro_distance("#{value}", &1) > 0)), &(String.jaro_distance(value, &1) >= String.jaro_distance(value, &2))) end reserved = Enum.reject(reserved, &(&1 in operators)) non_reserved = Enum.reject(non_reserved, &(&1 in operators or &1 in reserved)) case_ast = for {type, values} <- [operator: operators, reserved: reserved], {atom, match} <- values, hd(match) in ?a..?z do hd( quote do unquote(match) -> lex(var!(rest), var!(context), var!(line), var!(end_column), var!(line), var!(end_column), node(unquote(atom), unquote(type), var!(line), var!(column), var!(line), var!(end_column), var!(ol), var!(oc), var!(context), [], var!(acc))) end ) end ++ for {atom, match} <- non_reserved do hd( quote do unquote(match) -> lex(var!(rest), var!(context), var!(line), var!(end_column), var!(line), var!(end_column), node(unquote(atom), :non_reserved, var!(line), var!(column), var!(line), var!(end_column), var!(ol), var!(oc), var!(context), :lists.reverse(var!(data)), var!(acc))) end ) end ++ quote do data -> lex(var!(rest), var!(context), var!(line), var!(end_column), var!(line), var!(end_column), node(:ident, :literal, var!(line), var!(column), var!(line), var!(end_column), var!(ol), var!(oc), var!(context), :lists.reverse(data), var!(acc))) end defp ident(rest, data, context, line, column, length, ol, oc, acc) do case rest do <<226, 129, 166, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 167, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 168, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 169, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 170, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 171, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 172, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 173, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 174, _::binary>> -> {:error, :bidi, line, column} <<239, 187, 191, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 141, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 140, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 139, _::binary>> -> {:error, :zero_width, line, column} <<226, 129, 160, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 181, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 180, _::binary>> -> {:error, :zero_width, line, column} <<225, 160, 142, _::binary>> -> {:error, :zero_width, line, column} <<205, 143, _::binary>> -> {:error, :cgj, line, column} <> -> end_column = column+length backtick(rest, [], line, end_column, context, 0, 1, line, end_column, node(:ident, :literal, line, column, line, end_column, ol, oc, context, :lists.reverse(data), acc)) <> -> end_column = column+length quote(rest, [], line, end_column, context, 0, 1, line, end_column, node(:ident, :literal, line, column, line, end_column, ol, oc, context, :lists.reverse(data), acc)) <> -> end_column = column+length double_quote(rest, [], line, end_column, context, 0, 1, line, end_column, node(:ident, :literal, line, column, line, end_column, ol, oc, context, :lists.reverse(data), acc)) <> -> ident(rest, [?_|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?&|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?0|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?1|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?2|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?3|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?4|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?5|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?6|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?7|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?8|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?9|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?a|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?b|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?c|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?d|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?e|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?f|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?g|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?h|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?i|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?j|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?k|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?l|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?m|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?n|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?o|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?p|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?q|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?r|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?s|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?t|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?u|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?v|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?w|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?x|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?y|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?z|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?a|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?b|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?c|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?d|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?e|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?f|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?g|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?h|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?i|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?j|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?k|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?l|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?m|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?n|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?o|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?p|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?q|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?r|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?s|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?t|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?u|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?v|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?w|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?x|data], context, line, column, length+1, ol, oc, acc) <> -> ident(rest, [?y|data], context, line, column, length+1, ol, oc, acc) <> when Unicode.Set.match?(b, "[[:Lu:], [:Ll:], [:Lt:], [:Lm:], [:Lo:], [:Nl:], [:Mn:], [:Mc:], [:Nd:], [:Pc:], [:Cf:]]") and b != ?, -> ident(rest, [b|data], context, line, column, length+1, ol, oc, acc) rest -> end_column = column+length case data do unquote(case_ast) end end end defp comment(rest, data, l, c, context, line, column, ol, oc, acc) do case rest do <<194, 133, rest::binary>> -> l=l+1 lex(rest, context, l, c, l, c, node(:comment, :literal, line, column, l, c, ol, oc, context, :lists.reverse(data), acc)) <<226, 128, 168, rest::binary>> -> l=l+1 lex(rest, context, l, c, l, c, node(:comment, :literal, line, column, l, c, ol, oc, context, :lists.reverse(data), acc)) <<226, 128, 169, rest::binary>> -> l=l+1 lex(rest, context, l, c, l, c, node(:comment, :literal, line, column, l, c, ol, oc, context, :lists.reverse(data), acc)) <<10, rest::binary>> -> l=l+1 lex(rest, context, l, c, l, c, node(:comment, :literal, line, column, l, c, ol, oc, context, :lists.reverse(data), acc)) <<11, rest::binary>> -> l=l+1 lex(rest, context, l, c, l, c, node(:comment, :literal, line, column, l, c, ol, oc, context, :lists.reverse(data), acc)) <<12, rest::binary>> -> l=l+1 lex(rest, context, l, c, l, c, node(:comment, :literal, line, column, l, c, ol, oc, context, :lists.reverse(data), acc)) <<13, rest::binary>> -> l=l+1 lex(rest, context, l, c, l, c, node(:comment, :literal, line, column, l, c,ol, oc, context, :lists.reverse(data), acc)) <<194, 160, rest::binary>> -> comment(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<225, 154, 128, rest::binary>> -> comment(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 128, 130, rest::binary>> -> comment(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 128, 131, rest::binary>> -> comment(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 128, 137, rest::binary>> -> comment(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 128, 175, rest::binary>> -> comment(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 129, 159, rest::binary>> -> comment(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<227, 128, 128, rest::binary>> -> comment(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <> -> comment(rest, [b|data], l, c+1, context, line, column, ol, oc, acc) "" -> lex(rest, context, l, c, l, c, node(:comment, :literal, line, column, l, c, ol, oc, context, :lists.reverse(data), acc)) end end defp comments(rest, data, l, c, context, line, column, ol, oc, acc) do case rest do <<194, 133, rest::binary>> -> comments(rest, [?\n|data], l+1, c, context, line, column, ol, oc, acc) <<226, 128, 168, rest::binary>> -> comments(rest, [?\n|data], l+1, c, context, line, column, ol, oc, acc) <<226, 128, 169, rest::binary>> -> comments(rest, [?\n|data], l+1, c, context, line, column, ol, oc, acc) <<10, rest::binary>> -> comments(rest, [?\n|data], l+1, c, context, line, column, ol, oc, acc) <<11, rest::binary>> -> comments(rest, [?\n|data], l+1, c, context, line, column, ol, oc, acc) <<12, rest::binary>> -> comments(rest, [?\n|data], l+1, c, context, line, column, ol, oc, acc) <<13, rest::binary>> -> comments(rest, [?\n|data], l+1, c, context, line, column, ol, oc, acc) <<194, 160, rest::binary>> -> comments(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<225, 154, 128, rest::binary>> -> comments(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 128, 130, rest::binary>> -> comments(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 128, 131, rest::binary>> -> comments(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 128, 137, rest::binary>> -> comments(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 128, 175, rest::binary>> -> comments(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<226, 129, 159, rest::binary>> -> comments(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <<227, 128, 128, rest::binary>> -> comments(rest, [?\s|data], l, c+1, context, line, column, ol, oc, acc) <> -> c=c+2 lex(rest, context, l, c, l, c, node(:comments, :literal, line, column, l, c, ol, oc, context, :lists.reverse(data), acc)) <> -> comments(rest, [b|data], l, c+1, context, line, column, ol, oc, acc) "" -> {:error, file: context.file, end_line: l, end_column: c, line: line, column: column, opening_delimiter: :"/*", expected_delimiter: :"*/"} end end case_ast = for {atom, match} <- operators, hd(match) not in ?a..?z do hd( quote do unquote(match) -> lex(var!(rest), var!(context), var!(line), var!(end_column), var!(line), var!(end_column), node(unquote(atom), :operator, var!(line), var!(column), var!(line), var!(end_column), var!(ol), var!(oc), var!(context), [], var!(acc))) end ) end ++ quote do data -> node = node(:special, :operator, var!(line), var!(column), var!(line), var!(end_column), var!(ol), var!(oc), var!(context), data) lex(var!(rest), %{var!(context) | errors: [node|var!(context).errors]}, var!(line), var!(end_column), var!(line), var!(end_column), [node|var!(acc)]) end defp special(rest, data, context, line, column, length, ol, oc, acc) do case rest do <<226, 129, 166, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 167, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 168, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 169, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 170, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 171, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 172, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 173, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 174, _::binary>> -> {:error, :bidi, line, column} <<239, 187, 191, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 141, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 140, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 139, _::binary>> -> {:error, :zero_width, line, column} <<226, 129, 160, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 181, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 180, _::binary>> -> {:error, :zero_width, line, column} <<225, 160, 142, _::binary>> -> {:error, :zero_width, line, column} <<205, 143, _::binary>> -> {:error, :cgj, line, column} <> -> special(rest, [?!|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?#|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?$|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?%|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?&|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?*|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?+|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?-|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?/|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?:|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?<|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?=|data], context, line, column, length+1, ol, oc, acc) <, rest::binary>> -> special(rest, [?>|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [??|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?@|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?^|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?_|data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?||data], context, line, column, length+1, ol, oc, acc) <> -> special(rest, [?~|data], context, line, column, length+1, ol, oc, acc) rest -> end_column = column+length case data do unquote(case_ast) end end end defp num(rest, data, context, line, column, length, ol, oc, acc) do case rest do <<226, 129, 166, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 167, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 168, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 169, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 170, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 171, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 172, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 173, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 174, _::binary>> -> {:error, :bidi, line, column} <<239, 187, 191, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 141, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 140, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 139, _::binary>> -> {:error, :zero_width, line, column} <<226, 129, 160, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 181, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 180, _::binary>> -> {:error, :zero_width, line, column} <<225, 160, 142, _::binary>> -> {:error, :zero_width, line, column} <<205, 143, _::binary>> -> {:error, :cgj, line, column} <> -> num(rest, [?_|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?.|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?-|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?+|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?e|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?E|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?0|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?1|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?2|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?3|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?4|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?5|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?6|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?7|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?8|data], context, line, column, length+1, ol, oc, acc) <> -> num(rest, [?9|data], context, line, column, length+1, ol, oc, acc) rest -> end_column = column+length lex(rest, context, line, end_column, line, end_column, node(:numeric, :literal, line, column, line, end_column, ol, oc, context, :lists.reverse(data), acc)) end end defp hex(rest, data, context, line, column, length, ol, oc, acc) do case rest do <<226, 129, 166, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 167, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 168, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 169, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 170, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 171, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 172, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 173, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 174, _::binary>> -> {:error, :bidi, line, column} <<239, 187, 191, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 141, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 140, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 139, _::binary>> -> {:error, :zero_width, line, column} <<226, 129, 160, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 181, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 180, _::binary>> -> {:error, :zero_width, line, column} <<225, 160, 142, _::binary>> -> {:error, :zero_width, line, column} <<205, 143, _::binary>> -> {:error, :cgj, line, column} <> -> hex(rest, [?_|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?0|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?1|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?2|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?3|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?4|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?5|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?6|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?7|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?8|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?9|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?A|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?B|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?C|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?D|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?E|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?F|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?a|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?b|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?c|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?d|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?e|data], context, line, column, length+1, ol, oc, acc) <> -> hex(rest, [?f|data], context, line, column, length+1, ol, oc, acc) rest -> end_column = column+length lex(rest, context, line, end_column, line, end_column, node(:numeric, :hexadecimal, line, column, line, end_column, ol, oc, context, :lists.reverse(data), acc)) end end defp bin(rest, data, context, line, column, length, ol, oc, acc) do case rest do <<226, 129, 166, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 167, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 168, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 169, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 170, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 171, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 172, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 173, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 174, _::binary>> -> {:error, :bidi, line, column} <<239, 187, 191, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 141, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 140, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 139, _::binary>> -> {:error, :zero_width, line, column} <<226, 129, 160, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 181, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 180, _::binary>> -> {:error, :zero_width, line, column} <<225, 160, 142, _::binary>> -> {:error, :zero_width, line, column} <<205, 143, _::binary>> -> {:error, :cgj, line, column} <> -> bin(rest, [?_|data], context, line, column, length+1, ol, oc, acc) <> -> bin(rest, [?0|data], context, line, column, length+1, ol, oc, acc) <> -> bin(rest, [?1|data], context, line, column, length+1, ol, oc, acc) rest -> end_column = column+length lex(rest, context, line, end_column, line, end_column, node(:numeric, :binary, line, column, line, end_column, ol, oc, context, :lists.reverse(data), acc)) end end defp oct(rest, data, context, line, column, length, ol, oc, acc) do case rest do <<226, 129, 166, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 167, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 168, _::binary>> -> {:error, :bidi, line, column} <<226, 129, 169, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 170, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 171, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 172, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 173, _::binary>> -> {:error, :bidi, line, column} <<226, 128, 174, _::binary>> -> {:error, :bidi, line, column} <<239, 187, 191, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 141, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 140, _::binary>> -> {:error, :zero_width, line, column} <<226, 128, 139, _::binary>> -> {:error, :zero_width, line, column} <<226, 129, 160, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 181, _::binary>> -> {:error, :zero_width, line, column} <<225, 158, 180, _::binary>> -> {:error, :zero_width, line, column} <<225, 160, 142, _::binary>> -> {:error, :zero_width, line, column} <<205, 143, _::binary>> -> {:error, :cgj, line, column} <> -> oct(rest, [?_|data], context, line, column, length+1, ol, oc, acc) <> -> oct(rest, [?0|data], context, line, column, length+1, ol, oc, acc) <> -> oct(rest, [?1|data], context, line, column, length+1, ol, oc, acc) <> -> oct(rest, [?2|data], context, line, column, length+1, ol, oc, acc) <> -> oct(rest, [?3|data], context, line, column, length+1, ol, oc, acc) <> -> oct(rest, [?4|data], context, line, column, length+1, ol, oc, acc) <> -> oct(rest, [?5|data], context, line, column, length+1, ol, oc, acc) <> -> oct(rest, [?6|data], context, line, column, length+1, ol, oc, acc) <> -> oct(rest, [?7|data], context, line, column, length+1, ol, oc, acc) rest -> end_column = column+length lex(rest, context, line, end_column, line, end_column, node(:numeric, :octal, line, column, line, end_column, ol, oc, context, :lists.reverse(data), acc)) end end defp backtick(rest, data, l, c, context, line, column, ol, oc, acc) do case rest do <<239, 187, 191, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 141, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 140, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 139, _::binary>> -> {:error, :zero_width, l, c} <<226, 129, 160, _::binary>> -> {:error, :zero_width, l, c} <<225, 158, 181, _::binary>> -> {:error, :zero_width, l, c} <<225, 158, 180, _::binary>> -> {:error, :zero_width, l, c} <<225, 160, 142, _::binary>> -> {:error, :zero_width, l, c} <> -> end_line = l+line end_column = c+column+1 lex(rest, context, end_line, end_column, end_line, end_column, node(:backtick, :literal, l, c, end_line, end_column, ol, oc, context, :lists.reverse(data), acc)) <<194, 160, rest::binary>> -> backtick(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<225, 154, 128, rest::binary>> -> backtick(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 175, rest::binary>> -> backtick(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 137, rest::binary>> -> backtick(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 131, rest::binary>> -> backtick(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 130, rest::binary>> -> backtick(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 129, 159, rest::binary>> -> backtick(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<227, 128, 128, rest::binary>> -> backtick(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<194, 133, rest::binary>> -> backtick(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<226, 128, 168, rest::binary>> -> backtick(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<226, 128, 169, rest::binary>> -> backtick(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<10, rest::binary>> -> backtick(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<11, rest::binary>> -> backtick(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<12, rest::binary>> -> backtick(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<13, rest::binary>> -> backtick(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <> -> backtick(rest, [b|data], l, c, context, line, column+1, ol, oc, acc) "" -> {:error, file: context.file, line: l, column: c, end_line: l+line, end_column: c+column, opening_delimiter: :"`", expected_delimiter: :"`"} end end defp double_quote(rest, data, l, c, context, line, column, ol, oc, acc) do case rest do <<239, 187, 191, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 141, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 140, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 139, _::binary>> -> {:error, :zero_width, l, c} <<226, 129, 160, _::binary>> -> {:error, :zero_width, l, c} <<225, 158, 181, _::binary>> -> {:error, :zero_width, l, c} <<225, 158, 180, _::binary>> -> {:error, :zero_width, l, c} <<225, 160, 142, _::binary>> -> {:error, :zero_width, l, c} <> -> end_line = l+line end_column = c+column+1 lex(rest, context, end_line, end_column, end_line, end_column, node(:double_quote, :literal, l, c, end_line, end_column, ol, oc, context, :lists.reverse(data), acc)) <<194, 160, rest::binary>> -> double_quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<225, 154, 128, rest::binary>> -> double_quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 175, rest::binary>> -> double_quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 137, rest::binary>> -> double_quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 131, rest::binary>> -> double_quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 130, rest::binary>> -> double_quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 129, 159, rest::binary>> -> double_quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<227, 128, 128, rest::binary>> -> double_quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<194, 133, rest::binary>> -> double_quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<226, 128, 168, rest::binary>> -> double_quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<226, 128, 169, rest::binary>> -> double_quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<10, rest::binary>> -> double_quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<11, rest::binary>> -> double_quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<12, rest::binary>> -> double_quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<13, rest::binary>> -> double_quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <> -> double_quote(rest, [b|data], l, c, context, line, column+1, ol, oc, acc) "" -> {:error, file: context.file, line: l, column: c, end_line: l+line, end_column: c+column, opening_delimiter: :"\"", expected_delimiter: :"\""} end end defp double_brace(rest, data, l, c, n, context, line, column, ol, oc, acc) do case rest do <<239, 187, 191, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 141, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 140, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 139, _::binary>> -> {:error, :zero_width, l, c} <<226, 129, 160, _::binary>> -> {:error, :zero_width, l, c} <<225, 158, 181, _::binary>> -> {:error, :zero_width, l, c} <<225, 158, 180, _::binary>> -> {:error, :zero_width, l, c} <<225, 160, 142, _::binary>> -> {:error, :zero_width, l, c} <<205, 143, _::binary>> -> {:cgj, :zero_width, l, c} <<194, 160, rest::binary>> -> double_brace(rest, [?\s|data], l, c, n, context, line, column+1, ol, oc, acc) <<225, 154, 128, rest::binary>> -> double_brace(rest, [?\s|data], l, c, n, context, line, column+1, ol, oc, acc) <<226, 128, 175, rest::binary>> -> double_brace(rest, [?\s|data], l, c, n, context, line, column+1, ol, oc, acc) <<226, 128, 137, rest::binary>> -> double_brace(rest, [?\s|data], l, c, n, context, line, column+1, ol, oc, acc) <<226, 128, 131, rest::binary>> -> double_brace(rest, [?\s|data], l, c, n, context, line, column+1, ol, oc, acc) <<226, 128, 130, rest::binary>> -> double_brace(rest, [?\s|data], l, c, n, context, line, column+1, ol, oc, acc) <<226, 129, 159, rest::binary>> -> double_brace(rest, [?\s|data], l, c, n, context, line, column+1, ol, oc, acc) <<227, 128, 128, rest::binary>> -> double_brace(rest, [?\s|data], l, c, n, context, line, column+1, ol, oc, acc) <<194, 133, rest::binary>> -> double_brace(rest, [?\n|data], l, c, n, context, line, column+1, ol, oc, acc) <<226, 128, 168, rest::binary>> -> double_brace(rest, [?\n|data], l, c, n, context, line, column+1, ol, oc, acc) <<226, 128, 169, rest::binary>> -> double_brace(rest, [?\n|data], l, c, n, context, line, column+1, ol, oc, acc) <<10, rest::binary>> -> double_brace(rest, [?\n|data], l, c, n, context, line, column+1, ol, oc, acc) <<11, rest::binary>> -> double_brace(rest, [?\n|data], l, c, n, context, line, column+1, ol, oc, acc) <<12, rest::binary>> -> double_brace(rest, [?\n|data], l, c, n, context, line, column+1, ol, oc, acc) <<13, rest::binary>> -> double_brace(rest, [?\n|data], l, c, n, context, line, column+1, ol, oc, acc) <> -> double_brace(rest, [?{|data], l, c, n+1, context, line, column+1, ol, oc, acc) <> when n == 0 -> end_line = l+line end_column = c+column+2 value = Code.string_to_quoted!(:lists.reverse(data), file: context.file, line: line, column: column, columns: true, token_metadata: true, existing_atoms_only: true) lex(rest, %{context | binding: context.binding+1}, end_line, end_column, end_line, end_column, node(:binding, :binding, l, c, end_line, end_column, ol, oc, context, [value], acc)) <> -> double_brace(rest, [?}|data], l, c, n-1, context, line, column+1, ol, oc, acc) <> -> double_brace(rest, [b|data], l, c, n, context, line, column+1, ol, oc, acc) "" -> {:error, file: context.file, end_line: l, end_column: c, line: l+line, column: c+column, opening_delimiter: :"{", expected_delimiter: :"}"} end end defp quote(rest, data, l, c, context, line, column, ol, oc, acc) do case rest do <<239, 187, 191, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 141, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 140, _::binary>> -> {:error, :zero_width, l, c} <<226, 128, 139, _::binary>> -> {:error, :zero_width, l, c} <<226, 129, 160, _::binary>> -> {:error, :zero_width, l, c} <<225, 158, 181, _::binary>> -> {:error, :zero_width, l, c} <<225, 158, 180, _::binary>> -> {:error, :zero_width, l, c} <<225, 160, 142, _::binary>> -> {:error, :zero_width, l, c} <> -> end_line = l+line end_column = c+column+1 lex(rest, context, end_line, end_column, end_line, end_column, node(:quote, :literal, l, c, end_line, end_column, ol, oc, context, :lists.reverse(data), acc)) <<194, 160, rest::binary>> -> quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<225, 154, 128, rest::binary>> -> quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 175, rest::binary>> -> quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 137, rest::binary>> -> quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 131, rest::binary>> -> quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 128, 130, rest::binary>> -> quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<226, 129, 159, rest::binary>> -> quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<227, 128, 128, rest::binary>> -> quote(rest, [?\s|data], l, c, context, line, column+1, ol, oc, acc) <<194, 133, rest::binary>> -> quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<226, 128, 168, rest::binary>> -> quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<226, 128, 169, rest::binary>> -> quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<10, rest::binary>> -> quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<11, rest::binary>> -> quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<12, rest::binary>> -> quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <<13, rest::binary>> -> quote(rest, [?\n|data], l, c, context, line+1, column, ol, oc, acc) <> -> quote(rest, [b|data], l, c, context, line, column+1, ol, oc, acc) "" -> {:error, file: context.file, line: l, column: c, end_line: l+line, end_column: c+column, opening_delimiter: :"'", expected_delimiter: :"'"} end end defp node(tag, type, line, column, end_line, end_column, ol, oc, context, data) do case type do :non_reserved -> {:ident, [span: span(line, column, end_line, end_column, ol, oc), type: type, tag: tag, file: context.file], data} _ -> {tag, [span: span(line, column, end_line, end_column, ol, oc), type: type, file: context.file], data} end end defp node(tag, type, line, column, end_line, end_column, ol, oc, context, data, acc) do [node(tag, type, line, column, end_line, end_column, ol, oc, context, data)|acc] end defp span(line, column, end_line, end_column, ol, oc, end_line, ooc), do: {line, column, end_line, end_column, line-ol, column-oc, 0, end_column-ooc} defp span(line, column, end_line, end_column, line, oc, ool, _ooc), do: {line, column, end_line, end_column, 0, column-oc, end_line-ool, end_column} defp span(line, column, end_line, end_column, ol, _oc, ool, _ooc), do: {line, column, end_line, end_column, line-ol, end_column, end_line-ool, end_column} defp span(line, column, end_line, end_column, end_line, oc), do: {line, column, end_line, end_column, 0, column-oc} defp span(line, column, end_line, end_column, ol, _oc), do: {line, column, end_line, end_column, line-ol, column} end