2 -- Copyright (C) 2008-2009 Matthew Wild
3 -- Copyright (C) 2008-2009 Waqas Hussain
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
13 local function read(expected)
16 ch = last; last = nil;
17 else ch = file:read(1); end
18 if expected and ch ~= expected then error("expected: "..expected.."; got: "..(ch or "nil")); end
21 local function pushback(ch)
22 if last then error(); end
26 if not last then last = read(); end
30 local _A, _a, _Z, _z, _0, _9, __, _at, _space = string.byte("AaZz09@_ ", 1, 9);
31 local function isLowerAlpha(ch)
32 ch = string.byte(ch) or 0;
33 return (ch >= _a and ch <= _z);
35 local function isNumeric(ch)
36 ch = string.byte(ch) or 0;
37 return (ch >= _0 and ch <= _9);
39 local function isAtom(ch)
40 ch = string.byte(ch) or 0;
41 return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z) or (ch >= _0 and ch <= _9) or ch == __ or ch == _at;
43 local function isSpace(ch)
44 ch = string.byte(ch) or "x";
48 local escapes = {["\\b"]="\b", ["\\d"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]="\s", ["\\t"]="\t", ["\\v"]="\v", ["\\\""]="\"", ["\\'"]="'", ["\\\\"]="\\"};
49 local function readString()
50 read("\""); -- skip quote
57 if not escapes[slash] then error("Unknown escape sequence: "..slash); end
58 str = str..escapes[slash];
60 elseif ch == "\"" then
62 elseif ch == "\\" then
70 local function readAtom1()
72 while isAtom(peek()) do
77 local function readAtom2()
78 local str = read("'");
83 if ch == "'" and not slash then break; end
87 local function readNumber()
89 while isNumeric(peek()) do
95 local function readTuple()
97 local s = ""; -- string representation
98 read(); -- read {, or [, or <
100 local item = readItem();
101 if not item then break; end
102 if type(item) ~= type(0) or item > 255 then
105 s = s..string.char(item);
107 table.insert(t, item);
109 read(); -- read }, or ], or >
110 if s and s ~= "" then
116 local function readBinary()
118 local t = readTuple();
121 if type(t) == type("") then
122 -- binary is a list of integers
124 elseif type(t) == type({}) then
126 -- binary contains string
136 readItem = function()
138 if ch == nil then return nil end
139 if ch == "{" or ch == "[" then
141 elseif isLowerAlpha(ch) then
143 elseif ch == "'" then
145 elseif isNumeric(ch) then
147 elseif ch == "\"" then
149 elseif ch == "<" then
151 elseif isSpace(ch) or ch == "," or ch == "|" then
155 --print("Unknown char: "..ch);
159 local function readChunk()
160 local x = readItem();
161 if x then read("."); end
164 local function readFile(filename)
165 file = io.open(filename);
166 if not file then error("File not found: "..filename); os.exit(0); end
168 local x = readChunk();
169 if not x and peek() then error("Invalid char: "..peek()); end
176 function parseFile(file)
177 return readFile(file);