lib/js2lua.lua

changeset 0
b2e55f320d48
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/js2lua.lua	Fri Oct 15 15:17:17 2010 +0100
@@ -0,0 +1,113 @@
+local t = { op = {}, keyword = {}, name = {}, eos = {}, string = {}, regex = {} };
+
+local debug = function (...) io.stderr:write(table.concat({...}, "\t")); io.stderr:write"\n";end;
+local debug = function () end
+
+local function read_balanced(tokens, start, left, right)
+	local c = 0;
+	for i=start,#tokens do
+		if tokens[i].type == "op" then
+			local token = tokens[i].value;
+			if token == left then
+				c = c + 1;
+			elseif token == right then
+				c = c - 1;
+			end
+		end
+		if c == 0 then return i; end
+	end
+	return start;
+end
+
+local pair_op = { ["("] = ")", ["{"] = "}", ["["] = "]" };
+local function read_balanced_to(tokens, start, to)
+	local c = 0;
+	local i = start;
+	while i <= #tokens do
+		if tokens[i].type == "op" or tokens[i].type == "eos" then
+			local token = tokens[i].value;
+			if token == to then return i; end
+			
+			if pair_op[token] then
+				i = read_balanced(tokens, i, token, pair_op[token]);
+			end
+		end
+		i = i + 1;
+	end
+	return nil;
+end
+
+function js2lua(tokens, write)
+
+-- Scan
+	local i = 1;
+	while i <= #tokens do
+		local token = tokens[i];
+		debug(token.type, token.value);
+		if token.type == "keyword" and token.value == "function" then
+			local j = read_balanced_to(tokens, i+3, ")"); -- Find matching )
+			j = j + 1; -- j now points to {
+			local k = read_balanced_to(tokens, j+1, "}");
+			table.remove(tokens, j); -- Remove {
+			tokens[k-1].type, tokens[k-1].value = "keyword", "end";
+		elseif token.type == "keyword" and token.value == "if" then
+			table.remove(tokens, i+1); -- Remove (
+			local j = read_balanced_to(tokens, i, ")");
+			tokens[j].type, tokens[j].value = "keyword", "then";
+
+			-- Make sure to end a single-statement block
+			if tokens[j+1].type ~= "op" or tokens[j+1].value ~= "{" then
+				local eos = read_balanced_to(tokens, j+1, ";");
+				if tokens[eos+1].type ~= "keyword" or tokens[eos+1].value ~= "else" then
+					table.insert(tokens, eos+1, { type = "keyword", value = "end" });
+				end
+			end
+		elseif token.type == "keyword" and token.value == "else" then
+			if tokens[i+1].type == "keyword" and tokens[i+1].value == "if" then
+				token.value = "elseif";
+				table.remove(tokens, i+1);
+
+				table.remove(tokens, i+1); -- Remove (
+				local j = read_balanced_to(tokens, i, ")");
+				tokens[j].type, tokens[j].value = "keyword", "then";
+			end
+
+			-- Make sure to end a single-statement block
+			if tokens[i+1].type ~= "op" or tokens[i+1].value ~= "{" then
+				local eos = read_balanced_to(tokens, i+1, ";");
+				if tokens[eos+1].type ~= "keyword" or tokens[eos+1].value ~= "else" then
+					table.insert(tokens, eos+1, { type = "keyword", value = "end" });
+				end
+			end			
+		elseif token.type == "op" and token.value == "+" and tokens[i-1].type == "string" then
+			token.value = "..";
+		elseif token.type == "op" and token.value == "{" then
+		elseif token.type == "keyword" and token.value == "var" then
+			token.value = "local";
+		end
+		i = i + 1;
+	end
+
+-- Serialize
+	local last_token_type;
+	for _, token in ipairs(tokens) do
+		if token.type == "string" then
+			write("\"");
+		elseif token.type == "name" then
+			if last_token_type == "keyword" or last_token_type == "name" or last_token_type == "number" then
+				write(" ");
+			end
+		elseif token.type == "keyword" then
+			if last_token_type == "keyword" or last_token_type == "name" or last_token_type == "number" then
+				write(" ");
+			end
+		end
+		write(token.value);
+		if token.type == "string" then
+			write("\"");
+		end
+		last_token_type = token.type;
+	end
+end
+
+return js2lua;

mercurial