1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-21 10:37:58 +03:00
mal/julia/reader.jl

108 lines
2.1 KiB
Julia
Raw Normal View History

2015-03-29 01:44:31 +03:00
module reader
export read_str
type Reader
tokens
position::Int64
end
function next(rdr::Reader)
if rdr.position > length(rdr.tokens)
return nothing
end
rdr.position += 1
rdr.tokens[rdr.position-1]
end
function peek(rdr::Reader)
if rdr.position > length(rdr.tokens)
return nothing
end
rdr.tokens[rdr.position]
end
function tokenize(str)
re = r"[\s,]*(~@|[\[\]{}()'`~^@]|\"(?:\\.|[^\\\"])*\"|;.*|[^\s\[\]{}('\"`,;)]*)"
tokens = map((m) -> m.captures[1], eachmatch(re, str))
filter((t) -> t != "", tokens)
end
function read_atom(rdr)
token = next(rdr)
if ismatch(r"^-?[0-9]+$", token)
int(token)
elseif ismatch(r"^-?[0-9][0-9.]*$", token)
float(token)
elseif ismatch(r"^\".*\"$", token)
replace(
replace(token[2:end-1],
"\\\"", "\""),
"\\n", "\n")
elseif token == "nil"
nothing
elseif token == "true"
true
elseif token == "false"
false
else
symbol(token)
end
end
function read_list(rdr, start="(", last=")")
ast = Any[]
token = next(rdr)
if (token != start)
error("expected '$(start)'")
end
while ((token = peek(rdr)) != last)
if token == nothing
error("expected '$(last)', got EOF")
end
push!(ast, read_form(rdr))
end
next(rdr)
ast
end
function read_vector(rdr)
lst = read_list(rdr, "[", "]")
tuple(lst...)
end
function read_hash_map(rdr)
lst = read_list(rdr, "{", "}")
[x[1] => x[2] for x=reshape(lst, (2, div(length(lst), 2)))]
end
function read_form(rdr)
token = peek(rdr)
if token == ")"
error("unexpected ')'")
elseif token == "("
read_list(rdr)
elseif token == "]"
error("unexpected ']'")
elseif token == "["
read_vector(rdr)
elseif token == "}"
error("unexpected '}'")
elseif token == "{"
read_hash_map(rdr)
else
read_atom(rdr)
end
end
function read_str(str)
tokens = tokenize(str)
if length(tokens) == 0
return nothing
end
read_form(Reader(tokens, 1))
end
end