Changeset

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 1571:063d7be32fdd
children 1573:43cf3d027455 1574:3692706f78e3
files tools/erlparse.lua
diffstat 1 files changed, 55 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/tools/erlparse.lua	Tue Jul 21 19:23:03 2009 +0100
+++ b/tools/erlparse.lua	Thu Jul 23 01:38:13 2009 +0100
@@ -27,18 +27,18 @@
 	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";
@@ -57,24 +57,23 @@
 	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();
-	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 +84,60 @@
 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();