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