0.2->0.3
[prosody.git] / tools / erlparse.lua
1 -- Prosody IM v0.3
2 -- Copyright (C) 2008 Matthew Wild
3 -- Copyright (C) 2008 Waqas Hussain
4 -- 
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
8
9
10 \r
11 local file = nil;\r
12 local last = nil;\r
13 local function read(expected)\r
14         local ch;\r
15         if last then\r
16                 ch = last; last = nil;\r
17         else ch = file:read(1); end\r
18         if expected and ch ~= expected then error("expected: "..expected.."; got: "..(ch or "nil")); end\r
19         return ch;\r
20 end\r
21 local function pushback(ch)\r
22         if last then error(); end\r
23         last = ch;\r
24 end\r
25 local function peek()\r
26         if not last then last = read(); end\r
27         return last;\r
28 end\r
29 \r
30 local _A, _a, _Z, _z, _0, _9, __, _space = string.byte("AaZz09_ ", 1, 8);\r
31 local function isAlpha(ch)\r
32         ch = string.byte(ch) or 0;\r
33         return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z);\r
34 end\r
35 local function isNumeric(ch)\r
36         ch = string.byte(ch) or 0;\r
37         return (ch >= _0 and ch <= _9);\r
38 end\r
39 local function isVar(ch)\r
40         ch = string.byte(ch) or 0;\r
41         return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z) or (ch >= _0 and ch <= _9) or ch == __;\r
42 end\r
43 local function isSpace(ch)\r
44         ch = string.byte(ch) or "x";\r
45         return ch <= _space;\r
46 end\r
47 \r
48 local function readString()\r
49         read("\""); -- skip quote\r
50         local slash = nil;\r
51         local str = "";\r
52         while true do\r
53                 local ch = read();\r
54                 if ch == "\"" and not slash then break; end\r
55                 str = str..ch;\r
56         end\r
57         str = str:gsub("\\.", {["\\b"]="\b", ["\\d"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]="\s", ["\\t"]="\t", ["\\v"]="\v", ["\\\""]="\"", ["\\'"]="'", ["\\\\"]="\\"});\r
58         return str;\r
59 end\r
60 local function readSpecialString()\r
61         read("<"); read("<"); -- read <<\r
62         local str = "";\r
63         if peek() == "\"" then\r
64                 str = readString();\r
65         elseif peek() ~= ">" then\r
66                 error();\r
67         end\r
68         read(">"); read(">"); -- read >>\r
69         return str;\r
70 end\r
71 local function readVar()\r
72         local var = read();\r
73         while isVar(peek()) do\r
74                 var = var..read();\r
75         end\r
76         return var;\r
77 end\r
78 local function readNumber()\r
79         local num = read();\r
80         while isNumeric(peek()) do\r
81                 num = num..read();\r
82         end\r
83         return tonumber(num);\r
84 end\r
85 local readItem = nil;\r
86 local function readTuple()\r
87         local t = {};\r
88         read(); -- read { or [\r
89         while true do\r
90                 local item = readItem();\r
91                 if not item then break; end\r
92                 table.insert(t, item);\r
93         end\r
94         read(); -- read } or ]\r
95         return t;\r
96 end\r
97 readItem = function()\r
98         local ch = peek();\r
99         if ch == nil then return nil end\r
100         if ch == "{" or ch == "[" then\r
101                 return readTuple();\r
102         elseif isAlpha(ch) then\r
103                 return readVar();\r
104         elseif isNumeric(ch) then\r
105                 return readNumber();\r
106         elseif ch == "\"" then\r
107                 return readString();\r
108         elseif ch == "<" then\r
109                 return readSpecialString();\r
110         elseif isSpace(ch) or ch == "," or ch == "|" then\r
111                 read();\r
112                 return readItem();\r
113         else\r
114                 --print("Unknown char: "..ch);\r
115                 return nil;\r
116         end\r
117 end\r
118 local function readChunk()\r
119         local x = readItem();\r
120         if x then read("."); end\r
121         return x;\r
122 end\r
123 local function readFile(filename)\r
124         file = io.open(filename);\r
125         if not file then error("File not found: "..filename); os.exit(0); end\r
126         return function()\r
127                 local x = readChunk();\r
128                 if not x and peek() then error("Invalid char: "..peek()); end\r
129                 return x;\r
130         end;\r
131 end\r
132 \r
133 module "erlparse"\r
134 \r
135 function parseFile(file)\r
136         return readFile(file);\r
137 end\r
138 \r
139 return _M;\r