code / nomsu

Lines6.6K Lua5.1K PEG1.3K make117
2 others 83
Markdown60 Bourne Again Shell23
(107 lines)
1 local lpeg = require('lpeg')
2 local re = require('re')
3 lpeg.setmaxstack(20000)
4 local P, R, S, C, Cmt, Carg, Cc
5 P, R, S, C, Cmt, Carg, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cmt, lpeg.Carg, lpeg.Cc
6 local foldr
7 foldr = function(...)
8 local inner = select(1, ...)
9 for i = 2, select('#', ...) do
10 assert(inner.type)
11 local outer = select(i, ...)
12 table.insert(outer, 1, inner)
13 outer.source.start = inner.source.start
14 inner = outer
15 end
16 assert(inner.type)
17 return inner
18 end
19 local DEFS
20 do
21 local _with_0 = { }
22 _with_0.nl = P("\r") ^ -1 * P("\n")
23 _with_0.tab = P("\t")
24 _with_0.at_break = lpeg.B(lpeg.S(";,. \r\n\t({[")) + -lpeg.B(1)
25 _with_0.tonumber = tonumber
26 _with_0.tochar = string.char
27 _with_0.unpack = unpack or table.unpack
28 _with_0["nil"] = Cc(nil)
29 _with_0.userdata = Carg(1)
30 _with_0.indentation = lpeg.Cmt(P(0), function(s, i)
31 local sub = string.sub
32 while i > 1 and sub(s, i - 1, i - 1) ~= '\n' do
33 i = i - 1
34 end
35 return true, (s:match("^ *", i))
36 end)
37 _with_0.utf8_char = (R("\194\223") * R("\128\191") + R("\224\239") * R("\128\191") * R("\128\191") + R("\240\244") * R("\128\191") * R("\128\191") * R("\128\191"))
38 _with_0.operator_char = S("#'`~@^&*+=<>?/%!|\\-") + (P("\xE2") * (R("\x88\x8B") + R("\xA8\xAB")) * R("\128\191"))
39 _with_0.Tree = function(t, userdata)
40 return userdata.make_tree(t, userdata)
41 end
42 _with_0.foldr = foldr
43 DEFS = _with_0
44 end
45 setmetatable(DEFS, {
46 __index = function(self, key)
47 do
48 local i = key:match("^ascii_(%d+)$")
49 if i then
50 local c = string.char(tonumber(i))
51 self[key] = c
52 return c
53 else
54 do
55 i = key:match("^number_(%d+)$")
56 if i then
57 local p = Cc(tonumber(i))
58 self[key] = p
59 return p
60 end
61 end
62 end
63 end
64 end
65 })
66 local peg_tidier = re.compile([[ file <- %nl* {~ (captured_def/line) (%nl+ (captured_def/line))* %nl* ~}
67 ident <- [a-zA-Z_][a-zA-Z0-9_]*
68 line <- [^%nl]*
69 captured_def <-
70 ({ident} (" "*) "(" {ident} ")" (" "*) "<-" {[^%nl]* (%nl+ " "+ [^%nl]*)*}) ->
71 "%1 <- ({| {:type:''->'%2':} {:start:{}:}
72 (%3)
73 {:stop:{}:} |} %%userdata) -> Tree"
74 ]])
75 local make_parser
76 make_parser = function(peg, make_tree)
77 if make_tree == nil then
78 make_tree = nil
79 end
80 peg = assert(peg_tidier:match(peg))
81 peg = assert(re.compile(peg, DEFS))
82 return function(input, filename)
83 if filename == nil then
84 filename = '???'
85 end
86 input = tostring(input)
87 local tree_mt = {
88 __index = {
89 source = input,
90 filename = filename
93 local userdata = {
94 make_tree = make_tree or (function(t)
95 return setmetatable(t, tree_mt)
96 end),
97 filename = filename,
98 file = input
100 local tree = peg:match(input, nil, userdata)
101 if not tree or type(tree) == 'number' then
102 error("File " .. tostring(filename) .. " failed to parse:\n" .. tostring(input))
103 end
104 return tree
105 end
106 end
107 return make_parser