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"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]="\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
98 return tonumber(t_concat(num));
100 local readItem = nil;
101 local function readTuple()
103 local s = {}; -- string representation
104 read(); -- read {, or [, or <
106 local item = readItem();
107 if not item then break; end
108 if type(item) ~= "number" or item > 255 then
111 s[#s+1] = string_char(item);
115 read(); -- read }, or ], or >
122 local function readBinary()
125 if isNumeric(peek()) then
126 while peek() ~= ">" do read(); end
130 local t = readTuple();
133 if type(t) == "string" then
134 -- binary is a list of integers
136 elseif type(t) == "table" then
138 -- binary contains string
148 readItem = function()
150 if ch == nil then return nil end
151 if ch == "{" or ch == "[" then
153 elseif isLowerAlpha(ch) then
155 elseif ch == "'" then
157 elseif isNumeric(ch) then
159 elseif ch == "\"" then
161 elseif ch == "<" then
163 elseif isSpace(ch) or ch == "," or ch == "|" then
167 --print("Unknown char: "..ch);
171 local function readChunk()
172 local x = readItem();
173 if x then read("."); end
176 local function readFile(filename)
177 file = io.open(filename);
178 if not file then error("File not found: "..filename); os.exit(0); end
180 local x = readChunk();
181 if not x and peek() then error("Invalid char: "..peek()); end
188 function parseFile(file)
189 return readFile(file);