• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

andremm / lua-parser / #3

07 Jan 2026 03:48PM UTC coverage: 97.719% (-0.7%) from 98.417%
#3

push

github

andremm
adding coverage report

2099 of 2148 relevant lines covered (97.72%)

23.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.64
/lua-parser/pp.lua
1
--[[
2
This module impements a pretty printer to the AST
3
]]
4
local pp = {}
1✔
5

6
local block2str, stm2str, exp2str, var2str
7
local explist2str, varlist2str, parlist2str, fieldlist2str
8

9
local function iscntrl (x)
10
  if (x >= 0 and x <= 31) or (x == 127) then return true end
281✔
11
  return false
278✔
12
end
13

14
local function isprint (x)
15
  return not iscntrl(x)
281✔
16
end
17

18
local function fixed_string (str)
19
  local new_str = ""
34✔
20
  for i=1,string.len(str) do
346✔
21
    char = string.byte(str, i)
312✔
22
    if char == 34 then new_str = new_str .. string.format("\\\"")
312✔
23
    elseif char == 92 then new_str = new_str .. string.format("\\\\")
308✔
24
    elseif char == 7 then new_str = new_str .. string.format("\\a")
300✔
25
    elseif char == 8 then new_str = new_str .. string.format("\\b")
298✔
26
    elseif char == 12 then new_str = new_str .. string.format("\\f")
298✔
27
    elseif char == 10 then new_str = new_str .. string.format("\\n")
298✔
28
    elseif char == 13 then new_str = new_str .. string.format("\\r")
283✔
29
    elseif char == 9 then new_str = new_str .. string.format("\\t")
283✔
30
    elseif char == 11 then new_str = new_str .. string.format("\\v")
281✔
31
    else
32
      if isprint(char) then
281✔
33
        new_str = new_str .. string.format("%c", char)
278✔
34
      else
35
        new_str = new_str .. string.format("\\%03d", char)
3✔
36
      end
37
    end
38
  end
39
  return new_str
34✔
40
end
41

42
local function name2str (name)
43
  return string.format('"%s"', name)
228✔
44
end
45

46
local function boolean2str (b)
47
  return string.format('"%s"', tostring(b))
2✔
48
end
49

50
local function number2str (n)
51
  return string.format('"%s"', tostring(n))
123✔
52
end
53

54
local function string2str (s)
55
  return string.format('"%s"', fixed_string(s))
34✔
56
end
57

58
function var2str (var)
×
59
  local tag = var.tag
173✔
60
  local str = "`" .. tag
173✔
61
  if tag == "Id" then -- `Id{ <string> }
173✔
62
    str = str .. " " .. name2str(var[1])
161✔
63
  elseif tag == "Index" then -- `Index{ expr expr }
12✔
64
    str = str .. "{ "
12✔
65
    str = str .. exp2str(var[1]) .. ", "
12✔
66
    str = str .. exp2str(var[2])
12✔
67
    str = str .. " }"
12✔
68
  else
69
    error("expecting a variable, but got a " .. tag)
×
70
  end
71
  return str
173✔
72
end
73

74
function varlist2str (varlist)
×
75
  local l = {}
83✔
76
  for k, v in ipairs(varlist) do
180✔
77
    l[k] = var2str(v)
97✔
78
  end
79
  return "{ " .. table.concat(l, ", ") .. " }"
83✔
80
end
81

82
function parlist2str (parlist)
×
83
  local l = {}
16✔
84
  local len = #parlist
16✔
85
  local is_vararg = false
16✔
86
  if len > 0 and parlist[len].tag == "Dots" then
16✔
87
    is_vararg = true
11✔
88
    len = len - 1
11✔
89
  end
90
  local i = 1
16✔
91
  while i <= len do
32✔
92
    l[i] = var2str(parlist[i])
16✔
93
    i = i + 1
16✔
94
  end
95
  if is_vararg then
16✔
96
    l[i] = "`" .. parlist[i].tag
11✔
97
  end
98
  return "{ " .. table.concat(l, ", ") .. " }"
16✔
99
end
100

101
function fieldlist2str (fieldlist)
×
102
  local l = {}
61✔
103
  for k, v in ipairs(fieldlist) do
129✔
104
    local tag = v.tag
