papagaio 0.7.1 → 0.7.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "papagaio",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "easy yet powerful preprocessor",
5
5
  "main": "src/papagaio.js",
6
6
  "type": "module",
package/src/louro.js ADDED
@@ -0,0 +1,235 @@
1
+ // louro - https://github.com/jardimdanificado/papagaio
2
+ function parsePattern(symbols, pat) {
3
+ const t = [], S = symbols.sigil, O = symbols.open, C = symbols.close;
4
+ let i = 0;
5
+ while (i < pat.length) {
6
+ if (pat[i] === S) {
7
+ let j = i + S.length;
8
+ const isDouble = pat[j] === S;
9
+ if (isDouble) j++;
10
+ if (pat[j] === O) {
11
+ const [od, e1] = extractBlock(symbols, pat, j);
12
+ if (pat[e1] === O) {
13
+ const [cd, e2] = extractBlock(symbols, pat, e1);
14
+ let v = '', k = e2;
15
+ while (k < pat.length && /[A-Za-z0-9_]/.test(pat[k])) v += pat[k++];
16
+ if (v) {
17
+ let optional = pat[k] === '?';
18
+ if (optional) k++;
19
+
20
+ t.push({
21
+ type: isDouble ? 'blockseq' : 'block',
22
+ varName: v,
23
+ open: unescapeDelim(od.trim()) || O,
24
+ close: unescapeDelim(cd.trim()) || C,
25
+ optional
26
+ });
27
+ i = k; continue;
28
+ }
29
+ }
30
+ }
31
+ j = i + S.length;
32
+ let v = '';
33
+ while (j < pat.length && /[A-Za-z0-9_]/.test(pat[j])) v += pat[j++];
34
+ if (v) {
35
+ const optional = pat[j] === '?';
36
+ if (optional) j++;
37
+ t.push({ type: 'var', varName: v, optional });
38
+ i = j; continue;
39
+ }
40
+ t.push({ type: 'lit', value: S }); i += S.length; continue;
41
+ }
42
+ if (/\s/.test(pat[i])) {
43
+ while (i < pat.length && /\s/.test(pat[i])) i++;
44
+ t.push({ type: 'ws' }); continue;
45
+ }
46
+ let lit = '';
47
+ while (i < pat.length && pat[i] !== S && !/\s/.test(pat[i])) lit += pat[i++];
48
+ if (lit) t.push({ type: 'lit', value: lit });
49
+ }
50
+ return t;
51
+ }
52
+
53
+ function matchPattern(symbols, src, tok, pos = 0) {
54
+ let cap = {};
55
+ const startPos = pos;
56
+
57
+ for (let ti = 0; ti < tok.length; ti++) {
58
+ const t = tok[ti];
59
+ if (t.type === 'ws') { while (pos < src.length && /\s/.test(src[pos])) pos++; continue; }
60
+ if (t.type === 'lit') { if (!src.startsWith(t.value, pos)) return null; pos += t.value.length; continue; }
61
+ if (t.type === 'var') {
62
+ while (pos < src.length && /\s/.test(src[pos])) pos++;
63
+ const nx = findNext(tok, ti);
64
+ let v = '';
65
+ if (nx && (nx.type === 'block' || nx.type === 'lit')) {
66
+ const stop = nx.type === 'block' ? nx.open : nx.value;
67
+ while (pos < src.length && !src.startsWith(stop, pos) && src[pos] !== '\n') v += src[pos++];
68
+ v = v.trimEnd();
69
+ } else {
70
+ while (pos < src.length && !/\s/.test(src[pos])) v += src[pos++];
71
+ }
72
+ if (!v && !t.optional) return null;
73
+ cap[t.varName] = v;
74
+ continue;
75
+ }
76
+ if (t.type === 'blockseq') {
77
+ let blocks = [];
78
+ while (pos < src.length && src.startsWith(t.open, pos)) {
79
+ const [c, e] = extractBlock(symbols, src, pos, t.open, t.close);
80
+ blocks.push(c);
81
+ pos = e;
82
+ while (pos < src.length && /\s/.test(src[pos])) pos++;
83
+ }
84
+ if (!blocks.length && !t.optional) return null;
85
+ cap[t.varName] = blocks;
86
+ continue;
87
+ }
88
+ if (t.type === 'block') {
89
+ if (!src.startsWith(t.open, pos)) {
90
+ if (t.optional) {
91
+ cap[t.varName] = '';
92
+ continue;
93
+ }
94
+ return null;
95
+ }
96
+
97
+ const [c, e] = extractBlock(symbols, src, pos, t.open, t.close);
98
+ cap[t.varName] = c; pos = e; continue;
99
+ }
100
+ }
101
+ return { captures: cap, startPos, endPos: pos, matched: src.slice(startPos, pos) };
102
+ }
103
+
104
+ function findNext(t, i) {
105
+ for (let k = i + 1; k < t.length; k++)
106
+ if (t[k].type !== 'ws') return t[k];
107
+ return null;
108
+ }
109
+
110
+ function extractBlock(symbols, src, i, od = symbols.open, cd = symbols.close) {
111
+ if (od.length > 1 || cd.length > 1) {
112
+ if (src.substring(i, i + od.length) === od) {
113
+ i += od.length; const s = i; let d = 0;
114
+ while (i < src.length) {
115
+ if (src.substring(i, i + od.length) === od) { d++; i += od.length; }
116
+ else if (src.substring(i, i + cd.length) === cd) {
117
+ if (!d) return [src.substring(s, i), i + cd.length];
118
+ d--; i += cd.length;
119
+ } else i++;
120
+ }
121
+ return [src.substring(s), src.length];
122
+ }
123
+ }
124
+ if (src[i] === od) {
125
+ i++; const s = i;
126
+ if (od === cd) { while (i < src.length && src[i] !== cd) i++; return [src.substring(s, i), i + 1]; }
127
+ let d = 1;
128
+ while (i < src.length && d > 0) { if (src[i] === od) d++; else if (src[i] === cd) d--; if (d > 0) i++; }
129
+ return [src.substring(s, i), i + 1];
130
+ }
131
+ return ['', i];
132
+ }
133
+
134
+ function esc(s) { return s.replace(/[.*+?^${}()|[\]\\""']/g, '\\$&'); }
135
+ function unescapeDelim(s) {
136
+ let r = '';
137
+ for (let i = 0; i < s.length; i++) {
138
+ if (s[i] === '\\' && i + 1 < s.length && (s[i + 1] === '"' || s[i + 1] === "'" || s[i + 1] === '\\')) { r += s[i + 1]; i++; }
139
+ else r += s[i];
140
+ }
141
+ return r;
142
+ }
143
+
144
+ export function capture(content, pattern, symbols = { sigil: '$', open: '{', close: '}' }) {
145
+ const tokens = parsePattern(symbols, pattern);
146
+ const matches = [];
147
+
148
+ let pos = 0;
149
+ while (pos < content.length) {
150
+ const m = matchPattern(symbols, content, tokens, pos);
151
+ if (m) {
152
+ matches.push({
153
+ matched: m.matched,
154
+ captures: m.captures,
155
+ start: m.startPos,
156
+ end: m.endPos,
157
+ index: matches.length
158
+ });
159
+ pos = m.endPos;
160
+ } else {
161
+ pos++;
162
+ }
163
+ }
164
+
165
+ return {
166
+ content,
167
+ pattern,
168
+ matches,
169
+ count: matches.length,
170
+
171
+ replace(replacement) {
172
+ if (matches.length === 0) return { content, matches: [], count: 0 };
173
+
174
+ let result = '';
175
+ let lastPos = 0;
176
+
177
+ for (const match of matches) {
178
+ result += content.slice(lastPos, match.start);
179
+
180
+ let rep = typeof replacement === 'function'
181
+ ? replacement(match)
182
+ : replacement;
183
+
184
+ for (const [key, value] of Object.entries(match.captures)) {
185
+ const varPattern = new RegExp(esc(symbols.sigil + key) + '(?![A-Za-z0-9_])', 'g');
186
+ rep = rep.replace(varPattern, value);
187
+ }
188
+
189
+ result += rep;
190
+ lastPos = match.end;
191
+ }
192
+
193
+ result += content.slice(lastPos);
194
+
195
+ return result;
196
+ },
197
+
198
+ filter(predicate) {
199
+ const filtered = matches.filter(predicate);
200
+ return {
201
+ content,
202
+ pattern,
203
+ matches: filtered,
204
+ count: filtered.length,
205
+ replace: this.replace.bind({ ...this, matches: filtered }),
206
+ filter: this.filter,
207
+ only: this.only
208
+ };
209
+ },
210
+
211
+ only(n) {
212
+ const len = this.matches.length;
213
+ let idx = n >= 0 ? n : len + n;
214
+ if (idx < 0 || idx >= len) {
215
+ return {
216
+ ...this,
217
+ matches: []
218
+ };
219
+ }
220
+ return {
221
+ ...this,
222
+ matches: [this.matches[idx]]
223
+ };
224
+ }
225
+ };
226
+ }
227
+
228
+ Object.defineProperty(String.prototype, "capture", {
229
+ value: function (pattern, symbols) {
230
+ return capture(this.toString(), pattern, symbols);
231
+ },
232
+ writable: true,
233
+ configurable: true,
234
+ enumerable: false
235
+ });
package/src/papagaio.js CHANGED
@@ -1,112 +1,5 @@
1
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; }
2
+ import { capture } from './louro.js';
110
3
 
111
4
  function extractBlock(p, src, i, od = p.symbols.open, cd = p.symbols.close) {
112
5
  if (od.length > 1 || cd.length > 1) {
@@ -185,41 +78,101 @@ function applyEvals(p, txt, ev) {
185
78
  return r;
186
79
  }
187
80
 
81
+ function processRegexPatterns(p, src, pattern) {
82
+ // Processa padrões regex que o louro não suporta nativamente
83
+ const S = p.symbols.sigil, O = p.symbols.open;
84
+ const regexMatch = pattern.match(new RegExp(`${esc(S)}${esc(p.symbols.regex)}\\s+([A-Za-z0-9_]+)\\s*${esc(O)}([^${esc(p.symbols.close)}]*)${esc(p.symbols.close)}`));
85
+
86
+ if (!regexMatch) return null;
87
+
88
+ const varName = regexMatch[1];
89
+ const regexStr = regexMatch[2].trim();
90
+
91
+ try {
92
+ const rx = new RegExp(regexStr);
93
+ const matches = [];
94
+ let pos = 0;
95
+
96
+ while (pos < src.length) {
97
+ const m = src.slice(pos).match(rx);
98
+ if (m && m.index === 0) {
99
+ matches.push({
100
+ matched: m[0],
101
+ captures: { [varName]: m[0] },
102
+ start: pos,
103
+ end: pos + m[0].length
104
+ });
105
+ pos += m[0].length;
106
+ } else {
107
+ pos++;
108
+ }
109
+ }
110
+
111
+ return matches;
112
+ } catch (e) {
113
+ return null;
114
+ }
115
+ }
116
+
188
117
  function applyPats(p, src, pats) {
189
118
  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;
119
+ // Verifica se é um padrão regex
120
+ const regexMatches = processRegexPatterns(p, src, pat.m);
121
+
122
+ if (regexMatches) {
123
+ // Processa como padrão regex
124
+ let n = '', lastPos = 0;
125
+
126
+ for (const match of regexMatches) {
127
+ n += src.slice(lastPos, match.start);
128
+
196
129
  let r = pat.r;
197
130
  const [loc, cln] = extractNested(p, r);
198
131
  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]);
132
+
133
+ Object.keys(match.captures).forEach(k => {
134
+ r = r.replace(new RegExp(esc(p.symbols.sigil + k) + '(?![A-Za-z0-9_])', 'g'), match.captures[k]);
201
135
  });
136
+
202
137
  if (loc.length) r = applyPats(p, r, loc);
203
- p.match = src.slice(pos, m.endPos);
138
+ p.match = match.matched;
204
139
  const [ev, ct] = extractEvals(p, r);
205
140
  if (ev.length) r = applyEvals(p, ct, ev);
206
- n += r; pos = m.endPos;
207
- } else { n += src[pos]; pos++; }
141
+
142
+ n += r;
143
+ lastPos = match.end;
144
+ }
145
+
146
+ n += src.slice(lastPos);
147
+ if (regexMatches.length > 0) src = n;
148
+ } else {
149
+ // Usa louro para padrões normais
150
+ const result = capture(src, pat.m, p.symbols);
151
+
152
+ if (result.count > 0) {
153
+ src = result.replace((match) => {
154
+ let r = pat.r;
155
+ const [loc, cln] = extractNested(p, r);
156
+ r = cln;
157
+
158
+ Object.keys(match.captures).forEach(k => {
159
+ r = r.replace(new RegExp(esc(p.symbols.sigil + k) + '(?![A-Za-z0-9_])', 'g'), match.captures[k]);
160
+ });
161
+
162
+ if (loc.length) r = applyPats(p, r, loc);
163
+ p.match = match.matched;
164
+ const [ev, ct] = extractEvals(p, r);
165
+ if (ev.length) r = applyEvals(p, ct, ev);
166
+
167
+ return r;
168
+ });
169
+ }
208
170
  }
209
- if (ok) src = n;
210
171
  }
211
172
  return src;
212
173
  }
