Mercurial > prosody-hg
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); |
