2022-07-23 17:15:08 +00:00
|
|
|
defmodule MfmParser.Lexer do
|
|
|
|
alias MfmParser.Reader
|
|
|
|
|
2022-07-23 18:17:34 +00:00
|
|
|
alias MfmParser.Token
|
2022-07-24 05:55:55 +00:00
|
|
|
alias MfmParser.Token.MFM
|
2022-07-23 18:17:34 +00:00
|
|
|
alias MfmParser.Token.Newline
|
|
|
|
alias MfmParser.Token.Text
|
|
|
|
|
2022-07-23 17:15:08 +00:00
|
|
|
def peek(input) do
|
|
|
|
case next(input) do
|
2022-07-24 05:55:55 +00:00
|
|
|
{token, _} -> token
|
2022-07-23 17:15:08 +00:00
|
|
|
:eof -> :eof
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def next(input) do
|
2022-07-23 18:17:34 +00:00
|
|
|
recursive_extract_next_token(Reader.next(input), get_empty_token(input))
|
2022-07-23 17:15:08 +00:00
|
|
|
end
|
|
|
|
|
2022-07-23 18:17:34 +00:00
|
|
|
defp recursive_extract_next_token(:eof, _) do
|
2022-07-23 17:15:08 +00:00
|
|
|
:eof
|
|
|
|
end
|
|
|
|
|
2022-07-24 05:55:55 +00:00
|
|
|
defp recursive_extract_next_token({char, rest}, token) do
|
2022-07-23 18:17:34 +00:00
|
|
|
if is_last_char_of_token?(char, rest, token) do
|
2022-07-24 05:55:55 +00:00
|
|
|
{token |> Token.append(char), rest}
|
2022-07-23 17:15:08 +00:00
|
|
|
else
|
2022-07-23 18:17:34 +00:00
|
|
|
recursive_extract_next_token(Reader.next(rest), token |> Token.append(char))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defp get_empty_token(input) do
|
|
|
|
case Reader.peek(input) do
|
|
|
|
:eof -> :eof
|
2022-07-24 05:55:55 +00:00
|
|
|
"$" -> %MFM.Open{}
|
|
|
|
"]" -> %MFM.Close{}
|
|
|
|
"\n" -> %Newline{}
|
2022-07-23 18:17:34 +00:00
|
|
|
_ -> %Text{}
|
2022-07-23 17:15:08 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-24 05:55:55 +00:00
|
|
|
defp is_last_char_of_token?(char, _, %MFM.Open{}) do
|
2022-07-23 18:17:34 +00:00
|
|
|
char == " "
|
2022-07-23 17:15:08 +00:00
|
|
|
end
|
|
|
|
|
2022-07-24 05:55:55 +00:00
|
|
|
defp is_last_char_of_token?(_, _, %MFM.Close{}) do
|
2022-07-23 17:15:08 +00:00
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2022-07-23 18:17:34 +00:00
|
|
|
defp is_last_char_of_token?(_, _, %Newline{}) do
|
2022-07-23 17:15:08 +00:00
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2022-07-23 18:17:34 +00:00
|
|
|
defp is_last_char_of_token?(_, rest, %Text{}) do
|
2022-07-23 17:15:08 +00:00
|
|
|
case Reader.next(rest) do
|
|
|
|
:eof -> true
|
2022-07-24 05:55:55 +00:00
|
|
|
{"]", _} -> true
|
|
|
|
{"$", new_rest} -> Reader.peek(new_rest) == "["
|
2022-07-23 17:15:08 +00:00
|
|
|
_ -> false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|