213
174
 
214
175
  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
176
 
224
177
  export class Papagaio {
225
178
  constructor(sigil = '$', open = '{', close = '}', pattern = 'pattern', evalKw = 'eval', blockKw = 'recursive', regexKw = 'regex', blockseqKw = 'sequential') {
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>papagaio test</title>
7
- </head>
8
- <script src="../src/papagaio-bootstrap.mjs" type="module"></script>
9
- <script type="papagaio">
10
- $pattern {abc} {$eval{console.log(this)} aaaaaaaaaaaaaaaaaaaaaaaaaaaa}
11
- abc
12
- </script>
13
- <body>
14
- </body>
15
- </html>
@@ -1,70 +0,0 @@
1
- // generic ts-like to wasm compiler
2
-
3
- // util patterns
4
- $pattern {// $comment $regex newline{[^\n]*}} {}
5
- $pattern {$regex spaces{\s\s}}{ }
6
-
7
- $eval{
8
- papagaio.exit = function()
9
- {
10
- papagaio.content = "(module\n" + papagaio.content + "\n)";
11
- papagaio.exit = null;
12
- };
13
- return ""
14
- }
15
-
16
- $pattern {export function $name ${(}{)}params:$rets ${}{}content} {
17
- $pattern {parametrize}
18
- {
19
- $eval {
20
- let str = "$params".replace("(", "").replace(")", "");
21
- let params = str.split(",").map(p => p.trim()).filter(p => p);
22
- let new_stuff = "";
23
- for (const param of params) {
24
- if (!param.includes(":")) continue; // Pula se não tem ':'
25
- const [name, type] = param.split(":");
26
- if (name && type) { // Verifica se ambos existem
27
- new_stuff += ` (param $${name.trim()} ${type.trim()}) `;
28
- }
29
- }
30
- return new_stuff;
31
- }
32
- }
33
-
34
- (func (export "$name") parametrize (result $rets)
35
- $content
36
- )
37
- }
38
-
39
- $pattern {function $name ${}{}params{(}{)}:$rets ${}{}content} {
40
- $pattern {parametrize}
41
- {
42
- $eval {
43
- let str = "$params".replace("(", "").replace(")", "");
44
- let params = str.split(",").map(p => p.trim()).filter(p => p);
45
- let new_stuff = "";
46
- for (const param of params) {
47
- if (!param.includes(":")) continue; // Pula se não tem ':'
48
- const [name, type] = param.split(":");
49
- if (name && type) { // Verifica se ambos existem
50
- new_stuff += ` (param $${name.trim()} ${type.trim()}) `;
51
- }
52
- }
53
- return new_stuff;
54
- }
55
- }
56
-
57
- (func $$name parametrize (result $rets)
58
- $content
59
- )
60
- }
61
-
62
- function name(a:i32, b:i32):i64 i64
63
- {
64
- contentnans
65
- }
66
-
67
- export function funcao_exportada(a:f32, b:f32, c:f32):i64 i64 i64 i64
68
- {
69
- fução expoortada1
70
- }
@@ -1,23 +0,0 @@
1
- // papagaio-bootstrap.js
2
- // only needed if using <script type="papagaio"> in browser
3
- import { Papagaio } from "./papagaio.js";
4
-
5
- (async () => {
6
- const p = new Papagaio();
7
-
8
- const nodes = [...document.querySelectorAll('script[type="papagaio"]')];
9
-
10
- for (const el of nodes) {
11
- let src = el.textContent;
12
-
13
- if (el.src) {
14
- src = await fetch(el.src).then(r => r.text());
15
- }
16
-
17
- const out = p.process(src);
18
-
19
- const s = document.createElement("div");
20
- s.textContent = out;
21
- window.document.body.appendChild(s);
22
- }
23
- })();