68✔
105
    if tag == "Pair" then -- `Pair{ expr expr }
68✔
106
      l[k] = "`" .. tag .. "{ "
8✔
107
      l[k] = l[k] .. exp2str(v[1]) .. ", " .. exp2str(v[2])
8✔
108
      l[k] = l[k] .. " }"
8✔
109
    else -- expr
110
      l[k] = exp2str(v)
60✔
111
    end
112
  end
113
  if #l > 0 then
61✔
114
    return "{ " .. table.concat(l, ", ") .. " }"
57✔
115
  else
116
    return ""
4✔
117
  end
118
end
119

120
function exp2str (exp)
×
121
  local tag = exp.tag
352✔
122
  local str = "`" .. tag
352✔
123
  if tag == "Nil" or
352✔
124
     tag == "Dots" then
351✔
125
  elseif tag == "Boolean" then -- `Boolean{ <boolean> }
342✔
126
    str = str .. " " .. boolean2str(exp[1])
2✔
127
  elseif tag == "Number" then -- `Number{ <number> }
340✔
128
    str = str .. " " .. number2str(exp[1])
123✔
129
  elseif tag == "String" then -- `String{ <string> }
217✔
130
    str = str .. " " .. string2str(exp[1])
34✔
131
  elseif tag == "Function" then -- `Function{ { `Id{ <string> }* `Dots? } block }
183✔
132
    str = str .. "{ "
16✔
133
    str = str .. parlist2str(exp[1]) .. ", "
16✔
134
    str = str .. block2str(exp[2])
16✔
135
    str = str .. " }"
16✔
136
  elseif tag == "Table" then -- `Table{ ( `Pair{ expr expr } | expr )* }
167✔
137
    str = str .. fieldlist2str(exp)
61✔
138
  elseif tag == "Op" then -- `Op{ opid expr expr? }
106✔
139
    str = str .. "{ "
45✔
140
    str = str .. name2str(exp[1]) .. ", "
45✔
141
    str = str .. exp2str(exp[2])
45✔
142
    if exp[3] then
45✔
143
      str = str .. ", " .. exp2str(exp[3])
43✔
144
    end
145
    str = str .. " }"
45✔
146
  elseif tag == "Paren" then -- `Paren{ expr }
61✔
147
    str = str .. "{ " .. exp2str(exp[1]) .. " }"
