2 -- Copyright (C) 2008 Matthew Wild
3 -- Copyright (C) 2008 Waqas Hussain
5 -- This program is free software; you can redistribute it and/or
6 -- modify it under the terms of the GNU General Public License
7 -- as published by the Free Software Foundation; either version 2
8 -- of the License, or (at your option) any later version.
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 -- GNU General Public License for more details.
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 local function read(expected)
\r
27 ch = last; last = nil;
\r
28 else ch = file:read(1); end
\r
29 if expected and ch ~= expected then error("expected: "..expected.."; got: "..(ch or "nil")); end
\r
32 local function pushback(ch)
\r
33 if last then error(); end
\r
36 local function peek()
\r
37 if not last then last = read(); end
\r
41 local _A, _a, _Z, _z, _0, _9, __, _space = string.byte("AaZz09_ ", 1, 8);
\r
42 local function isAlpha(ch)
\r
43 ch = string.byte(ch) or 0;
\r
44 return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z);
\r
46 local function isNumeric(ch)
\r
47 ch = string.byte(ch) or 0;
\r
48 return (ch >= _0 and ch <= _9);
\r
50 local function isVar(ch)
\r
51 ch = string.byte(ch) or 0;
\r
52 return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z) or (ch >= _0 and ch <= _9) or ch == __;
\r
54 local function isSpace(ch)
\r
55 ch = string.byte(ch) or "x";
\r
56 return ch <= _space;
\r
59 local function readString()
\r
60 read("\""); -- skip quote
\r
65 if ch == "\"" and not slash then break; end
\r
68 str = str:gsub("\\.", {["\\b"]="\b", ["\\d"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]="\s", ["\\t"]="\t", ["\\v"]="\v", ["\\\""]="\"", ["\\'"]="'", ["\\\\"]="\\"});
\r
71 local function readSpecialString()
\r
72 read("<"); read("<"); -- read <<
\r
74 if peek() == "\"" then
\r
75 local str = readString();
\r
76 elseif peek() ~= ">" then
\r
79 read(">"); read(">"); -- read >>
\r
82 local function readVar()
\r
84 while isVar(peek()) do
\r
89 local function readNumber()
\r
91 while isNumeric(peek()) do
\r
94 return tonumber(num);
\r
96 local readItem = nil;
\r
97 local function readTuple()
\r
99 read(); -- read { or [
\r
101 local item = readItem();
\r
102 if not item then break; end
\r
103 table.insert(t, item);
\r
105 read(); -- read } or ]
\r
108 readItem = function()
\r
110 if ch == nil then return nil end
\r
111 if ch == "{" or ch == "[" then
\r
112 return readTuple();
\r
113 elseif isAlpha(ch) then
\r
115 elseif isNumeric(ch) then
\r
116 return readNumber();
\r
117 elseif ch == "\"" then
\r
118 return readString();
\r
119 elseif ch == "<" then
\r
120 return readSpecialString();
\r
121 elseif isSpace(ch) or ch == "," or ch == "|" then
\r
125 --print("Unknown char: "..ch);
\r
129 local function readChunk()
\r
130 local x = readItem();
\r
131 if x then read("."); end
\r
134 local function readFile(filename)
\r
135 file = io.open(filename);
\r
136 if not file then error("File not found: "..filename); os.exit(0); end
\r
138 local x = readChunk();
\r
139 if not x and peek() then error("Invalid char: "..peek()); end
\r
146 function parseFile(file)
\r
147 return readFile(file);
\r