papagaio 0.7.1 → 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/papagaio.js DELETED
@@ -1,249 +0,0 @@
1
- // papagaio - https://github.com/jardimdanificado/papagaio
2
- function parsePattern(p, pat) {
3
- const t = [], S = p.symbols.sigil, O = p.symbols.open, C = p.symbols.close;
4
- let i = 0;
5
- while (i < pat.length) {
6
- if (pat.startsWith(S + p.symbols.regex, i)) {
7
- let j = i + S.length + p.symbols.regex.length;
8
- while (j < pat.length && /\s/.test(pat[j])) j++;
9
- let v = '';
10
- while (j < pat.length && /[A-Za-z0-9_]/.test(pat[j])) v += pat[j++];
11
- if (v) {
12
- while (j < pat.length && /\s/.test(pat[j])) j++;
13
- if (pat[j] === O) {
14
- const [rx, e] = extractBlock(p, pat, j);
15
- t.push({ type: 'regex', varName: v, regex: rx.trim() });
16
- i = e; continue;
17
- }
18
- }
19
- }
20
- if (pat[i] === S) {
21
- let j = i + S.length;
22
- const isDouble = pat[j] === S;
23
- if (isDouble) j++;
24
- if (pat[j] === O) {
25
- const [od, e1] = extractBlock(p, pat, j);
26
- if (pat[e1] === O) {
27
- const [cd, e2] = extractBlock(p, pat, e1);
28
- let v = '', k = e2;
29
- while (k < pat.length && /[A-Za-z0-9_]/.test(pat[k])) v += pat[k++];
30
- if (v) {
31
- t.push({ type: isDouble ? 'blockseq' : 'block', varName: v, open: unescapeDelim(od.trim()) || O, close: unescapeDelim(cd.trim()) || C });
32
- i = k; continue;
33
- }
34
- }
35
- }
36
- j = i + S.length;
37
- let v = '';
38
- while (j < pat.length && /[A-Za-z0-9_]/.test(pat[j])) v += pat[j++];
39
- if (v) {
40
- const optional = pat[j] === '?';
41
- if (optional) j++;
42
- t.push({ type: 'var', varName: v, optional });
43
- i = j; continue;
44
- }
45
- t.push({ type: 'lit', value: S }); i += S.length; continue;
46
- }
47
- if (/\s/.test(pat[i])) {
48
- while (i < pat.length && /\s/.test(pat[i])) i++;
49
- t.push({ type: 'ws' }); continue;
50
- }
51
- let lit = '';
52
- while (i < pat.length && pat[i] !== S && !/\s/.test(pat[i])) lit += pat[i++];
53
- if (lit) t.push({ type: 'lit', value: lit });
54
- }
55
- return t;
56
- }
57
-
58
- function matchPattern(p, src, tok, pos = 0) {
59
- let cap = {};
60
- for (let ti = 0; ti < tok.length; ti++) {
61
- const t = tok[ti];
62
- if (t.type === 'ws') { while (pos < src.length && /\s/.test(src[pos])) pos++; continue; }
63
- if (t.type === 'lit') { if (!src.startsWith(t.value, pos)) return null; pos += t.value.length; continue; }
64
- if (t.type === 'regex') {
65
- try {
66
- const rx = new RegExp(t.regex), m = src.slice(pos).match(rx);
67
- if (!m || m.index !== 0) return null;
68
- cap[p.symbols.sigil + t.varName] = m[0];
69
- pos += m[0].length;
70
- } catch (e) { return null; }
71
- continue;
72
- }
73
- if (t.type === 'var') {
74
- while (pos < src.length && /\s/.test(src[pos])) pos++;
75
- const nx = findNext(tok, ti);
76
- let v = '';
77
- if (nx && (nx.type === 'block' || nx.type === 'lit')) {
78
- const stop = nx.type === 'block' ? nx.open : nx.value;
79
- while (pos < src.length && !src.startsWith(stop, pos) && src[pos] !== '\n') v += src[pos++];
80
- v = v.trimEnd();
81
- } else {
82
- while (pos < src.length && !/\s/.test(src[pos])) v += src[pos++];
83
- }
84
- if (!v && !t.optional) return null;
85
- cap[p.symbols.sigil + t.varName] = v;
86
- continue;
87
- }
88
- if (t.type === 'blockseq') {
89
- let blocks = [];
90
- while (pos < src.length && src.startsWith(t.open, pos)) {
91
- const [c, e] = extractBlock(p, src, pos, t.open, t.close);
92
- blocks.push(c);
93
- pos = e;
94
- while (pos < src.length && /\s/.test(src[pos])) pos++;
95
- }
96
- if (!blocks.length) return null;
97
- cap[p.symbols.sigil + t.varName] = blocks.join(' ');
98
- continue;
99
- }
100
- if (t.type === 'block') {
101
- if (!src.startsWith(t.open, pos)) return null;
102
- const [c, e] = extractBlock(p, src, pos, t.open, t.close);
103
- cap[p.symbols.sigil + t.varName] = c; pos = e; continue;
104
- }
105
- }
106
- return { captures: cap, endPos: pos };
107
- }
108
-
109
- function findNext(t, i) { for (let k = i + 1; k < t.length; k++) if (t[k].type !== 'ws') return t[k]; return null; }
110
-
111
- function extractBlock(p, src, i, od = p.symbols.open, cd = p.symbols.close) {
112
- if (od.length > 1 || cd.length > 1) {
113
- if (src.substring(i, i + od.length) === od) {
114
- i += od.length; const s = i; let d = 0;
115
- while (i < src.length) {
116
- if (src.substring(i, i + od.length) === od) { d++; i += od.length; }
117
- else if (src.substring(i, i + cd.length) === cd) {
118
- if (!d) return [src.substring(s, i), i + cd.length];
119
- d--; i += cd.length;
120
- } else i++;
121
- }
122
- return [src.substring(s), src.length];
123
- }
124
- }
125
- if (src[i] === od) {
126
- i++; const s = i;
127
- if (od === cd) { while (i < src.length && src[i] !== cd) i++; return [src.substring(s, i), i + 1]; }
128
- let d = 1;
129
- while (i < src.length && d > 0) { if (src[i] === od) d++; else if (src[i] === cd) d--; if (d > 0) i++; }
130
- return [src.substring(s, i), i + 1];
131
- }
132
- return ['', i];
133
- }
134
-
135
- function extractNested(p, txt) {
136
- const loc = [], S = p.symbols.sigil, O = p.symbols.open;
137
- let out = txt;
138
- const rx = new RegExp(`${esc(S)}${esc(p.symbols.pattern)}\\s*${esc(O)}`, "g");
139
- while (1) {
140
- rx.lastIndex = 0; const m = rx.exec(out); if (!m) break;
141
- const s = m.index, o = m.index + m[0].length - O.length;
142
- const [mp, em] = extractBlock(p, out, o); let k = em;
143
- while (k < out.length && /\s/.test(out[k])) k++;
144
- if (k < out.length && out.substring(k, k + O.length) === O) {
145
- const [rp, er] = extractBlock(p, out, k);
146
- loc.push({ m: mp.trim(), r: rp.trim() });
147
- out = out.slice(0, s) + out.slice(er); continue;
148
- }
149
- out = out.slice(0, s) + out.slice(em);
150
- }
151
- return [loc, out];
152
- }
153
-
154
- function extractEvals(p, txt) {
155
- const ev = [], S = p.symbols.sigil, O = p.symbols.open;
156
- let i = 0, out = txt, off = 0;
157
- while (i < txt.length) {
158
- if (txt.substring(i, i + S.length) === S && txt.substring(i + S.length).startsWith(p.symbols.eval)) {
159
- let j = i + S.length + p.symbols.eval.length;
160
- while (j < txt.length && /\s/.test(txt[j])) j++;
161
- if (j < txt.length && txt.substring(j, j + O.length) === O) {
162
- const sp = i, bp = j, [c, ep] = extractBlock(p, txt, bp);
163
- ev.push({ code: c, sp: sp - off, ep: ep - off });
164
- const ph = `__E${ev.length - 1}__`;
165
- out = out.substring(0, sp - off) + ph + out.substring(ep - off);
166
- off += (ep - sp) - ph.length; i = ep; continue;
167
- }
168
- }
169
- i++;
170
- }
171
- return [ev, out];
172
- }
173
-
174
- function applyEvals(p, txt, ev) {
175
- let r = txt;
176
- for (let i = ev.length - 1; i >= 0; i--) {
177
- const ph = `__E${i}__`;
178
- try {
179
- r = r.replace(ph, String(
180
- Function("ctx", `"use strict";${ev[i].code}`).call(p, {})
181
- ));
182
- }
183
- catch (e) { r = r.replace(ph, "error: " + e.message); }
184
- }
185
- return r;
186
- }
187
-
188
- function applyPats(p, src, pats) {
189
- for (const pat of pats) {
190
- const tok = parsePattern(p, pat.m);
191
- let n = '', pos = 0, ok = false;
192
- while (pos < src.length) {
193
- const m = matchPattern(p, src, tok, pos);
194
- if (m) {
195
- ok = true;
196
- let r = pat.r;
197
- const [loc, cln] = extractNested(p, r);
198
- r = cln;
199
- Object.keys(m.captures).forEach(k => {
200
- r = r.replace(new RegExp(esc(k) + '(?![A-Za-z0-9_])', 'g'), m.captures[k]);
201
- });
202
- if (loc.length) r = applyPats(p, r, loc);
203
- p.match = src.slice(pos, m.endPos);
204
- const [ev, ct] = extractEvals(p, r);
205
- if (ev.length) r = applyEvals(p, ct, ev);
206
- n += r; pos = m.endPos;
207
- } else { n += src[pos]; pos++; }
208
- }
209
- if (ok) src = n;
210
- }
211
- return src;
212
- }
213
-
214
- function esc(s) { return s.replace(/[.*+?^${}()|[\]\\""']/g, '\\$&'); }
215
- function unescapeDelim(s) {
216
- let r = '';
217
- for (let i = 0; i < s.length; i++) {
218
- if (s[i] === '\\' && i + 1 < s.length && (s[i+1] === '"' || s[i+1] === "'" || s[i+1] === '\\')) { r += s[i+1]; i++; }
219
- else r += s[i];
220
- }
221
- return r;
222
- }
223
-
224
- export class Papagaio {
225
- constructor(sigil = '$', open = '{', close = '}', pattern = 'pattern', evalKw = 'eval', blockKw = 'recursive', regexKw = 'regex', blockseqKw = 'sequential') {
226
- this.symbols = { pattern, open, close, sigil, eval: evalKw, block: blockKw, regex: regexKw, blockseq: blockseqKw };
227
- this.content = "";
228
- this.match = "";
229
- }
230
- process(input) {
231
- const [loc, cln] = extractNested(this, input);
232
- const [evals, ph] = extractEvals(this, cln);
233
- let proc = applyEvals(this, ph, evals);
234
- if (loc.length === 0) {
235
- this.content = proc;
236
- return proc;
237
- }
238
- let src = proc, last = null;
239
- while (src !== last) {
240
- last = src;
241
- src = applyPats(this, src, loc);
242
- const [nested] = extractNested(this, src);
243
- if (nested.length === 0) break;
244
- }
245
- this.content = src;
246
- if (typeof this.exit == "function") this.exit();
247
- return this.content;
248
- }
249
- }