diff options
author | Sergio Medeiros <sqmedeiros@gmail.com> | 2015-03-23 15:09:08 -0300 |
---|---|---|
committer | Sergio Medeiros <sqmedeiros@gmail.com> | 2015-03-23 15:09:08 -0300 |
commit | f124b2d4449a13ac21af9581a44b4455d89eaddb (patch) | |
tree | e0486555ac811c5f712927f110bb7bcda8569adf /re.lua | |
parent | 0e93d536ba2d312502737cce2ab0cc21393c4842 (diff) | |
download | lpeglabel-f124b2d4449a13ac21af9581a44b4455d89eaddb.tar.gz lpeglabel-f124b2d4449a13ac21af9581a44b4455d89eaddb.tar.bz2 lpeglabel-f124b2d4449a13ac21af9581a44b4455d89eaddb.zip |
Renaming "re.lua" to "relabel.lua".
Adding examples, README and lpeglabel.html
Diffstat (limited to 're.lua')
-rw-r--r-- | re.lua | 282 |
1 files changed, 0 insertions, 282 deletions
@@ -1,282 +0,0 @@ | |||
1 | -- $Id: re.lua,v 1.44 2013/03/26 20:11:40 roberto Exp $ | ||
2 | |||
3 | -- imported functions and modules | ||
4 | local tonumber, type, print, error = tonumber, type, print, error | ||
5 | local setmetatable = setmetatable | ||
6 | local unpack = table.unpack | ||
7 | local m = require"lpeglabel" | ||
8 | |||
9 | -- 'm' will be used to parse expressions, and 'mm' will be used to | ||
10 | -- create expressions; that is, 're' runs on 'm', creating patterns | ||
11 | -- on 'mm' | ||
12 | local mm = m | ||
13 | |||
14 | -- pattern's metatable | ||
15 | local mt = getmetatable(mm.P(0)) | ||
16 | |||
17 | |||
18 | |||
19 | -- No more global accesses after this point | ||
20 | local version = _VERSION | ||
21 | if version == "Lua 5.2" then _ENV = nil end | ||
22 | |||
23 | |||
24 | local any = m.P(1) | ||
25 | |||
26 | |||
27 | -- Pre-defined names | ||
28 | local Predef = { nl = m.P"\n" } | ||
29 | local tlabels = {} | ||
30 | |||
31 | |||
32 | local mem | ||
33 | local fmem | ||
34 | local gmem | ||
35 | |||
36 | |||
37 | local function updatelocale () | ||
38 | mm.locale(Predef) | ||
39 | Predef.a = Predef.alpha | ||
40 | Predef.c = Predef.cntrl | ||
41 | Predef.d = Predef.digit | ||
42 | Predef.g = Predef.graph | ||
43 | Predef.l = Predef.lower | ||
44 | Predef.p = Predef.punct | ||
45 | Predef.s = Predef.space | ||
46 | Predef.u = Predef.upper | ||
47 | Predef.w = Predef.alnum | ||
48 | Predef.x = Predef.xdigit | ||
49 | Predef.A = any - Predef.a | ||
50 | Predef.C = any - Predef.c | ||
51 | Predef.D = any - Predef.d | ||
52 | Predef.G = any - Predef.g | ||
53 | Predef.L = any - Predef.l | ||
54 | Predef.P = any - Predef.p | ||
55 | Predef.S = any - Predef.s | ||
56 | Predef.U = any - Predef.u | ||
57 | Predef.W = any - Predef.w | ||
58 | Predef.X = any - Predef.x | ||
59 | mem = {} -- restart memoization | ||
60 | fmem = {} | ||
61 | gmem = {} | ||
62 | local mt = {__mode = "v"} | ||
63 | setmetatable(mem, mt) | ||
64 | setmetatable(fmem, mt) | ||
65 | setmetatable(gmem, mt) | ||
66 | end | ||
67 | |||
68 | |||
69 | updatelocale() | ||
70 | |||
71 | |||
72 | |||
73 | local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end) | ||
74 | |||
75 | |||
76 | local function getdef (id, defs) | ||
77 | local c = defs and defs[id] | ||
78 | if not c then error("undefined name: " .. id) end | ||
79 | return c | ||
80 | end | ||
81 | |||
82 | |||
83 | local function patt_error (s, i) | ||
84 | local msg = (#s < i + 20) and s:sub(i) | ||
85 | or s:sub(i,i+20) .. "..." | ||
86 | msg = ("pattern error near '%s'"):format(msg) | ||
87 | error(msg, 2) | ||
88 | end | ||
89 | |||
90 | local function mult (p, n) | ||
91 | local np = mm.P(true) | ||
92 | while n >= 1 do | ||
93 | if n%2 >= 1 then np = np * p end | ||
94 | p = p * p | ||
95 | n = n/2 | ||
96 | end | ||
97 | return np | ||
98 | end | ||
99 | |||
100 | local function equalcap (s, i, c) | ||
101 | if type(c) ~= "string" then return nil end | ||
102 | local e = #c + i | ||
103 | if s:sub(i, e - 1) == c then return e else return nil end | ||
104 | end | ||
105 | |||
106 | |||
107 | local S = (Predef.space + "--" * (any - Predef.nl)^0)^0 | ||
108 | |||
109 | local name = m.R("AZ", "az", "__") * m.R("AZ", "az", "__", "09")^0 | ||
110 | |||
111 | local arrow = S * "<-" | ||
112 | |||
113 | local seq_follow = m.P"/" + ")" + "}" + ":}" + "~}" + "|}" + (name * arrow) + -1 | ||
114 | |||
115 | name = m.C(name) | ||
116 | |||
117 | |||
118 | -- a defined name only have meaning in a given environment | ||
119 | local Def = name * m.Carg(1) | ||
120 | |||
121 | local num = m.C(m.R"09"^1) * S / tonumber | ||
122 | |||
123 | local String = "'" * m.C((any - "'")^0) * "'" + | ||
124 | '"' * m.C((any - '"')^0) * '"' | ||
125 | |||
126 | |||
127 | local defined = "%" * Def / function (c,Defs) | ||
128 | local cat = Defs and Defs[c] or Predef[c] | ||
129 | if not cat then error ("name '" .. c .. "' undefined") end | ||
130 | return cat | ||
131 | end | ||
132 | |||
133 | local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R | ||
134 | |||
135 | local item = defined + Range + m.C(any) | ||
136 | |||
137 | local Class = | ||
138 | "[" | ||
139 | * (m.C(m.P"^"^-1)) -- optional complement symbol | ||
140 | * m.Cf(item * (item - "]")^0, mt.__add) / | ||
141 | function (c, p) return c == "^" and any - p or p end | ||
142 | * "]" | ||
143 | |||
144 | local function adddef (t, k, exp) | ||
145 | if t[k] then | ||
146 | error("'"..k.."' already defined as a rule") | ||
147 | else | ||
148 | t[k] = exp | ||
149 | end | ||
150 | return t | ||
151 | end | ||
152 | |||
153 | local function firstdef (n, r) return adddef({n}, n, r) end | ||
154 | |||
155 | |||
156 | local function NT (n, b) | ||
157 | if not b then | ||
158 | error("rule '"..n.."' used outside a grammar") | ||
159 | else return mm.V(n) | ||
160 | end | ||
161 | end | ||
162 | |||
163 | local function labchoice (...) | ||
164 | local t = { ... } | ||
165 | local n = #t | ||
166 | local p = t[1] | ||
167 | local i = 2 | ||
168 | while i + 1 <= n do | ||
169 | p = mm.Lc(p, t[i+1], unpack(t[i])) | ||
170 | i = i + 2 | ||
171 | end | ||
172 | |||
173 | return p | ||
174 | end | ||
175 | |||
176 | |||
177 | local exp = m.P{ "Exp", | ||
178 | Exp = S * ( m.V"Grammar" | ||
179 | + (m.V"Seq") * ("/" * m.V"Labels" * S * m.V"Seq")^1 / labchoice | ||
180 | + m.Cf(m.V"Seq" * ("/" * S * m.V"Seq")^0, mt.__add) ); | ||
181 | Labels = m.Ct(m.P"{" * S * m.V"Label" * (S * "," * S * m.V"Label")^0 * S * "}"); | ||
182 | Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix"^0 , mt.__mul) | ||
183 | * (#seq_follow + patt_error); | ||
184 | Prefix = "&" * S * m.V"Prefix" / mt.__len | ||
185 | + "!" * S * m.V"Prefix" / mt.__unm | ||
186 | + m.V"Suffix"; | ||
187 | Suffix = m.Cf(m.V"Primary" * S * | ||
188 | ( ( m.P"+" * m.Cc(1, mt.__pow) | ||
189 | + m.P"*" * m.Cc(0, mt.__pow) | ||
190 | + m.P"?" * m.Cc(-1, mt.__pow) | ||
191 | + "^" * ( m.Cg(num * m.Cc(mult)) | ||
192 | + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow)) | ||
193 | ) | ||
194 | + "->" * S * ( m.Cg((String + num) * m.Cc(mt.__div)) | ||
195 | + m.P"{}" * m.Cc(nil, m.Ct) | ||
196 | + m.Cg(Def / getdef * m.Cc(mt.__div)) | ||
197 | ) | ||
198 | + "=>" * S * m.Cg(Def / getdef * m.Cc(m.Cmt)) | ||
199 | ) * S | ||
200 | )^0, function (a,b,f) return f(a,b) end ); | ||
201 | Primary = "(" * m.V"Exp" * ")" | ||
202 | + String / mm.P | ||
203 | + Class | ||
204 | + defined | ||
205 | + "%{" * S * m.V"Label" * (S * "," * S * m.V"Label")^0 * S * "}" / mm.T | ||
206 | + "{:" * (name * ":" + m.Cc(nil)) * m.V"Exp" * ":}" / | ||
207 | function (n, p) return mm.Cg(p, n) end | ||
208 | + "=" * name / function (n) return mm.Cmt(mm.Cb(n), equalcap) end | ||
209 | + m.P"{}" / mm.Cp | ||
210 | + "{~" * m.V"Exp" * "~}" / mm.Cs | ||
211 | + "{|" * m.V"Exp" * "|}" / mm.Ct | ||
212 | + "{" * m.V"Exp" * "}" / mm.C | ||
213 | + m.P"." * m.Cc(any) | ||
214 | + (name * -arrow + "<" * name * ">") * m.Cb("G") / NT; | ||
215 | Label = num + name / function (f) return tlabels[f] end; | ||
216 | Definition = name * arrow * m.V"Exp"; | ||
217 | Grammar = m.Cg(m.Cc(true), "G") * | ||
218 | m.Cf(m.V"Definition" / firstdef * m.Cg(m.V"Definition")^0, | ||
219 | adddef) / mm.P | ||
220 | } | ||
221 | |||
222 | local pattern = S * m.Cg(m.Cc(false), "G") * exp / mm.P * (-any + patt_error) | ||
223 | |||
224 | |||
225 | local function compile (p, defs) | ||
226 | if mm.type(p) == "pattern" then return p end -- already compiled | ||
227 | local cp = pattern:match(p, 1, defs) | ||
228 | if not cp then error("incorrect pattern", 3) end | ||
229 | return cp | ||
230 | end | ||
231 | |||
232 | local function match (s, p, i) | ||
233 | local cp = mem[p] | ||
234 | if not cp then | ||
235 | cp = compile(p) | ||
236 | mem[p] = cp | ||
237 | end | ||
238 | return cp:match(s, i or 1) | ||
239 | end | ||
240 | |||
241 | local function find (s, p, i) | ||
242 | local cp = fmem[p] | ||
243 | if not cp then | ||
244 | cp = compile(p) / 0 | ||
245 | cp = mm.P{ mm.Cp() * cp * mm.Cp() + 1 * mm.V(1) } | ||
246 | fmem[p] = cp | ||
247 | end | ||
248 | local i, e = cp:match(s, i or 1) | ||
249 | if i then return i, e - 1 | ||
250 | else return i | ||
251 | end | ||
252 | end | ||
253 | |||
254 | local function gsub (s, p, rep) | ||
255 | local g = gmem[p] or {} -- ensure gmem[p] is not collected while here | ||
256 | gmem[p] = g | ||
257 | local cp = g[rep] | ||
258 | if not cp then | ||
259 | cp = compile(p) | ||
260 | cp = mm.Cs((cp / rep + 1)^0) | ||
261 | g[rep] = cp | ||
262 | end | ||
263 | return cp:match(s) | ||
264 | end | ||
265 | |||
266 | local function setlabels (t) | ||
267 | tlabels = t | ||
268 | end | ||
269 | |||
270 | -- exported names | ||
271 | local re = { | ||
272 | compile = compile, | ||
273 | match = match, | ||
274 | find = find, | ||
275 | gsub = gsub, | ||
276 | updatelocale = updatelocale, | ||
277 | setlabels = setlabels | ||
278 | } | ||
279 | |||
280 | if version == "Lua 5.1" then _G.re = re end | ||
281 | |||
282 | return re | ||