2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
9 local string_byte
, string_char
= string.byte
, string.char
;
10 local t_concat
, t_insert
= table.concat
, table.insert
;
11 local type, tonumber, tostring = type, tonumber, tostring;
16 local function read(expected
)
19 ch
= last
; last
= nil;
22 if ch
== "\n" then line
= line
+ 1; end
24 if expected
and ch
~= expected
then error("expected: "..expected
.."; got: "..(ch
or "nil").." on line "..line
); end
27 local function pushback(ch
)
28 if last
then error(); end
32 if not last
then last
= read(); end
36 local _A
, _a
, _Z
, _z
, _0
, _9
, __
, _at
, _space
, _minus
= string_byte("AaZz09@_ -", 1, 10);
37 local function isLowerAlpha(ch
)
38 ch
= string_byte(ch
) or 0;
39 return (ch
>= _a
and ch
<= _z
);
41 local function isNumeric(ch
)
42 ch
= string_byte(ch
) or 0;
43 return (ch
>= _0
and ch
<= _9
) or ch
== _minus
;
45 local function isAtom(ch
)
46 ch
= string_byte(ch
) or 0;
47 return (ch
>= _A
and ch
<= _Z
) or (ch
>= _a
and ch
<= _z
) or (ch
>= _0
and ch
<= _9
) or ch
== __
or ch
== _at
;
49 local function isSpace(ch
)
50 ch
= string_byte(ch
) or "x";
54 local escapes
= {["\\b"]="\b", ["\\d"]="\127", ["\\e"]="\27", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]=" ", ["\\t"]="\t", ["\\v"]="\v", ["\\\""]="\"", ["\\'"]="'", ["\\\\"]="\\"};
55 local function readString()
56 read("\""); -- skip quote
63 if not escapes
[slash
] then error("Unknown escape sequence: "..slash
); end
64 str
[#str
+1] = escapes
[slash
];
66 elseif ch
== "\"" then
68 elseif ch
== "\\" then
76 local function readAtom1()
77 local var
= { read() };
78 while isAtom(peek()) do
83 local function readAtom2()
84 local str
= { read("'") };
89 if ch
== "'" and not slash
then break; end
93 local function readNumber()
94 local num
= { read() };
95 while isNumeric(peek()) do
100 while isNumeric(peek()) do
101 num
[#num
+1] = read();
104 return tonumber(t_concat(num
));
106 local readItem
= nil;
107 local function readTuple()
109 local s
= {}; -- string representation
110 read(); -- read {, or [, or <
112 local item
= readItem();
113 if not item
then break; end
114 if type(item
) ~= "number" or item
> 255 then
117 s
[#s
+1] = string_char(item
);
121 read(); -- read }, or ], or >
128 local function readBinary()
131 if isNumeric(peek()) then
132 while peek() ~= ">" do read(); end
136 local t
= readTuple();
139 if type(t
) == "string" then
140 -- binary is a list of integers
142 elseif type(t
) == "table" then
144 -- binary contains string
154 readItem
= function()
156 if ch
== nil then return nil end
157 if ch
== "{" or ch
== "[" then
159 elseif isLowerAlpha(ch
) then
161 elseif ch
== "'" then
163 elseif isNumeric(ch
) then
165 elseif ch
== "\"" then
167 elseif ch
== "<" then
169 elseif isSpace(ch
) or ch
== "," or ch
== "|" then
173 --print("Unknown char: "..ch);
177 local function readChunk()
178 local x
= readItem();
179 if x
then read("."); end
182 local function readFile(filename
)
183 file
= io
.open(filename
);
184 if not file
then error("File not found: "..filename
); os
.exit(0); end
186 local x
= readChunk();
187 if not x
and peek() then error("Invalid char: "..peek()); end
194 function _M
.parseFile(file
)
195 return readFile(file
);