@marrs/sxml 0.3.0
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/LICENCE +21 -0
- package/README.md +13 -0
- package/cli/index.js +32 -0
- package/lib/index.js +3 -0
- package/lib/preprocessors.js +15 -0
- package/package.json +40 -0
- package/src/buffer.js +72 -0
- package/src/index.js +31 -0
- package/src/init.js +5 -0
- package/src/parser.js +1012 -0
- package/src/processors/index.js +186 -0
- package/src/util.js +58 -0
package/src/parser.js
ADDED
|
@@ -0,0 +1,1012 @@
|
|
|
1
|
+
import { Readable } from 'stream';
|
|
2
|
+
import { Buffer_Trait, Sexp_Buffer_Trait } from './buffer.js'
|
|
3
|
+
import { last, last_but, Interface } from './util.js';
|
|
4
|
+
import { pre_html_chars, pre_hex_chars, pre_html_entity, pre_hex_entity, pre_qualified_ns, unqualified_xml } from './processors/index.js';
|
|
5
|
+
|
|
6
|
+
// String catenation by joining an array is a bit faster
|
|
7
|
+
// than using +. Therefore we prefer to build an array
|
|
8
|
+
// of string parts rather than appending to a preexisting
|
|
9
|
+
// string variable.
|
|
10
|
+
|
|
11
|
+
function is_found(idxOrStr, substr) {
|
|
12
|
+
if (void 0 === substr) {
|
|
13
|
+
return idxOrStr > -1;
|
|
14
|
+
}
|
|
15
|
+
return idxOrStr.indexOf(substr) > -1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function identify_operator(token) {
|
|
19
|
+
if (token.length) {
|
|
20
|
+
var firstChar = token.charAt(0);
|
|
21
|
+
if (/\s/.test(firstChar)) {
|
|
22
|
+
return 'none';
|
|
23
|
+
}
|
|
24
|
+
switch(firstChar) {
|
|
25
|
+
case "@": return 'attr';
|
|
26
|
+
case ")": return 'none';
|
|
27
|
+
case "(": return 'bracket';
|
|
28
|
+
case "&": return 'specialchar';
|
|
29
|
+
case "<": return 'specialchar';
|
|
30
|
+
case ">": return 'specialchar';
|
|
31
|
+
default: return 'tag';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return 'none';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const iStackFrame = Interface.create({
|
|
38
|
+
assertions: {
|
|
39
|
+
processor: Interface.isDefined,
|
|
40
|
+
data: Interface.isArray
|
|
41
|
+
},
|
|
42
|
+
defaults: {
|
|
43
|
+
processor: null,
|
|
44
|
+
operator: '',
|
|
45
|
+
ast: [''],
|
|
46
|
+
namespace: null
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
function is_valid_attr_name(name) {
|
|
52
|
+
if (0 === name.length) return false;
|
|
53
|
+
if (is_found(name, '"')) return false;
|
|
54
|
+
if (is_found(name, "'")) return false;
|
|
55
|
+
if (is_found(name, ">")) return false;
|
|
56
|
+
if (is_found(name, "/")) return false;
|
|
57
|
+
if (is_found(name, "=")) return false;
|
|
58
|
+
// Reject control chars
|
|
59
|
+
if (/[\u0000-\u001F\u0020]/.test(name)) return false;
|
|
60
|
+
// Reject nonchars
|
|
61
|
+
if (/[\uFDD0-\uFDEF\uFFFE\uFFFF\u1FFFE\u1FFFF\u2FFFE\u2FFFF\u3FFFE\u3FFFF\u4FFFE\u4FFFF\u5FFFE\u5FFFF\u6FFFE\u6FFFF\u7FFFE\u7FFFF\u8FFFE\u8FFFF\u9FFFE\u9FFFF\uAFFFE\uAFFFF\uBFFFE\uBFFFF\uCFFFE\uCFFFF\uDFFFE\uDFFFF\uEFFFE\uEFFFF\uFFFFE\uFFFFF\u10FFFE\u10FFFF]/.test(name)) return false;
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function is_char_quote_mark(ch) {
|
|
66
|
+
return ['"', "'"].indexOf(ch) > -1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function log_parse_error(data) {
|
|
70
|
+
console.info("TODO: LOG TO STDERR -", data.msg, "- line:", data.lineNumber, "token:", data.token);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function is_within_quote(isQuoting, idxQuote, idxString) {
|
|
74
|
+
if (idxQuote === idxString) {
|
|
75
|
+
throw new Error("Substring and quote char cannot begin at same index");
|
|
76
|
+
}
|
|
77
|
+
if (isQuoting) {
|
|
78
|
+
if (is_found(idxQuote)) {
|
|
79
|
+
return idxQuote > idxString;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (is_found(idxQuote)) {
|
|
85
|
+
return idxQuote < idxString;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function is_quoting_by(idx, idxQuote, isAlreadyQuoting) {
|
|
92
|
+
if (is_found(idxQuote) && idxQuote <= idx) {
|
|
93
|
+
return !isAlreadyQuoting;
|
|
94
|
+
}
|
|
95
|
+
return isAlreadyQuoting;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function index_of_closing_quote(str, quoteChar) {
|
|
99
|
+
var maybeClosingQuote = str.indexOf(quoteChar);
|
|
100
|
+
if (maybeClosingQuote < 0) return -1;
|
|
101
|
+
if (0 === maybeClosingQuote) return 0;
|
|
102
|
+
if ('\\' === str.charAt(maybeClosingQuote -1)) {
|
|
103
|
+
// XXX Could stack-overflow in theory
|
|
104
|
+
return maybeClosingQuote + 1 + index_of_closing_quote(str.substring(maybeClosingQuote +1), quoteChar);
|
|
105
|
+
}
|
|
106
|
+
return maybeClosingQuote;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function extend_default_processors(ext) {
|
|
110
|
+
const target = {};
|
|
111
|
+
Object.entries(defaultProcessors).forEach(([ns, proc]) => {
|
|
112
|
+
target[ns] = {
|
|
113
|
+
pre: proc.pre.slice(),
|
|
114
|
+
proc: proc.proc,
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
Object.entries(ext).forEach(([ns, proc]) => {
|
|
118
|
+
const extPre = proc?.pre;
|
|
119
|
+
const extProc = proc?.proc;
|
|
120
|
+
if (target[ns]) {
|
|
121
|
+
if(extPre && extPre.length) {
|
|
122
|
+
target[ns].pre = extPre;
|
|
123
|
+
}
|
|
124
|
+
if(extProc) {
|
|
125
|
+
if (typeof extProc !== 'function') {
|
|
126
|
+
throw new Error(`${ns}.proc must be a function`);
|
|
127
|
+
}
|
|
128
|
+
target[ns].proc = extProc;
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
target[ns] = {
|
|
132
|
+
pre: extPre,
|
|
133
|
+
proc: extProc,
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
return target;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function make_pipeline(descriptor) {
|
|
141
|
+
if (typeof descriptor === 'function') return descriptor;
|
|
142
|
+
var pres = descriptor.pre || [];
|
|
143
|
+
var proc = descriptor.proc;
|
|
144
|
+
return function(event, stackFrame, content, state, callData) {
|
|
145
|
+
var args = [event, stackFrame, content, state, callData];
|
|
146
|
+
for (var i = 0; i < pres.length; i++) {
|
|
147
|
+
args = pres[i].apply(null, args);
|
|
148
|
+
}
|
|
149
|
+
return proc.apply(null, args);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function definitely_comes_before(idx1, idx2) {
|
|
154
|
+
if (idx1 > -1 && idx2 < 0) return true;
|
|
155
|
+
return idx1 > -1 && idx1 < idx2;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function track_line_state(content, data) {
|
|
159
|
+
var lastNl = content.lastIndexOf('\n');
|
|
160
|
+
if (lastNl >= 0) {
|
|
161
|
+
data.hadNewline = true;
|
|
162
|
+
data.currentLineIndent = content.substring(lastNl + 1);
|
|
163
|
+
} else {
|
|
164
|
+
data.currentLineIndent += content;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const defaultProcessor = 'html';
|
|
169
|
+
|
|
170
|
+
const defaultProcessors = {
|
|
171
|
+
unqualified_xml: {
|
|
172
|
+
pre: [pre_hex_chars, pre_hex_entity],
|
|
173
|
+
proc: unqualified_xml
|
|
174
|
+
},
|
|
175
|
+
html: {
|
|
176
|
+
pre: [pre_html_chars, pre_html_entity],
|
|
177
|
+
proc: unqualified_xml
|
|
178
|
+
},
|
|
179
|
+
xsl: {
|
|
180
|
+
pre: [pre_qualified_ns, pre_hex_chars, pre_hex_entity],
|
|
181
|
+
proc: unqualified_xml
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export function init_parse_state(initData) {
|
|
186
|
+
initData = initData || {};
|
|
187
|
+
var data = {
|
|
188
|
+
processor: defaultProcessor,
|
|
189
|
+
lineCount: 0,
|
|
190
|
+
offset: 0,
|
|
191
|
+
lexicalStack: {
|
|
192
|
+
frames: [],
|
|
193
|
+
push: function(x) {
|
|
194
|
+
return this.frames.push(x);
|
|
195
|
+
},
|
|
196
|
+
current_frame: function() {
|
|
197
|
+
return last(this.frames);
|
|
198
|
+
},
|
|
199
|
+
parent_frame: function() {
|
|
200
|
+
return last_but(1, this.frames);
|
|
201
|
+
},
|
|
202
|
+
processor: function() {
|
|
203
|
+
if (!this.frames.length) {
|
|
204
|
+
return data.processor || defaultProcessor;
|
|
205
|
+
}
|
|
206
|
+
var currentFrame = this.current_frame();
|
|
207
|
+
var idxColon = (currentFrame.operator || '').indexOf(':');
|
|
208
|
+
switch (idxColon) {
|
|
209
|
+
case -1: return currentFrame.processor || data.processor || defaultProcessor;
|
|
210
|
+
case 0: return currentFrame.processor;
|
|
211
|
+
default: {
|
|
212
|
+
var currentNs = currentFrame.operator.substring(0, idxColon);
|
|
213
|
+
if (data.processors[currentNs]) {
|
|
214
|
+
return currentNs;
|
|
215
|
+
}
|
|
216
|
+
return defaultProcessor;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
pop: function(buf, isTagChildless) {
|
|
221
|
+
var event = isTagChildless? 'write-tag:no-children' : 'close-tag';
|
|
222
|
+
var poppedFrame = this.frames.pop();
|
|
223
|
+
var currentFrame = this.current_frame();
|
|
224
|
+
var poppedFrameAst = poppedFrame.ast;
|
|
225
|
+
switch (identify_operator(poppedFrame.operator)) {
|
|
226
|
+
case 'tag':
|
|
227
|
+
poppedFrame.processedData = data.processors[poppedFrame.processor](
|
|
228
|
+
event,
|
|
229
|
+
poppedFrame,
|
|
230
|
+
'',
|
|
231
|
+
data.processorState[poppedFrame.processor],
|
|
232
|
+
{
|
|
233
|
+
ast: poppedFrameAst,
|
|
234
|
+
cursor: data.cursor,
|
|
235
|
+
source: data.source,
|
|
236
|
+
lineCount: data.lineCount
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
break;
|
|
240
|
+
case 'attr':
|
|
241
|
+
if (currentFrame) {
|
|
242
|
+
switch (identify_operator(currentFrame.operator)) {
|
|
243
|
+
case 'tag':
|
|
244
|
+
currentFrame.ast.push(poppedFrameAst);
|
|
245
|
+
break;
|
|
246
|
+
case 'attr':
|
|
247
|
+
currentFrame.ast.push(poppedFrameAst);
|
|
248
|
+
break;
|
|
249
|
+
default:
|
|
250
|
+
console.error("Could not merge attributes. Stack frame did not represent attribute or tag.");
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
break;
|
|
254
|
+
default:
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
return poppedFrame;
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
state: null,
|
|
261
|
+
wsBuf: '',
|
|
262
|
+
lastChunk: '',
|
|
263
|
+
isPrettyFormatting: initData.isPrettyFormatting || false,
|
|
264
|
+
currentLineIndent: '',
|
|
265
|
+
hadNewline: false,
|
|
266
|
+
readerMacroName: '',
|
|
267
|
+
readerMacroArgs: ''
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
var source = initData.source;
|
|
271
|
+
if (source === undefined || source === null) {
|
|
272
|
+
data.source = process.stdin;
|
|
273
|
+
} else if (typeof source === 'string' || source instanceof Readable) {
|
|
274
|
+
data.source = source;
|
|
275
|
+
} else {
|
|
276
|
+
throw new Error('source must be a string or a Readable stream');
|
|
277
|
+
}
|
|
278
|
+
data.cursor = initData.cursor || 0;
|
|
279
|
+
|
|
280
|
+
data.processors = {};
|
|
281
|
+
data.processorState = {};
|
|
282
|
+
|
|
283
|
+
const processors = extend_default_processors(initData?.extensions || {});
|
|
284
|
+
|
|
285
|
+
Object.entries(processors).forEach(([ns, descriptor]) => {
|
|
286
|
+
data.processors[ns] = make_pipeline(descriptor);
|
|
287
|
+
data.processorState[ns] = iStackFrame.new();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
data.readers = {
|
|
291
|
+
ext: function(data, args) {
|
|
292
|
+
data.lexicalStack.push(iStackFrame.new({ processor: args, isExtWrapper: true }));
|
|
293
|
+
},
|
|
294
|
+
_default: function(data, args) {
|
|
295
|
+
log_parse_error({ msg: "Unknown reader macro: #" + data.readerMacroName, lineNumber: data.lineCount });
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
if (initData.readers) {
|
|
300
|
+
for (let name in initData.readers) {
|
|
301
|
+
data.readers[name] = initData.readers[name];
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
data.barf_ws = function() {
|
|
306
|
+
var buf = this.wsBuf;
|
|
307
|
+
this.wsBuf = '';
|
|
308
|
+
return buf;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return data;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function update_parse_state(strChunk, data, result) {
|
|
315
|
+
parse_chunk(strChunk, data, result);
|
|
316
|
+
data.offset += strChunk.length;
|
|
317
|
+
data.lastChunk = strChunk;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// The AST for lexical stack frame data is represented like so:
|
|
321
|
+
// [ LEADING_WHITESPACE, TAG [LEADING_WHITESPACE, ATTR_NAME, ATTR_VALUE], ...]
|
|
322
|
+
|
|
323
|
+
const AST_IDX_WS = 0;
|
|
324
|
+
const AST_IDX_TAG = 1;
|
|
325
|
+
const AST_IDX_NAME = 1;
|
|
326
|
+
const AST_IDX_VAL = 2;
|
|
327
|
+
const AST_IDX_AT1 = 2;
|
|
328
|
+
|
|
329
|
+
export function parse_chunk(strChunk, data, result) {
|
|
330
|
+
var lineLength = strChunk.length;
|
|
331
|
+
|
|
332
|
+
var buf = Object.create(Sexp_Buffer_Trait);
|
|
333
|
+
Object.assign(buf, {
|
|
334
|
+
cursor: 0,
|
|
335
|
+
lineCount: data.lineCount,
|
|
336
|
+
str: strChunk,
|
|
337
|
+
token: '',
|
|
338
|
+
substr: strChunk,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
var $1, $2, $3;
|
|
342
|
+
var count = 0;
|
|
343
|
+
|
|
344
|
+
while (true) {
|
|
345
|
+
if (data.state === null
|
|
346
|
+
&& data.attrCapture !== undefined
|
|
347
|
+
&& data.lexicalStack.frames.length === data.attrCaptureDepth) {
|
|
348
|
+
var $captured = result.splice(data.attrCapture).join('');
|
|
349
|
+
data.lexicalStack.current_frame().ast[AST_IDX_VAL] += $captured;
|
|
350
|
+
data.attrCapture = undefined;
|
|
351
|
+
data.state = '(@ _';
|
|
352
|
+
}
|
|
353
|
+
if (!buf.substr) {
|
|
354
|
+
data.cursor += buf.cursor;
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
// Code:
|
|
358
|
+
// #? : Possible escape sequence
|
|
359
|
+
// #_ : Acquire reader macro name
|
|
360
|
+
// #_[ : Acquire reader macro args
|
|
361
|
+
// #( : Opened trapdoor
|
|
362
|
+
// )#? : Closing trapdoor?
|
|
363
|
+
// (? : Discover purpose of opening bracket
|
|
364
|
+
// (# : Opening an s-exp for a tag
|
|
365
|
+
// (# ?: Discover what comes after tag operator
|
|
366
|
+
// (# (: Handle opener discovered within tag operand
|
|
367
|
+
// (@ ?: Discover what comes after attr operator
|
|
368
|
+
// (@1 : Handle first char of s-exp for attribute name
|
|
369
|
+
// (@! : Bad attribute
|
|
370
|
+
// (@_ : Acquire attribute name
|
|
371
|
+
// (@ ": Parsing an attribute value wrapped in double quotes
|
|
372
|
+
// (@ ': Parsing an attribute value wrapped in single quotes
|
|
373
|
+
// (@ _: Parsing an attribute value not wrapped in quotes
|
|
374
|
+
// (& : Parse special char
|
|
375
|
+
// (& 1: Parse the first operand of the special char function
|
|
376
|
+
// (& _: Parse the remaining operands of the special char function
|
|
377
|
+
// (& ): Resolve the special char function
|
|
378
|
+
// )) : Handle second closing bracket
|
|
379
|
+
switch (data.state) {
|
|
380
|
+
case '#?': {
|
|
381
|
+
if ('(' === buf.substr[0]) {
|
|
382
|
+
data.state = '#(';
|
|
383
|
+
} else if (';' === buf.substr[0]) {
|
|
384
|
+
data.state = '#;';
|
|
385
|
+
} else if (/[a-zA-Z0-9_<>=.!-]/.test(buf.substr[0])) {
|
|
386
|
+
data.readerMacroName = buf.substr[0];
|
|
387
|
+
data.state = '#_';
|
|
388
|
+
} else {
|
|
389
|
+
result[result.length] = '#';
|
|
390
|
+
data.state = null;
|
|
391
|
+
}
|
|
392
|
+
buf.step();
|
|
393
|
+
} break;
|
|
394
|
+
case '#_': {
|
|
395
|
+
var nameChars = (buf.substr.match(/^[a-zA-Z0-9_<>=?!.-]*/) || [''])[0];
|
|
396
|
+
data.readerMacroName += nameChars;
|
|
397
|
+
buf.step(nameChars.length);
|
|
398
|
+
if (!buf.substr) { return; }
|
|
399
|
+
if ('_' === data.readerMacroName[0]) {
|
|
400
|
+
log_parse_error({ msg: "Reader macro names cannot start with underscore: #" + data.readerMacroName, lineNumber: data.lineCount });
|
|
401
|
+
data.readerMacroName = '';
|
|
402
|
+
data.state = null;
|
|
403
|
+
} else if ('[' === buf.substr[0]) {
|
|
404
|
+
buf.step();
|
|
405
|
+
data.state = '#_[';
|
|
406
|
+
} else {
|
|
407
|
+
var reader = data.readers[data.readerMacroName] || data.readers._default;
|
|
408
|
+
reader(data, null);
|
|
409
|
+
data.readerMacroName = '';
|
|
410
|
+
data.state = null;
|
|
411
|
+
}
|
|
412
|
+
} break;
|
|
413
|
+
case '#_[': {
|
|
414
|
+
var idxClose = buf.substr.indexOf(']');
|
|
415
|
+
if (idxClose < 0) {
|
|
416
|
+
data.readerMacroArgs += buf.read_to_end();
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
data.readerMacroArgs += buf.read_to(idxClose);
|
|
420
|
+
buf.step();
|
|
421
|
+
var reader = data.readers[data.readerMacroName] || data.readers._default;
|
|
422
|
+
reader(data, data.readerMacroArgs);
|
|
423
|
+
data.readerMacroName = '';
|
|
424
|
+
data.readerMacroArgs = '';
|
|
425
|
+
data.state = null;
|
|
426
|
+
} break;
|
|
427
|
+
case '#(': {
|
|
428
|
+
result[result.length] = buf.read_to(')')
|
|
429
|
+
if (!buf.substr) {
|
|
430
|
+
return;
|
|
431
|
+
} else {
|
|
432
|
+
buf.step();
|
|
433
|
+
data.state = ')#?';
|
|
434
|
+
}
|
|
435
|
+
} break;
|
|
436
|
+
case ')#?': {
|
|
437
|
+
if ('#' === buf.substr[0]) {
|
|
438
|
+
buf.step();
|
|
439
|
+
data.state = null;
|
|
440
|
+
} else {
|
|
441
|
+
result[result.length] = ')';
|
|
442
|
+
data.state = '#(';
|
|
443
|
+
}
|
|
444
|
+
} break;
|
|
445
|
+
case '#;': {
|
|
446
|
+
buf.skip_whitespace();
|
|
447
|
+
if (!buf.substr) { return; }
|
|
448
|
+
if ('(' === buf.substr[0]) {
|
|
449
|
+
data.commentDepth = 1;
|
|
450
|
+
buf.step();
|
|
451
|
+
data.state = '#;(';
|
|
452
|
+
} else {
|
|
453
|
+
data.state = null;
|
|
454
|
+
}
|
|
455
|
+
} break;
|
|
456
|
+
case '#;(': {
|
|
457
|
+
var i = 0;
|
|
458
|
+
var len = buf.substr.length;
|
|
459
|
+
while (i < len) {
|
|
460
|
+
if (buf.substr[i] === '(') {
|
|
461
|
+
data.commentDepth++;
|
|
462
|
+
} else if (buf.substr[i] === ')') {
|
|
463
|
+
data.commentDepth--;
|
|
464
|
+
if (data.commentDepth === 0) {
|
|
465
|
+
buf.reset(i);
|
|
466
|
+
buf.step();
|
|
467
|
+
data.state = null;
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
i++;
|
|
472
|
+
}
|
|
473
|
+
if (data.state === '#;(') {
|
|
474
|
+
buf.reset(len);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
} break;
|
|
478
|
+
case '(?': {
|
|
479
|
+
if (!buf.substr) { return; }
|
|
480
|
+
$1 = identify_operator(buf.substr);
|
|
481
|
+
switch ($1) {
|
|
482
|
+
case 'tag':
|
|
483
|
+
$2 = data.lexicalStack.current_frame();
|
|
484
|
+
if (data.isPrettyFormatting && data.hadNewline && $2) {
|
|
485
|
+
$2.hasBlockChildren = true;
|
|
486
|
+
}
|
|
487
|
+
data.lexicalStack.push(iStackFrame.new({
|
|
488
|
+
processor: null,
|
|
489
|
+
operator: '',
|
|
490
|
+
ast: [''], // 1st element contains whitespace
|
|
491
|
+
namespace: ($2 || {}).namespace,
|
|
492
|
+
indent: data.currentLineIndent
|
|
493
|
+
}));
|
|
494
|
+
data.hadNewline = false;
|
|
495
|
+
data.state = '(#';
|
|
496
|
+
break;
|
|
497
|
+
case 'attr':
|
|
498
|
+
buf.step();
|
|
499
|
+
data.state = '(@1';
|
|
500
|
+
break;
|
|
501
|
+
case 'bracket':
|
|
502
|
+
data.lexicalStack.push(iStackFrame.new({
|
|
503
|
+
processor: data.processor,
|
|
504
|
+
operator: '('
|
|
505
|
+
}));
|
|
506
|
+
result[result.length] = '(';
|
|
507
|
+
buf.step();
|
|
508
|
+
data.state = null;
|
|
509
|
+
break;
|
|
510
|
+
case 'specialchar': {
|
|
511
|
+
var $c = buf.substr[0];
|
|
512
|
+
var $isDirect = $c === '<' || $c === '>';
|
|
513
|
+
data.lexicalStack.push(iStackFrame.new({
|
|
514
|
+
processor: (data.lexicalStack.current_frame() || {}).processor || data.processor,
|
|
515
|
+
operator: '&',
|
|
516
|
+
ast: $isDirect ? [$c, 1] : [''],
|
|
517
|
+
namespace: (
|
|
518
|
+
data.lexicalStack.current_frame() || {}
|
|
519
|
+
).namespace,
|
|
520
|
+
}));
|
|
521
|
+
data.state = $isDirect ? '(& )' : '(&';
|
|
522
|
+
buf.step();
|
|
523
|
+
} break;
|
|
524
|
+
default:
|
|
525
|
+
result[result.length] = '(';
|
|
526
|
+
data.state = null;
|
|
527
|
+
// XXX Why don't we advance here?
|
|
528
|
+
// We must be advancing somewhere else?
|
|
529
|
+
// Is that ok?
|
|
530
|
+
}
|
|
531
|
+
} break;
|
|
532
|
+
case '(#': {
|
|
533
|
+
$1 = data.lexicalStack.current_frame();
|
|
534
|
+
$1.operator += buf.read_token();
|
|
535
|
+
$2 = $1.operator.indexOf(":");
|
|
536
|
+
if ($2 < 0) {
|
|
537
|
+
$1.processor = last_but(1, data.lexicalStack.frames, {}).processor || data.processor;
|
|
538
|
+
} else {
|
|
539
|
+
$1.processor = $1.operator.substring(0, $2);
|
|
540
|
+
if (!data.processors[$1.processor]) {
|
|
541
|
+
$1.processor = defaultProcessor;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
var $parentFrame = last_but(1, data.lexicalStack.frames, {});
|
|
545
|
+
if ($parentFrame.isExtWrapper) {
|
|
546
|
+
$1.processor = $parentFrame.processor;
|
|
547
|
+
data.lexicalStack.frames.splice(data.lexicalStack.frames.length - 2, 1);
|
|
548
|
+
}
|
|
549
|
+
if (!buf.substr) { return; }
|
|
550
|
+
$1.ast[AST_IDX_TAG] = $1.operator;
|
|
551
|
+
$1.ast[AST_IDX_AT1] = [];
|
|
552
|
+
data.state = '(# ?';
|
|
553
|
+
} break;
|
|
554
|
+
case '(# (': {
|
|
555
|
+
switch (identify_operator(buf.substr)) {
|
|
556
|
+
case 'attr':
|
|
557
|
+
data.lexicalStack.push(iStackFrame.new({
|
|
558
|
+
processor: data.processor,
|
|
559
|
+
operator: '@',
|
|
560
|
+
ast: [data.barf_ws()],
|
|
561
|
+
namespace: (
|
|
562
|
+
data.lexicalStack.current_frame() || {}
|
|
563
|
+
).namespace,
|
|
564
|
+
}));
|
|
565
|
+
$1 = data.lexicalStack.current_frame().ast;
|
|
566
|
+
buf.step();
|
|
567
|
+
data.state = '(@1';
|
|
568
|
+
break;
|
|
569
|
+
case 'tag':
|
|
570
|
+
$1 = data.lexicalStack.current_frame();
|
|
571
|
+
if (data.isPrettyFormatting && is_found(data.wsBuf, '\n')) {
|
|
572
|
+
$1.hasBlockChildren = true;
|
|
573
|
+
}
|
|
574
|
+
result[result.length] =
|
|
575
|
+
data.processors[$1.processor](
|
|
576
|
+
'open-tag',
|
|
577
|
+
$1,
|
|
578
|
+
'',
|
|
579
|
+
data.processorState[$1.processor],
|
|
580
|
+
{
|
|
581
|
+
ast: $1.ast,
|
|
582
|
+
cursor: data.cursor + buf.cursor,
|
|
583
|
+
source: data.source,
|
|
584
|
+
lineCount: data.lineCount
|
|
585
|
+
}
|
|
586
|
+
);
|
|
587
|
+
data.lexicalStack.push(iStackFrame.new({
|
|
588
|
+
processor: null,
|
|
589
|
+
operator: '',
|
|
590
|
+
ast: [''],
|
|
591
|
+
namespace: $1.namespace
|
|
592
|
+
}));
|
|
593
|
+
data.lexicalStack.current_frame().ast[AST_IDX_WS] = (
|
|
594
|
+
is_found(data.wsBuf, '\n')? data.barf_ws() : data.barf_ws().substring(1)
|
|
595
|
+
);
|
|
596
|
+
data.lexicalStack.current_frame().indent =
|
|
597
|
+
(data.lexicalStack.current_frame().ast[AST_IDX_WS] || '').match(/[^\n]*$/)[0];
|
|
598
|
+
data.state = '(#';
|
|
599
|
+
break;
|
|
600
|
+
case 'bracket':
|
|
601
|
+
result[result.length] =
|
|
602
|
+
data.processors[data.lexicalStack.processor()](
|
|
603
|
+
'open-tag',
|
|
604
|
+
data.lexicalStack.current_frame(),
|
|
605
|
+
data.processorState[data.lexicalStack.processor()],
|
|
606
|
+
{
|
|
607
|
+
cursor: data.cursor + buf.cursor,
|
|
608
|
+
source: data.source,
|
|
609
|
+
lineCount: data.lineCount
|
|
610
|
+
}
|
|
611
|
+
);
|
|
612
|
+
data.lexicalStack.push(iStackFrame.new({
|
|
613
|
+
processor: data.processor,
|
|
614
|
+
operator: '('
|
|
615
|
+
}));
|
|
616
|
+
result[result.length] =
|
|
617
|
+
data.processors[data.lexicalStack.processor()](
|
|
618
|
+
'begin-escape-bracket',
|
|
619
|
+
data.lexicalStack.current_frame(),
|
|
620
|
+
null,
|
|
621
|
+
{
|
|
622
|
+
cursor: data.cursor + buf.cursor,
|
|
623
|
+
source: data.source,
|
|
624
|
+
lineCount: data.lineCount
|
|
625
|
+
}
|
|
626
|
+
);
|
|
627
|
+
buf.step();
|
|
628
|
+
data.wsBuf = '';
|
|
629
|
+
data.state = null;
|
|
630
|
+
break;
|
|
631
|
+
case 'specialchar': {
|
|
632
|
+
$1 = data.lexicalStack.current_frame();
|
|
633
|
+
result[result.length] = data.processors[$1.processor](
|
|
634
|
+
'open-tag',
|
|
635
|
+
$1,
|
|
636
|
+
'',
|
|
637
|
+
data.processorState[$1.processor],
|
|
638
|
+
{
|
|
639
|
+
ast: $1.ast,
|
|
640
|
+
cursor: data.cursor + buf.cursor,
|
|
641
|
+
source: data.source,
|
|
642
|
+
lineCount: data.lineCount
|
|
643
|
+
}
|
|
644
|
+
);
|
|
645
|
+
data.barf_ws();
|
|
646
|
+
var $c2 = buf.substr[0];
|
|
647
|
+
var $isDirect2 = $c2 === '<' || $c2 === '>';
|
|
648
|
+
data.lexicalStack.push(iStackFrame.new({
|
|
649
|
+
processor: $1.processor || data.processor,
|
|
650
|
+
operator: '&',
|
|
651
|
+
ast: $isDirect2 ? [$c2, 1] : [''],
|
|
652
|
+
namespace: $1.namespace,
|
|
653
|
+
}));
|
|
654
|
+
data.state = $isDirect2 ? '(& )' : '(&';
|
|
655
|
+
buf.step();
|
|
656
|
+
} break;
|
|
657
|
+
case 'none':
|
|
658
|
+
$1 = data.lexicalStack.processor();
|
|
659
|
+
result[result.length] =
|
|
660
|
+
data.processors[$1](
|
|
661
|
+
'open-tag',
|
|
662
|
+
data.lexicalStack.current_frame(),
|
|
663
|
+
data.processorState[data.lexicalStack.processor()],
|
|
664
|
+
{
|
|
665
|
+
ast: $1.ast,
|
|
666
|
+
cursor: data.cursor + buf.cursor,
|
|
667
|
+
source: data.source,
|
|
668
|
+
lineCount: data.lineCount
|
|
669
|
+
}
|
|
670
|
+
);
|
|
671
|
+
data.state = null;
|
|
672
|
+
buf.step();
|
|
673
|
+
break;
|
|
674
|
+
default: {
|
|
675
|
+
console.error(["ERR: ", identify_operator(buf.substr), "did not match a pattern"].join(' '));
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
} break;
|
|
679
|
+
case '(# ?': {
|
|
680
|
+
data.wsBuf += buf.read_whitespace();
|
|
681
|
+
$1 = data.lexicalStack.current_frame().ast
|
|
682
|
+
if (!buf.substr) { return; }
|
|
683
|
+
if (buf.substr[0] === ')') {
|
|
684
|
+
buf.step();
|
|
685
|
+
$1[AST_IDX_AT1] = [data.barf_ws()];
|
|
686
|
+
$2 = data.lexicalStack.pop(buf, true);
|
|
687
|
+
result[result.length] = $2.processedData;
|
|
688
|
+
data.state = null;
|
|
689
|
+
} else if (buf.substr[0] === '(') {
|
|
690
|
+
buf.step();
|
|
691
|
+
data.state = '(# (';
|
|
692
|
+
} else {
|
|
693
|
+
var $frame = data.lexicalStack.current_frame();
|
|
694
|
+
result[result.length] =
|
|
695
|
+
data.processors[$frame.processor](
|
|
696
|
+
'open-tag',
|
|
697
|
+
$frame,
|
|
698
|
+
data.processorState[$frame.processor],
|
|
699
|
+
{
|
|
700
|
+
ast: $1,
|
|
701
|
+
cursor: data.cursor + buf.cursor,
|
|
702
|
+
source: data.source,
|
|
703
|
+
lineCount: data.lineCount
|
|
704
|
+
}
|
|
705
|
+
);
|
|
706
|
+
// TODO: Work out how to handle this whitespace after opening tag.
|
|
707
|
+
if (is_found(data.wsBuf, '\n')) {
|
|
708
|
+
result[result.length] = data.barf_ws();
|
|
709
|
+
} else {
|
|
710
|
+
result[result.length] = data.barf_ws().substring(1);
|
|
711
|
+
}
|
|
712
|
+
data.state = null;
|
|
713
|
+
}
|
|
714
|
+
} break;
|
|
715
|
+
case '(@1': {
|
|
716
|
+
$1 = buf.substr[0];
|
|
717
|
+
switch ($1) {
|
|
718
|
+
case ')':
|
|
719
|
+
buf.step();
|
|
720
|
+
data.state = null;
|
|
721
|
+
break;
|
|
722
|
+
default: {
|
|
723
|
+
if (/[\s'"]/.test($1)) {
|
|
724
|
+
data.state = '(@!';
|
|
725
|
+
} else {
|
|
726
|
+
buf.step();
|
|
727
|
+
if (!data.lexicalStack.current_frame()) {
|
|
728
|
+
data.lexicalStack.push(iStackFrame.new({
|
|
729
|
+
processor: data.processor,
|
|
730
|
+
operator: '@',
|
|
731
|
+
ast: []
|
|
732
|
+
}));
|
|
733
|
+
}
|
|
734
|
+
data.lexicalStack.current_frame().ast[AST_IDX_NAME] = $1;
|
|
735
|
+
data.state = '(@_';
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
} break;
|
|
740
|
+
case '(@!': {
|
|
741
|
+
// TODO: Put bad attributes into AST.
|
|
742
|
+
// Maybe by appending to ws string.
|
|
743
|
+
result[result.length] = buf.read_to(')')
|
|
744
|
+
if (!buf.substr) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
buf.step();
|
|
748
|
+
data.state = null;
|
|
749
|
+
} break;
|
|
750
|
+
case '(@_': {
|
|
751
|
+
$1 = data.lexicalStack.current_frame();
|
|
752
|
+
$2 = $1.ast;
|
|
753
|
+
$2[AST_IDX_NAME] += buf.read_token();
|
|
754
|
+
if (!buf.substr) { return; }
|
|
755
|
+
if (!is_valid_attr_name($2[AST_IDX_NAME])) {
|
|
756
|
+
// XXX Will read funny for super-long attribute names
|
|
757
|
+
log_parse_error({
|
|
758
|
+
msg: "Invalid attribute name",
|
|
759
|
+
lineNumber: data.lineCount,
|
|
760
|
+
token: last($2)[AST_IDX_NAME]
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
$2[AST_IDX_VAL] = '';
|
|
764
|
+
data.state = '(@ ?';
|
|
765
|
+
} break;
|
|
766
|
+
case '(@ ?': {
|
|
767
|
+
buf.skip_whitespace();
|
|
768
|
+
if (!buf.substr) { return; }
|
|
769
|
+
$1 = buf.substr[0];
|
|
770
|
+
if (is_char_quote_mark($1)) {
|
|
771
|
+
data.lexicalStack.current_frame().ast[AST_IDX_VAL] = $1;
|
|
772
|
+
buf.step();
|
|
773
|
+
data.state = '(@ ' + $1;
|
|
774
|
+
} else if (')' === $1) {
|
|
775
|
+
data.lexicalStack.pop(buf);
|
|
776
|
+
buf.step();
|
|
777
|
+
data.state = '(# ?';
|
|
778
|
+
} else {
|
|
779
|
+
data.lexicalStack.current_frame().ast[AST_IDX_VAL] = '"';
|
|
780
|
+
buf.skip_whitespace();
|
|
781
|
+
data.state = '(@ _';
|
|
782
|
+
}
|
|
783
|
+
} break;
|
|
784
|
+
case '(@ "':
|
|
785
|
+
case "(@ '": {
|
|
786
|
+
$1 = index_of_closing_quote(buf.substr, last(data.state));
|
|
787
|
+
$2 = data.lexicalStack.current_frame().ast;
|
|
788
|
+
if ($1 > -1) {
|
|
789
|
+
$2[AST_IDX_VAL] += buf.read_to($1 +1);
|
|
790
|
+
if (!(0 === $1 && '\\' === (last(data.lastChunk)))) {
|
|
791
|
+
data.state = '(@ ?';
|
|
792
|
+
}
|
|
793
|
+
} else {
|
|
794
|
+
$2[AST_IDX_VAL] += buf.read_to_end();
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
} break;
|
|
798
|
+
|
|
799
|
+
case '(@ ?(': {
|
|
800
|
+
if (!buf.substr) { return; }
|
|
801
|
+
if (buf.substr[0] === '@') {
|
|
802
|
+
data.lexicalStack.current_frame().ast[AST_IDX_VAL] += '(';
|
|
803
|
+
data.state = '(@ _';
|
|
804
|
+
} else {
|
|
805
|
+
data.attrCapture = result.length;
|
|
806
|
+
data.attrCaptureDepth = data.lexicalStack.frames.length;
|
|
807
|
+
data.state = '(?';
|
|
808
|
+
}
|
|
809
|
+
} break;
|
|
810
|
+
|
|
811
|
+
case '(@ _': {
|
|
812
|
+
$1 = buf.substr.indexOf(')');
|
|
813
|
+
$3 = buf.substr.indexOf('(');
|
|
814
|
+
$2 = data.lexicalStack.current_frame().ast;
|
|
815
|
+
if (definitely_comes_before($3, $1)) {
|
|
816
|
+
$2[AST_IDX_VAL] += buf.read_to($3);
|
|
817
|
+
buf.step();
|
|
818
|
+
data.state = '(@ ?(';
|
|
819
|
+
} else if ($1 > -1) {
|
|
820
|
+
$2[AST_IDX_VAL] += buf.read_to($1) + '"';
|
|
821
|
+
data.state = '(@ ?';
|
|
822
|
+
} else {
|
|
823
|
+
$2[AST_IDX_VAL] += buf.read_to_end();
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
} break;
|
|
827
|
+
|
|
828
|
+
case '(&': {
|
|
829
|
+
$1 = data.lexicalStack.current_frame();
|
|
830
|
+
$1.ast[0] += buf.read_token();
|
|
831
|
+
if (!buf.substr) { return }
|
|
832
|
+
if (')' === buf.substr[0]) {
|
|
833
|
+
$1.ast[1] = 1;
|
|
834
|
+
data.state = '(& )';
|
|
835
|
+
} else {
|
|
836
|
+
$1.ast[1] = '';
|
|
837
|
+
buf.step();
|
|
838
|
+
data.state = '(& 1';
|
|
839
|
+
}
|
|
840
|
+
} break;
|
|
841
|
+
|
|
842
|
+
case '(& 1': {
|
|
843
|
+
$1 = data.lexicalStack.current_frame();
|
|
844
|
+
$1.ast[1] += buf.read_token()
|
|
845
|
+
if (!buf.substr) { return; }
|
|
846
|
+
$1.ast[1] = parseInt($1.ast[1], 10);
|
|
847
|
+
if (')' === buf.substr[0]) {
|
|
848
|
+
data.state = '(& )';
|
|
849
|
+
} else {
|
|
850
|
+
data.state = '(& _';
|
|
851
|
+
}
|
|
852
|
+
} break;
|
|
853
|
+
|
|
854
|
+
case '(& _': {
|
|
855
|
+
$1 = buf.substr.indexOf(')');
|
|
856
|
+
if ($1 < 0) { return; }
|
|
857
|
+
buf.reset($1);
|
|
858
|
+
data.state = '(& )';
|
|
859
|
+
} break;
|
|
860
|
+
|
|
861
|
+
case '(& )': {
|
|
862
|
+
$1 = data.lexicalStack.current_frame();
|
|
863
|
+
$2 = {'': '&', '&': '&', '<': '<', '>': '>'}[$1.ast[0]];
|
|
864
|
+
if ($2 !== undefined) {
|
|
865
|
+
result[result.length] = data.processors[data.lexicalStack.processor()](
|
|
866
|
+
'content',
|
|
867
|
+
$1,
|
|
868
|
+
$2.repeat($1.ast[1]),
|
|
869
|
+
data.processorState[data.lexicalStack.processor()],
|
|
870
|
+
{
|
|
871
|
+
cursor: data.cursor + buf.cursor,
|
|
872
|
+
lineCount: data.lineCount,
|
|
873
|
+
source: data.source
|
|
874
|
+
}
|
|
875
|
+
);
|
|
876
|
+
} else {
|
|
877
|
+
$2 = data.processors[data.lexicalStack.processor()](
|
|
878
|
+
'entity',
|
|
879
|
+
$1,
|
|
880
|
+
$1.ast[0],
|
|
881
|
+
data.processorState[data.lexicalStack.processor()],
|
|
882
|
+
{
|
|
883
|
+
cursor: data.cursor + buf.cursor,
|
|
884
|
+
lineCount: data.lineCount,
|
|
885
|
+
source: data.source
|
|
886
|
+
}
|
|
887
|
+
);
|
|
888
|
+
for ($3 = 0; $3 < $1.ast[1]; ++$3) {
|
|
889
|
+
result[result.length] = $2;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
buf.step();
|
|
893
|
+
data.lexicalStack.pop(buf);
|
|
894
|
+
data.state = null;
|
|
895
|
+
} break;
|
|
896
|
+
|
|
897
|
+
case '))': {
|
|
898
|
+
if (!buf.substr.length) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
if (')' === buf.substr[0]) {
|
|
902
|
+
buf.step();
|
|
903
|
+
}
|
|
904
|
+
data.state = null;
|
|
905
|
+
} break;
|
|
906
|
+
|
|
907
|
+
default: {
|
|
908
|
+
// Not quoting an attribute value. Any string that's
|
|
909
|
+
// within an s-exp is a text node (barring the operator).
|
|
910
|
+
//
|
|
911
|
+
// We can put anything up to a closing bracket straight
|
|
912
|
+
// to result if we're in a stack. Anything up to an opener
|
|
913
|
+
// if we're not.
|
|
914
|
+
|
|
915
|
+
var idxOpeningBracket = buf.substr.indexOf('(');
|
|
916
|
+
var idxClosingBracket = buf.substr.indexOf(')');
|
|
917
|
+
var idxHash = buf.substr.indexOf('#');
|
|
918
|
+
|
|
919
|
+
if (definitely_comes_before(idxClosingBracket, idxOpeningBracket)) {
|
|
920
|
+
$3 = buf.read_to(idxClosingBracket);
|
|
921
|
+
if (data.isPrettyFormatting) track_line_state($3, data);
|
|
922
|
+
result[result.length] = data.processors[data.lexicalStack.processor()](
|
|
923
|
+
'content',
|
|
924
|
+
data.lexicalStack.current_frame(),
|
|
925
|
+
$3,
|
|
926
|
+
data.processorState[data.lexicalStack.processor()],
|
|
927
|
+
{
|
|
928
|
+
cursor: data.cursor + buf.cursor,
|
|
929
|
+
lineCount: data.lineCount,
|
|
930
|
+
source: data.source
|
|
931
|
+
}
|
|
932
|
+
);
|
|
933
|
+
if (data.lexicalStack.frames.length) {
|
|
934
|
+
if ('(' === data.lexicalStack.current_frame().operator) {
|
|
935
|
+
result[result.length] = data.processors[data.lexicalStack.processor()]('end-escape-bracket');
|
|
936
|
+
data.lexicalStack.pop(buf);
|
|
937
|
+
data.state = '))';
|
|
938
|
+
} else {
|
|
939
|
+
$1 = data.lexicalStack.pop(buf)
|
|
940
|
+
if ('tag' === identify_operator($1.operator)) {
|
|
941
|
+
if (data.isPrettyFormatting && $1.hasBlockChildren) {
|
|
942
|
+
$2 = result[result.length - 1] || '';
|
|
943
|
+
if (!$2.endsWith('\n')) {
|
|
944
|
+
result[result.length] = '\n' + ($1.indent || '');
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
result[result.length] = $1.processedData;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
} else {
|
|
951
|
+
result[result.length] = ')';
|
|
952
|
+
}
|
|
953
|
+
buf.step();
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
if (definitely_comes_before(idxHash, idxOpeningBracket)) {
|
|
958
|
+
$3 = buf.read_to(idxHash);
|
|
959
|
+
if (data.isPrettyFormatting) track_line_state($3, data);
|
|
960
|
+
result[result.length] = data.processors[data.lexicalStack.processor()](
|
|
961
|
+
'content',
|
|
962
|
+
data.lexicalStack.current_frame(),
|
|
963
|
+
$3,
|
|
964
|
+
data.processorState[data.lexicalStack.processor()],
|
|
965
|
+
{
|
|
966
|
+
cursor: data.cursor + buf.cursor,
|
|
967
|
+
lineCount: data.lineCount,
|
|
968
|
+
source: data.source
|
|
969
|
+
}
|
|
970
|
+
);
|
|
971
|
+
buf.step();
|
|
972
|
+
data.state = '#?';
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
if (idxOpeningBracket > -1) {
|
|
977
|
+
$3 = buf.read_to(idxOpeningBracket);
|
|
978
|
+
if (data.isPrettyFormatting) track_line_state($3, data);
|
|
979
|
+
result[result.length] = data.processors[data.lexicalStack.processor()](
|
|
980
|
+
'content',
|
|
981
|
+
data.lexicalStack.current_frame(),
|
|
982
|
+
$3,
|
|
983
|
+
data.processorState[data.lexicalStack.processor()],
|
|
984
|
+
{
|
|
985
|
+
cursor: data.cursor + buf.cursor,
|
|
986
|
+
lineCount: data.lineCount,
|
|
987
|
+
source: data.source
|
|
988
|
+
}
|
|
989
|
+
);
|
|
990
|
+
buf.step();
|
|
991
|
+
data.state = '(?';
|
|
992
|
+
continue;
|
|
993
|
+
} else {
|
|
994
|
+
$3 = buf.read_to_end();
|
|
995
|
+
if (data.isPrettyFormatting) track_line_state($3, data);
|
|
996
|
+
result[result.length] = data.processors[data.lexicalStack.processor()](
|
|
997
|
+
'content',
|
|
998
|
+
data.lexicalStack.current_frame(),
|
|
999
|
+
$3,
|
|
1000
|
+
data.processorState[data.lexicalStack.processor()],
|
|
1001
|
+
{
|
|
1002
|
+
cursor: data.cursor + buf.cursor,
|
|
1003
|
+
lineCount: data.lineCount,
|
|
1004
|
+
source: data.source
|
|
1005
|
+
}
|
|
1006
|
+
);
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|