Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions lib/lua/lexer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,23 @@ defmodule Lua.Lexer do
"""
@spec tokenize(String.t()) :: {:ok, [token()]} | {:error, term()}
def tokenize(code) when is_binary(code) do
# Handle shebang on first line (Unix convention: #! means interpreter directive)
code = strip_shebang(code)
pos = %{line: 1, column: 1, byte_offset: 0}
do_tokenize(code, [], pos)
end

# Strip shebang (#!) if it's the first line
defp strip_shebang(<<"#!", rest::binary>>) do
# Skip entire first line (everything up to and including the newline)
case String.split(rest, ~r/\r\n|\r|\n/, parts: 2) do
[_shebang_line, remaining] -> remaining
[_only_shebang] -> ""
end
end

defp strip_shebang(code), do: code

# End of input
defp do_tokenize(<<>>, acc, pos) do
{:ok, Enum.reverse([{:eof, pos} | acc])}
Expand Down
22 changes: 22 additions & 0 deletions test/lua/lexer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,28 @@ defmodule Lua.LexerTest do
assert {:ok, [{:comment, :multi, " comment ", _}, {:identifier, "x", _}, {:eof, _}]} =
Lexer.tokenize("--[[ comment ]]x")
end

test "ignores shebang on first line" do
# Lua ignores the first line if it starts with #
code = """
#!/usr/bin/env lua
local x = 1
return x
"""

assert {:ok, tokens} = Lexer.tokenize(code)
# Shebang should be treated as a comment and stripped
assert [{:keyword, :local, _} | _] = tokens

# Shebang only on first line
code2 = """
local x = 1
#!/usr/bin/env lua
"""

# Second line with # should cause error (not a shebang)
assert {:error, _} = Lexer.tokenize(code2)
end
end

describe "whitespace" do
Expand Down