comparison tools/erlparse.lua @ 1572:1b87dfb76caa

ejabberd2prosody, erlparse: Add support for parsing non-ASCII strings and binaries, and atoms enclosed in single quotes
author Sergei Golovan
date Thu, 23 Jul 2009 01:38:13 +0100
parents 063d7be32fdd
children f79972ad8965
comparison
equal deleted inserted replaced
1571:063d7be32fdd 1572:1b87dfb76caa
25 local function peek() 25 local function peek()
26 if not last then last = read(); end 26 if not last then last = read(); end
27 return last; 27 return last;
28 end 28 end
29 29
30 local _A, _a, _Z, _z, _0, _9, __, _space = string.byte("AaZz09_ ", 1, 8); 30 local _A, _a, _Z, _z, _0, _9, __, _at, _space = string.byte("AaZz09@_ ", 1, 9);
31 local function isAlpha(ch) 31 local function isLowerAlpha(ch)
32 ch = string.byte(ch) or 0; 32 ch = string.byte(ch) or 0;
33 return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z); 33 return (ch >= _a and ch <= _z);
34 end 34 end
35 local function isNumeric(ch) 35 local function isNumeric(ch)
36 ch = string.byte(ch) or 0; 36 ch = string.byte(ch) or 0;
37 return (ch >= _0 and ch <= _9); 37 return (ch >= _0 and ch <= _9);
38 end 38 end
39 local function isVar(ch) 39 local function isAtom(ch)
40 ch = string.byte(ch) or 0; 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 == __; 41 return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z) or (ch >= _0 and ch <= _9) or ch == __ or ch == _at;
42 end 42 end
43 local function isSpace(ch) 43 local function isSpace(ch)
44 ch = string.byte(ch) or "x"; 44 ch = string.byte(ch) or "x";
45 return ch <= _space; 45 return ch <= _space;
46 end 46 end
55 str = str..ch; 55 str = str..ch;
56 end 56 end
57 str = str:gsub("\\.", {["\\b"]="\b", ["\\d"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]="\s", ["\\t"]="\t", ["\\v"]="\v", ["\\\""]="\"", ["\\'"]="'", ["\\\\"]="\\"}); 57 str = str:gsub("\\.", {["\\b"]="\b", ["\\d"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]="\s", ["\\t"]="\t", ["\\v"]="\v", ["\\\""]="\"", ["\\'"]="'", ["\\\\"]="\\"});
58 return str; 58 return str;
59 end 59 end
60 local function readSpecialString() 60 local function readAtom1()
61 read("<"); read("<"); -- read <<
62 local str = "";
63 if peek() == "\"" then
64 str = readString();
65 elseif peek() ~= ">" then
66 error();
67 end
68 read(">"); read(">"); -- read >>
69 return str;
70 end
71 local function readVar()
72 local var = read(); 61 local var = read();
73 while isVar(peek()) do 62 while isAtom(peek()) do
74 var = var..read(); 63 var = var..read();
75 end 64 end
76 return var; 65 return var;
66 end
67 local function readAtom2()
68 local str = read("'");
69 local slash = nil;
70 while true do
71 local ch = read();
72 str = str..ch;
73 if ch == "'" and not slash then break; end
74 end
75 return str;
77 end 76 end
78 local function readNumber() 77 local function readNumber()
79 local num = read(); 78 local num = read();
80 while isNumeric(peek()) do 79 while isNumeric(peek()) do
81 num = num..read(); 80 num = num..read();
83 return tonumber(num); 82 return tonumber(num);
84 end 83 end
85 local readItem = nil; 84 local readItem = nil;
86 local function readTuple() 85 local function readTuple()
87 local t = {}; 86 local t = {};
88 read(); -- read { or [ 87 local s = ""; -- string representation
88 read(); -- read {, or [, or <
89 while true do 89 while true do
90 local item = readItem(); 90 local item = readItem();
91 if not item then break; end 91 if not item then break; end
92 if type(item) ~= type(0) or item > 255 then
93 s = nil;
94 elseif s then
95 s = s..string.char(item);
96 end
92 table.insert(t, item); 97 table.insert(t, item);
93 end 98 end
94 read(); -- read } or ] 99 read(); -- read }, or ], or >
95 return t; 100 if s and s ~= "" then
101 return s
102 else
103 return t
104 end;
105 end
106 local function readBinary()
107 read("<"); -- read <
108 local t = readTuple();
109 read(">") -- read >
110 local ch = peek();
111 if type(t) == type("") then
112 -- binary is a list of integers
113 return t;
114 elseif type(t) == type({}) then
115 if t[1] then
116 -- binary contains string
117 return t[1];
118 else
119 -- binary is empty
120 return "";
121 end;
122 else
123 error();
124 end
96 end 125 end
97 readItem = function() 126 readItem = function()
98 local ch = peek(); 127 local ch = peek();
99 if ch == nil then return nil end 128 if ch == nil then return nil end
100 if ch == "{" or ch == "[" then 129 if ch == "{" or ch == "[" then
101 return readTuple(); 130 return readTuple();
102 elseif isAlpha(ch) then 131 elseif isLowerAlpha(ch) then
103 return readVar(); 132 return readAtom1();
133 elseif ch == "'" then
134 return readAtom2();
104 elseif isNumeric(ch) then 135 elseif isNumeric(ch) then
105 return readNumber(); 136 return readNumber();
106 elseif ch == "\"" then 137 elseif ch == "\"" then
107 return readString(); 138 return readString();
108 elseif ch == "<" then 139 elseif ch == "<" then
109 return readSpecialString(); 140 return readBinary();
110 elseif isSpace(ch) or ch == "," or ch == "|" then 141 elseif isSpace(ch) or ch == "," or ch == "|" then
111 read(); 142 read();
112 return readItem(); 143 return readItem();
113 else 144 else
114 --print("Unknown char: "..ch); 145 --print("Unknown char: "..ch);