Fri, 15 Oct 2010 15:17:17 +0100
Initial commit
0 | 1 | local t = { op = {}, keyword = {}, name = {}, eos = {}, string = {}, regex = {} }; |
2 | ||
3 | local debug = function (...) io.stderr:write(table.concat({...}, "\t")); io.stderr:write"\n";end; | |
4 | local debug = function () end | |
5 | ||
6 | local function read_balanced(tokens, start, left, right) | |
7 | local c = 0; | |
8 | for i=start,#tokens do | |
9 | if tokens[i].type == "op" then | |
10 | local token = tokens[i].value; | |
11 | if token == left then | |
12 | c = c + 1; | |
13 | elseif token == right then | |
14 | c = c - 1; | |
15 | end | |
16 | end | |
17 | if c == 0 then return i; end | |
18 | end | |
19 | return start; | |
20 | end | |
21 | ||
22 | local pair_op = { ["("] = ")", ["{"] = "}", ["["] = "]" }; | |
23 | local function read_balanced_to(tokens, start, to) | |
24 | local c = 0; | |
25 | local i = start; | |
26 | while i <= #tokens do | |
27 | if tokens[i].type == "op" or tokens[i].type == "eos" then | |
28 | local token = tokens[i].value; | |
29 | if token == to then return i; end | |
30 | ||
31 | if pair_op[token] then | |
32 | i = read_balanced(tokens, i, token, pair_op[token]); | |
33 | end | |
34 | end | |
35 | i = i + 1; | |
36 | end | |
37 | return nil; | |
38 | end | |
39 | ||
40 | function js2lua(tokens, write) | |
41 | ||
42 | -- Scan | |
43 | local i = 1; | |
44 | while i <= #tokens do | |
45 | local token = tokens[i]; | |
46 | debug(token.type, token.value); | |
47 | if token.type == "keyword" and token.value == "function" then | |
48 | local j = read_balanced_to(tokens, i+3, ")"); -- Find matching ) | |
49 | j = j + 1; -- j now points to { | |
50 | local k = read_balanced_to(tokens, j+1, "}"); | |
51 | table.remove(tokens, j); -- Remove { | |
52 | tokens[k-1].type, tokens[k-1].value = "keyword", "end"; | |
53 | elseif token.type == "keyword" and token.value == "if" then | |
54 | table.remove(tokens, i+1); -- Remove ( | |
55 | local j = read_balanced_to(tokens, i, ")"); | |
56 | tokens[j].type, tokens[j].value = "keyword", "then"; | |
57 | ||
58 | -- Make sure to end a single-statement block | |
59 | if tokens[j+1].type ~= "op" or tokens[j+1].value ~= "{" then | |
60 | local eos = read_balanced_to(tokens, j+1, ";"); | |
61 | if tokens[eos+1].type ~= "keyword" or tokens[eos+1].value ~= "else" then | |
62 | table.insert(tokens, eos+1, { type = "keyword", value = "end" }); | |
63 | end | |
64 | end | |
65 | elseif token.type == "keyword" and token.value == "else" then | |
66 | if tokens[i+1].type == "keyword" and tokens[i+1].value == "if" then | |
67 | token.value = "elseif"; | |
68 | table.remove(tokens, i+1); | |
69 | ||
70 | table.remove(tokens, i+1); -- Remove ( | |
71 | local j = read_balanced_to(tokens, i, ")"); | |
72 | tokens[j].type, tokens[j].value = "keyword", "then"; | |
73 | end | |
74 | ||
75 | -- Make sure to end a single-statement block | |
76 | if tokens[i+1].type ~= "op" or tokens[i+1].value ~= "{" then | |
77 | local eos = read_balanced_to(tokens, i+1, ";"); | |
78 | if tokens[eos+1].type ~= "keyword" or tokens[eos+1].value ~= "else" then | |
79 | table.insert(tokens, eos+1, { type = "keyword", value = "end" }); | |
80 | end | |
81 | end | |
82 | elseif token.type == "op" and token.value == "+" and tokens[i-1].type == "string" then | |
83 | token.value = ".."; | |
84 | elseif token.type == "op" and token.value == "{" then | |
85 | elseif token.type == "keyword" and token.value == "var" then | |
86 | token.value = "local"; | |
87 | end | |
88 | i = i + 1; | |
89 | end | |
90 | ||
91 | -- Serialize | |
92 | local last_token_type; | |
93 | for _, token in ipairs(tokens) do | |
94 | if token.type == "string" then | |
95 | write("\""); | |
96 | elseif token.type == "name" then | |
97 | if last_token_type == "keyword" or last_token_type == "name" or last_token_type == "number" then | |
98 | write(" "); | |
99 | end | |
100 | elseif token.type == "keyword" then | |
101 | if last_token_type == "keyword" or last_token_type == "name" or last_token_type == "number" then | |
102 | write(" "); | |
103 | end | |
104 | end | |
105 | write(token.value); | |
106 | if token.type == "string" then | |
107 | write("\""); | |
108 | end | |
109 | last_token_type = token.type; | |
110 | end | |
111 | end | |
112 | ||
113 | return js2lua; |