lib/js2lua.lua

Fri, 15 Oct 2010 15:17:17 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Fri, 15 Oct 2010 15:17:17 +0100
changeset 0
b2e55f320d48
permissions
-rw-r--r--

Initial commit

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