1✔
148
  elseif tag == "Call" then -- `Call{ expr expr* }
60✔
149
    str = str .. "{ "
6✔
150
    str = str .. exp2str(exp[1])
6✔
151
    if exp[2] then
6✔
152
      for i=2, #exp do
6✔
153
        str = str .. ", " .. exp2str(exp[i])
3✔
154
      end
155
    end
156
    str = str .. " }"
6✔
157
  elseif tag == "Invoke" then -- `Invoke{ expr `String{ <string> } expr* }
54✔
158
    str = str .. "{ "
1✔
159
    str = str .. exp2str(exp[1]) .. ", "
1✔
160
    str = str .. exp2str(exp[2])
1✔
161
    if exp[3] then
1✔
162
      for i=3, #exp do
2✔
163
        str = str .. ", " .. exp2str(exp[i])
1✔
164
      end
165
    end
166
    str = str .. " }"
1✔
167
  elseif tag == "Id" or -- `Id{ <string> }
53✔
168
         tag == "Index" then -- `Index{ expr expr }
6✔
169
    str = var2str(exp)
53✔
170
  else
171
    error("expecting an expression, but got a " .. tag)
×
172
  end
173
  return str
352✔
174
end
175

176
function explist2str (explist)
×
177
  local l = {}
109✔
178
  for k, v in ipairs(explist) do
226✔
179
    l[k] = exp2str(v)
117✔
180
  end
181
  if #l > 0 then
109✔
182
    return "{ " .. table.concat(l, ", ") .. " }"
101✔
183
  else
184
    return ""
8✔
185
  end
186
end
187

188
function stm2str (stm)
×
189
  local tag = stm.tag
175✔
190
  local str = "`" .. tag
175✔
191
  if tag == "Do" then -- `Do{ stat* }
175✔
192
    local l = {}
12✔
193
    for k, v in ipairs(stm) do
29✔
194
      l[k] = stm2str(v)
17✔
195
    end
196
    str = str .. "{ " .. table.concat(l, ", ") .. " }"
12✔
197
  elseif tag == "Set" then -- `Set{ {lhs+} {expr+} }
163✔
198
    str = str .. "{ "
65✔
199
    str = str .. varlist2str(stm[1]) .. ", "
65✔
200
    str = str .. explist2str(stm[2])
65✔
201
    str = str .. " }"
65✔
202
  elseif tag == "While" then -- `While{ expr block }
98✔
203
    str = str .. "{ "
4✔
204
    str = str .. exp2str(stm[1]) .. ", "
4✔
205
    str = str .. block2str(stm[2])
4✔
206
    str = str .. " }"
4✔
207
  elseif tag == "Repeat" then -- `Repeat{ block expr }
94✔
208
    str = str .. "{ "
2✔
209
    str = str .. block2str(stm[1]) .. ", "
2✔
210
    str = str .. exp2str(stm[2])
2✔
211
    str = str .. " }"
2✔
212
  elseif tag == "If" then -- `If{ (expr block)+ block? }
92✔
213
    str = str .. "{ "
7✔
214
    local len = #stm
7✔
215
    if len % 2 == 0 then
7✔
216
      local l = {}
4✔
217
      for i=1,len-2,2 do
7✔
218
        str = str .. exp2str(stm[i]) .. ", " .. block2str(stm[i+1]) .. ", "
3✔
219
      end
220
      str = str .. exp2str(stm[len-1]) .. ", " .. block2str(stm[len])
4✔
221
    else
222
      local l = {}
3✔
223
      for i=1,len-3,2 do
4✔
224
        str = str .. exp2str(stm[i]) .. ", " .. block2str(stm[i+1]) .. ", "
1✔
225
      end
226
      str = str .. exp2str(stm[len-2]) .. ", " .. block2str(stm[len-1]) .. ", "
3✔
227
      str = str .. block2str(stm[len])
3✔
228
    end
229
    str = str .. " }"
7✔
230
  elseif tag == "Fornum" then -- `Fornum{ ident expr expr expr? block }
85✔
231
    str = str .. "{ "
3✔
232
    str = str .. var2str(stm[1]) .. ", "
3✔
233
    str = str .. exp2str(stm[2]) .. ", "
3✔
234
    str = str .. exp2str(stm[3]) .. ", "
3✔
235
    if stm[5] then
3✔
236
      str = str .. exp2str(stm[4]) .. ", "
1✔
237
      str = str .. block2str(stm[5])
1✔
238
    else
239
      str = str .. block2str(stm[4])
2✔
240
    end
241
    str = str .. " }"
3✔
242
  elseif tag == "Forin" then -- `Forin{ {ident+} {expr+} block }
82✔
243
    str = str .. "{ "
1✔
244
    str = str .. varlist2str(stm[1]) .. ", "
1✔
245
    str = str .. explist2str(stm[2]) .. ", "
1✔
246
    str = str .. block2str(stm[3])
1✔
247
    str = str .. " }"
1✔
248
  elseif tag == "Local" then -- `Local{ {ident+} {expr+}? }
81✔
249
    str = str .. "{ "
17✔
250
    str = str .. varlist2str(stm[1])
17✔
251
    if #stm[2] > 0 then
17✔
252
      str = str .. ", " .. explist2str(stm[2])
15✔
253
    else
254
      str = str .. ", " .. "{  }"
2✔
255
    end
256
    str = str .. " }"
17✔
257
  elseif tag == "Localrec" then -- `Localrec{ ident expr }
64✔
258
    str = str .. "{ "
4✔
259
    str = str .. "{ " .. var2str(stm[1][1]) .. " }, "
4✔
260
    str = str .. "{ " .. exp2str(stm[2][1]) .. " }"
4✔
261
    str = str .. " }"
4✔
262
  elseif tag == "Goto" or -- `Goto{ <string> }
60✔
263
         tag == "Label" then -- `Label{ <string> }
52✔
264
    str = str .. "{ " .. name2str(stm[1]) .. " }"
22✔
265
  elseif tag == "Return" then -- `Return{ <expr>* }
38✔
266
    str = str .. explist2str(stm)
28✔
267
  elseif tag == "Break" then
10✔
268
  elseif tag == "Call" then -- `Call{ expr expr* }
3✔
269
    str = str .. "{ "
3✔
270
    str = str .. exp2str(stm[1])
3✔
271
    if stm[2] then
3✔
272
      for i=2, #stm do
5✔
273
        str = str .. ", " .. exp2str(stm[i])
3✔
274
      end
275
    end
276
    str = str .. " }"
3✔
277
  elseif tag == "Invoke" then -- `Invoke{ expr `String{ <string> } expr* }
×
278
    str = str .. "{ "
×
279
    str = str .. exp2str(stm[1]) .. ", "
×
280
    str = str .. exp2str(stm[2])
×
281
    if stm[3] then
×
282
      for i=3, #stm do
×
283
        str = str .. ", " .. exp2str(stm[i])
×
284
      end
285
    end
286
    str = str .. " }"
×
287
  else
288
    error("expecting a statement, but got a " .. tag)
×
289
  end
290
  return str
175✔
291
end
292

293
function block2str (block)
×
294
  local l = {}
138✔
295
  for k, v in ipairs(block) do
296✔
296
    l[k] = stm2str(v)
158✔
297
  end
298
  return "{ " .. table.concat(l, ", ") .. " }"
138✔
299
end
300

301
function pp.tostring (t)
1✔
302
  assert(type(t) == "table")
98✔
303
  return block2str(t)
98✔
304
end
305

306
function pp.print (t)
1✔
307
  assert(type(t) == "table")
×
308
  print(pp.tostring(t))
×
309
end
310

311
function pp.dump (t, i)
1✔
312
  if i == nil then i = 0 end
×
313
  io.write(string.format("{\n"))
×
314
  io.write(string.format("%s[tag] = %s\n", string.rep(" ", i+2), t.tag or "nil"))
×
315
  io.write(string.format("%s[pos] = %s\n", string.rep(" ", i+2), t.pos or "nil"))
×
316
  for k,v in ipairs(t) do
×
317
    io.write(string.format("%s[%s] = ", string.rep(" ", i+2), tostring(k)))
×
318
    if type(v) == "table" then
×
319
      pp.dump(v,i+2)
×
320
    else
321
      io.write(string.format("%s\n", tostring(v)))
×
322
    end
323
  end
324
  io.write(string.format("%s}\n", string.rep(" ", i)))
×
325
end
326

327
return pp
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc