Merge with 0.5
[prosody.git] / tools / erlparse.lua
index c4372243273838cc0743a1ffa51fee8b405391fa..f2d410a3626bd9dd512f9b57420d5e8b8265535b 100644 (file)
-\r
-local file = nil;\r
-local last = nil;\r
-local function read(expected)\r
-       local ch;\r
-       if last then\r
-               ch = last; last = nil;\r
-       else ch = file:read(1); end\r
-       if expected and ch ~= expected then error("expected: "..expected.."; got: "..(ch or "nil")); end\r
-       return ch;\r
-end\r
-local function pushback(ch)\r
-       if last then error(); end\r
-       last = ch;\r
-end\r
-local function peek()\r
-       if not last then last = read(); end\r
-       return last;\r
-end\r
-\r
-local _A, _a, _Z, _z, _0, _9, __, _space = string.byte("AaZz09_ ", 1, 8);\r
-local function isAlpha(ch)\r
-       ch = string.byte(ch) or 0;\r
-       return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z);\r
-end\r
-local function isNumeric(ch)\r
-       ch = string.byte(ch) or 0;\r
-       return (ch >= _0 and ch <= _9);\r
-end\r
-local function isVar(ch)\r
-       ch = string.byte(ch) or 0;\r
-       return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z) or (ch >= _0 and ch <= _9) or ch == __;\r
-end\r
-local function isSpace(ch)\r
-       ch = string.byte(ch) or "x";\r
-       return ch <= _space;\r
-end\r
-\r
-local function readString()\r
-       read("\""); -- skip quote\r
-       local slash = nil;\r
-       local str = "";\r
-       while true do\r
-               local ch = read();\r
-               if ch == "\"" and not slash then break; end\r
-               str = str..ch;\r
-       end\r
-       str = str:gsub("\\.", {["\\b"]="\b", ["\\d"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]="\s", ["\\t"]="\t", ["\\v"]="\v", ["\\\""]="\"", ["\\'"]="'", ["\\\\"]="\\"});\r
-       return str;\r
-end\r
-local function readSpecialString()\r
-       read("<"); read("<"); -- read <<\r
-       local str = "";\r
-       if peek() == "\"" then\r
-               local str = readString();\r
-       elseif peek() ~= ">" then\r
-               error();\r
-       end\r
-       read(">"); read(">"); -- read >>\r
-       return str;\r
-end\r
-local function readVar()\r
-       local var = read();\r
-       while isVar(peek()) do\r
-               var = var..read();\r
-       end\r
-       return var;\r
-end\r
-local function readNumber()\r
-       local num = read();\r
-       while isNumeric(peek()) do\r
-               num = num..read();\r
-       end\r
-       return tonumber(num);\r
-end\r
-local readItem = nil;\r
-local function readTuple()\r
-       local t = {};\r
-       read(); -- read { or [\r
-       while true do\r
-               local item = readItem();\r
-               if not item then break; end\r
-               table.insert(t, item);\r
-       end\r
-       read(); -- read } or ]\r
-       return t;\r
-end\r
-readItem = function()\r
-       local ch = peek();\r
-       if ch == nil then return nil end\r
-       if ch == "{" or ch == "[" then\r
-               return readTuple();\r
-       elseif isAlpha(ch) then\r
-               return readVar();\r
-       elseif isNumeric(ch) then\r
-               return readNumber();\r
-       elseif ch == "\"" then\r
-               return readString();\r
-       elseif ch == "<" then\r
-               return readSpecialString();\r
-       elseif isSpace(ch) or ch == "," then\r
-               read();\r
-               return readItem();\r
-       else\r
-               --print("Unknown char: "..ch);\r
-               return nil;\r
-       end\r
-end\r
-local function readChunk()\r
-       local x = readItem();\r
-       if x then read("."); end\r
-       return x;\r
-end\r
-local function readFile(filename)\r
-       file = io.open(filename);\r
-       if not file then error("File not found: "..filename); os.exit(0); end\r
-       return function()\r
-               local x = readChunk();\r
-               if not x and peek() then error("Invalid char: "..peek()); end\r
-               return x;\r
-       end;\r
-end\r
-\r
-module "erlparse"\r
-\r
-function parseFile(file)\r
-       return readFile(file);\r
-end\r
-\r
-return _M;\r
+-- Prosody IM
+-- Copyright (C) 2008-2009 Matthew Wild
+-- Copyright (C) 2008-2009 Waqas Hussain
+-- 
+-- This project is MIT/X11 licensed. Please see the
+-- COPYING file in the source package for more information.
+--
+
+
+
+local file = nil;
+local last = nil;
+local function read(expected)
+       local ch;
+       if last then
+               ch = last; last = nil;
+       else ch = file:read(1); end
+       if expected and ch ~= expected then error("expected: "..expected.."; got: "..(ch or "nil")); end
+       return ch;
+end
+local function pushback(ch)
+       if last then error(); end
+       last = ch;
+end
+local function peek()
+       if not last then last = read(); end
+       return last;
+end
+
+local _A, _a, _Z, _z, _0, _9, __, _at, _space = string.byte("AaZz09@_ ", 1, 9);
+local function isLowerAlpha(ch)
+       ch = string.byte(ch) or 0;
+       return (ch >= _a and ch <= _z);
+end
+local function isNumeric(ch)
+       ch = string.byte(ch) or 0;
+       return (ch >= _0 and ch <= _9);
+end
+local function isAtom(ch)
+       ch = string.byte(ch) or 0;
+       return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z) or (ch >= _0 and ch <= _9) or ch == __ or ch == _at;
+end
+local function isSpace(ch)
+       ch = string.byte(ch) or "x";
+       return ch <= _space;
+end
+
+local function readString()
+       read("\""); -- skip quote
+       local slash = nil;
+       local str = "";
+       while true do
+               local ch = read();
+               if ch == "\"" and not slash then break; end
+               str = str..ch;
+       end
+       str = str:gsub("\\.", {["\\b"]="\b", ["\\d"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]="\s", ["\\t"]="\t", ["\\v"]="\v", ["\\\""]="\"", ["\\'"]="'", ["\\\\"]="\\"});
+       return str;
+end
+local function readAtom1()
+       local var = read();
+       while isAtom(peek()) do
+               var = var..read();
+       end
+       return var;
+end
+local function readAtom2()
+       local str = read("'");
+       local slash = nil;
+       while true do
+               local ch = read();
+               str = str..ch;
+               if ch == "'" and not slash then break; end
+       end
+       return str;
+end
+local function readNumber()
+       local num = read();
+       while isNumeric(peek()) do
+               num = num..read();
+       end
+       return tonumber(num);
+end
+local readItem = nil;
+local function readTuple()
+       local t = {};
+       local s = ""; -- string representation
+       read(); -- read {, or [, or <
+       while true do
+               local item = readItem();
+               if not item then break; end
+               if type(item) ~= type(0) or item > 255 then
+                       s = nil;
+               elseif s then
+                       s = s..string.char(item);
+               end
+               table.insert(t, item);
+       end
+       read(); -- read }, or ], or >
+       if s and s ~= "" then
+               return s
+       else
+               return t
+       end;
+end
+local function readBinary()
+       read("<"); -- read <
+       local t = readTuple();
+       read(">") -- read >
+       local ch = peek();
+       if type(t) == type("") then
+               -- binary is a list of integers
+               return t;
+       elseif type(t) == type({}) then
+               if t[1] then
+                       -- binary contains string
+                       return t[1];
+               else
+                       -- binary is empty
+                       return "";
+               end;
+       else
+               error();
+       end
+end
+readItem = function()
+       local ch = peek();
+       if ch == nil then return nil end
+       if ch == "{" or ch == "[" then
+               return readTuple();
+       elseif isLowerAlpha(ch) then
+               return readAtom1();
+       elseif ch == "'" then
+               return readAtom2();
+       elseif isNumeric(ch) then
+               return readNumber();
+       elseif ch == "\"" then
+               return readString();
+       elseif ch == "<" then
+               return readBinary();
+       elseif isSpace(ch) or ch == "," or ch == "|" then
+               read();
+               return readItem();
+       else
+               --print("Unknown char: "..ch);
+               return nil;
+       end
+end
+local function readChunk()
+       local x = readItem();
+       if x then read("."); end
+       return x;
+end
+local function readFile(filename)
+       file = io.open(filename);
+       if not file then error("File not found: "..filename); os.exit(0); end
+       return function()
+               local x = readChunk();
+               if not x and peek() then error("Invalid char: "..peek()); end
+               return x;
+       end;
+end
+
+module "erlparse"
+
+function parseFile(file)
+       return readFile(file);
+end
+
+return _M;