X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=tools%2Ferlparse.lua;h=bfec3b4da2c17bdfd6fe0e07be0f74ee386282f7;hb=d70c6826bb26938b25135e955e52d8c25aa2429b;hp=0bd4b3b84a61988c03ca383b61509ac24363c3f1;hpb=7baa83edbd77d8d0a48b244160ef33d435b7f911;p=prosody.git diff --git a/tools/erlparse.lua b/tools/erlparse.lua index 0bd4b3b8..bfec3b4d 100644 --- a/tools/erlparse.lua +++ b/tools/erlparse.lua @@ -27,54 +27,63 @@ local function peek() return last; end -local _A, _a, _Z, _z, _0, _9, __, _space = string.byte("AaZz09_ ", 1, 8); -local function isAlpha(ch) +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) or (ch >= _a and ch <= _z); + 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 isVar(ch) +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 == __; + 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 escapes = {["\\b"]="\b", ["\\d"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"]="\n", ["\\r"]="\r", ["\\s"]="\s", ["\\t"]="\t", ["\\v"]="\v", ["\\\""]="\"", ["\\'"]="'", ["\\\\"]="\\"}; 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 readSpecialString() - read("<"); read("<"); -- read << - local str = ""; - if peek() == "\"" then - str = readString(); - elseif peek() ~= ">" then - error(); + if slash then + slash = slash..ch; + if not escapes[slash] then error("Unknown escape sequence: "..slash); end + str = str..escapes[slash]; + slash = nil; + elseif ch == "\"" then + break; + elseif ch == "\\" then + slash = ch; + else + str = str..ch; + end end - read(">"); read(">"); -- read >> return str; end -local function readVar() +local function readAtom1() local var = read(); - while isVar(peek()) do + 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 @@ -85,28 +94,60 @@ end local readItem = nil; local function readTuple() local t = {}; - read(); -- read { or [ + 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 ] - return t; + 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 isAlpha(ch) then - return readVar(); + 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 readSpecialString(); + return readBinary(); elseif isSpace(ch) or ch == "," or ch == "|" then read(); return readItem();