wikipeg 2.0.5 → 4.0.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/README.md +2 -0
- package/VERSION +1 -1
- package/bin/wikipeg +18 -0
- package/lib/compiler/language/javascript.js +8 -2
- package/lib/compiler/language/php.js +15 -10
- package/lib/compiler/passes/ast-to-code.js +61 -18
- package/lib/parser.js +2 -0
- package/lib/peg.js +1 -1
- package/lib/runtime/template.js +1 -3
- package/lib/runtime/template.php +61 -47
- package/package.json +47 -47
- package/src/DefaultTracer.php +61 -60
- package/src/Expectation.php +48 -46
- package/src/InternalError.php +1 -1
- package/src/Location.php +33 -32
- package/src/LocationRange.php +32 -30
- package/src/PEGParserBase.php +298 -277
- package/src/SyntaxError.php +30 -27
- package/src/Tracer.php +2 -2
- package/CHANGELOG.md +0 -433
package/README.md
CHANGED
|
@@ -67,6 +67,8 @@ You can tweak the generated parser with several options:
|
|
|
67
67
|
* `--extra-options-file` — file with additional options (in JSON format) to
|
|
68
68
|
pass to `PEG.buildParser`
|
|
69
69
|
* `--trace` — makes the parser trace its progress
|
|
70
|
+
* `--header-comment-file` — file containing a well-formatted comment, used
|
|
71
|
+
to customize the comment at the top of the generated file
|
|
70
72
|
|
|
71
73
|
### JavaScript API
|
|
72
74
|
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0.0
|
package/bin/wikipeg
CHANGED
|
@@ -47,6 +47,11 @@ Options:
|
|
|
47
47
|
to PEG.buildParser
|
|
48
48
|
--extra-options-file <file> file with additional options (in JSON
|
|
49
49
|
format) to pass to PEG.buildParser
|
|
50
|
+
--header-comment-file <file> file containing the comment to add at the top
|
|
51
|
+
of the generated file to document where it
|
|
52
|
+
comes from. Must contain all formatting
|
|
53
|
+
necessary for said comment in the target
|
|
54
|
+
language.
|
|
50
55
|
-v, --version print version information and exit
|
|
51
56
|
-h, --help print help and exit
|
|
52
57
|
`);
|
|
@@ -210,6 +215,19 @@ while (args.length > 0 && isOption(args[0])) {
|
|
|
210
215
|
addExtraOptions(options, json);
|
|
211
216
|
break;
|
|
212
217
|
|
|
218
|
+
case "--header-comment-file":
|
|
219
|
+
nextArg();
|
|
220
|
+
if (args.length === 0) {
|
|
221
|
+
abort("Missing parameter of the --header-comment-file option.");
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
var comment = fs.readFileSync(args[0]);
|
|
225
|
+
} catch(e) {
|
|
226
|
+
abort("Can't read from file \"" + args[0] + "\".");
|
|
227
|
+
}
|
|
228
|
+
options.headerComment = comment;
|
|
229
|
+
break;
|
|
230
|
+
|
|
213
231
|
case "-v":
|
|
214
232
|
case "--version":
|
|
215
233
|
printVersion();
|
|
@@ -225,6 +225,11 @@ let javascript = {
|
|
|
225
225
|
if (opts.params.length) {
|
|
226
226
|
keyParts = keyParts.concat(opts.params);
|
|
227
227
|
}
|
|
228
|
+
let storeRefs = opts.storeRefs.filter(function(part) {
|
|
229
|
+
return part !== '';
|
|
230
|
+
}).map(function(part) {
|
|
231
|
+
return ' ' + part;
|
|
232
|
+
}).join('\n');
|
|
228
233
|
return {
|
|
229
234
|
start: [
|
|
230
235
|
`var key = [${keyParts.join(',')}].map(String).join(":");`,
|
|
@@ -241,7 +246,7 @@ let javascript = {
|
|
|
241
246
|
' nextPos: peg$currPos, ',
|
|
242
247
|
` result: ${opts.result}, `,
|
|
243
248
|
'};',
|
|
244
|
-
|
|
249
|
+
storeRefs
|
|
245
250
|
].join('\n')
|
|
246
251
|
};
|
|
247
252
|
},
|
|
@@ -251,7 +256,8 @@ let javascript = {
|
|
|
251
256
|
return ` if (cached.hasOwnProperty(${encName})) param_${name}.value = cached.$${name};`;
|
|
252
257
|
},
|
|
253
258
|
|
|
254
|
-
cacheStoreRef(name) {
|
|
259
|
+
cacheStoreRef(name, store) {
|
|
260
|
+
if (!store) return '';
|
|
255
261
|
return `if (saved_${name} !== param_${name}.value) cached.$${name} = param_${name}.value;`;
|
|
256
262
|
},
|
|
257
263
|
|
|
@@ -424,33 +424,38 @@ let php = {
|
|
|
424
424
|
if (opts.params.length) {
|
|
425
425
|
keyParts = keyParts.concat(opts.params);
|
|
426
426
|
}
|
|
427
|
+
let storeRefs = opts.storeRefs.map(function(part) {
|
|
428
|
+
return ' ' + part;
|
|
429
|
+
}).join(',\n');
|
|
427
430
|
return {
|
|
428
431
|
start: [
|
|
429
432
|
`$key = json_encode([${keyParts.join(',')}]);`,
|
|
430
433
|
`$cached = $this->cache[$key] ?? null;`,
|
|
431
434
|
`if ($cached) {`,
|
|
432
|
-
` $this->currPos = $cached
|
|
435
|
+
` $this->currPos = $cached->nextPos;`,
|
|
433
436
|
opts.loadRefs,
|
|
434
|
-
` return $cached
|
|
437
|
+
` return $cached->result;`,
|
|
435
438
|
'}',
|
|
436
439
|
opts.saveRefs,
|
|
437
440
|
].join('\n'),
|
|
438
441
|
store: [
|
|
439
|
-
`$
|
|
440
|
-
|
|
441
|
-
|
|
442
|
+
`$this->cache[$key] = new ${opts.className}CacheEntry(`,
|
|
443
|
+
' $this->currPos,',
|
|
444
|
+
` ${opts.result + (opts.storeRefs.length > 0 ? ',' : '')}`,
|
|
445
|
+
storeRefs,
|
|
446
|
+
`);`
|
|
442
447
|
].join('\n')
|
|
443
448
|
};
|
|
444
449
|
},
|
|
445
450
|
|
|
446
451
|
cacheLoadRef(name) {
|
|
447
|
-
|
|
448
|
-
return `if (array_key_exists(${encName}, $cached)) $param_${name} = $cached[${encName}];`;
|
|
452
|
+
return `if ($cached->${name} !== self::$UNDEFINED) { $param_${name} = $cached->${name}; }`;
|
|
449
453
|
},
|
|
450
454
|
|
|
451
|
-
cacheStoreRef(name) {
|
|
452
|
-
|
|
453
|
-
|
|
455
|
+
cacheStoreRef(name, store) {
|
|
456
|
+
return store ?
|
|
457
|
+
`$saved_${name} !== $param_${name} ? $param_${name} : self::$UNDEFINED` :
|
|
458
|
+
'self::$UNDEFINED';
|
|
454
459
|
},
|
|
455
460
|
|
|
456
461
|
/**
|
|
@@ -80,6 +80,28 @@ function generateJavascript(ast, options) {
|
|
|
80
80
|
language = js;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
var className = options.className || 'PEGParser';
|
|
84
|
+
var namespace = '';
|
|
85
|
+
var matches = className.match(/^(.*)\\([^\\]*)$/);
|
|
86
|
+
if (matches) {
|
|
87
|
+
className = matches[2];
|
|
88
|
+
namespace = `namespace ${matches[1]};`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
var refsSet = {};
|
|
92
|
+
var getRefs = visitor.build({
|
|
93
|
+
rule_ref: function(node) {
|
|
94
|
+
for (let i = 0; i < node.assignments.length; i++) {
|
|
95
|
+
let assignment = node.assignments[i];
|
|
96
|
+
if (assignment.isref) {
|
|
97
|
+
refsSet[assignment.name] = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
getRefs(ast);
|
|
103
|
+
var references = Object.keys(refsSet);
|
|
104
|
+
|
|
83
105
|
/**
|
|
84
106
|
* The default init cache hook
|
|
85
107
|
*/
|
|
@@ -91,7 +113,6 @@ function generateJavascript(ast, options) {
|
|
|
91
113
|
var generateCacheRule = language.generateCacheRule;
|
|
92
114
|
|
|
93
115
|
function indent2(code) { return code.replace(/^(.+)$/gm, ' $1'); }
|
|
94
|
-
function indent4(code) { return code.replace(/^(.+)$/gm, ' $1'); }
|
|
95
116
|
|
|
96
117
|
/**
|
|
97
118
|
* The Context class.
|
|
@@ -749,21 +770,23 @@ function generateJavascript(ast, options) {
|
|
|
749
770
|
block.push(language.cacheLoadRef(name));
|
|
750
771
|
}
|
|
751
772
|
}
|
|
752
|
-
return
|
|
773
|
+
return indent2(block.join('\n'));
|
|
753
774
|
}
|
|
754
775
|
|
|
755
776
|
/**
|
|
756
|
-
* Get
|
|
757
|
-
* refs
|
|
777
|
+
* Get the list of expressions or statements returned by cacheStoreRef() for
|
|
778
|
+
* refs which may have changed.
|
|
758
779
|
*/
|
|
759
780
|
function getCacheStoreRefs(rule) {
|
|
760
|
-
var
|
|
781
|
+
var store = {};
|
|
761
782
|
for (let name in rule.passedParams) {
|
|
762
783
|
if (rule.passedParams[name].type === 'reference') {
|
|
763
|
-
|
|
784
|
+
store[name] = true;
|
|
764
785
|
}
|
|
765
786
|
}
|
|
766
|
-
return
|
|
787
|
+
return references.map(function(name) {
|
|
788
|
+
return language.cacheStoreRef(name, store[name]);
|
|
789
|
+
});
|
|
767
790
|
}
|
|
768
791
|
|
|
769
792
|
/**
|
|
@@ -774,10 +797,10 @@ function generateJavascript(ast, options) {
|
|
|
774
797
|
var parts = [];
|
|
775
798
|
for (let name in rule.passedParams) {
|
|
776
799
|
if (rule.passedParams[name].type === 'reference') {
|
|
777
|
-
parts.push(
|
|
800
|
+
parts.push(language.cacheSaveRef(name));
|
|
778
801
|
}
|
|
779
802
|
}
|
|
780
|
-
return
|
|
803
|
+
return parts.join('\n');
|
|
781
804
|
}
|
|
782
805
|
|
|
783
806
|
function expandTemplate(template, vars) {
|
|
@@ -848,6 +871,7 @@ function generateJavascript(ast, options) {
|
|
|
848
871
|
loadRefs: getCacheLoadRefs(node),
|
|
849
872
|
saveRefs: getCacheSaveRefs(node),
|
|
850
873
|
storeRefs: getCacheStoreRefs(node),
|
|
874
|
+
className: className,
|
|
851
875
|
});
|
|
852
876
|
body.push(cacheBits.start);
|
|
853
877
|
}
|
|
@@ -1356,15 +1380,8 @@ function generateJavascript(ast, options) {
|
|
|
1356
1380
|
}
|
|
1357
1381
|
templateVars['/*GENERATED*/'] = generated.join('\n');
|
|
1358
1382
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
if (matches) {
|
|
1362
|
-
templateVars['CLASS_NAME'] = matches[2];
|
|
1363
|
-
templateVars['/*NAMESPACE*/'] = `namespace ${matches[1]};`;
|
|
1364
|
-
} else {
|
|
1365
|
-
templateVars['CLASS_NAME'] = className;
|
|
1366
|
-
templateVars['/*NAMESPACE*/'] = '';
|
|
1367
|
-
}
|
|
1383
|
+
templateVars['CLASS_NAME'] = className;
|
|
1384
|
+
templateVars['/*NAMESPACE*/'] = namespace;
|
|
1368
1385
|
|
|
1369
1386
|
var cacheInitCode = '';
|
|
1370
1387
|
var cacheInitHook;
|
|
@@ -1377,9 +1394,35 @@ function generateJavascript(ast, options) {
|
|
|
1377
1394
|
}
|
|
1378
1395
|
templateVars['/*CACHE_INIT*/'] = cacheInitCode;
|
|
1379
1396
|
|
|
1397
|
+
var headerComment = '';
|
|
1398
|
+
if (options.headerComment) {
|
|
1399
|
+
headerComment = options.headerComment + '\n';
|
|
1400
|
+
} else {
|
|
1401
|
+
headerComment = '/*\n' +
|
|
1402
|
+
' * Generated by WikiPEG\n' +
|
|
1403
|
+
' */\n\n';
|
|
1404
|
+
}
|
|
1405
|
+
templateVars['/*HEADER_COMMENT*/'] = headerComment;
|
|
1406
|
+
|
|
1380
1407
|
var template;
|
|
1381
1408
|
if (options.language === 'php') {
|
|
1382
1409
|
template = fs.readFileSync(__dirname + '/../../runtime/template.php', 'utf8');
|
|
1410
|
+
if (options.cache) {
|
|
1411
|
+
templateVars['/*CACHE_ENTRY_BEGIN*/'] = '';
|
|
1412
|
+
templateVars['/*CACHE_ENTRY_END*/'] = '';
|
|
1413
|
+
templateVars['/*CACHE_ENTRY_DECLARE*/'] = '';
|
|
1414
|
+
templateVars['/*CACHE_ENTRY_ARGS*/'] = '';
|
|
1415
|
+
templateVars['/*CACHE_ENTRY_INIT*/'] = '';
|
|
1416
|
+
references.forEach(function(name) {
|
|
1417
|
+
templateVars['/*CACHE_ENTRY_DECLARE*/'] += `\tpublic $${name};\n`;
|
|
1418
|
+
templateVars['/*CACHE_ENTRY_ARGS*/'] += `, $${name}`;
|
|
1419
|
+
templateVars['/*CACHE_ENTRY_INIT*/'] += `\t\t$this->${name} = $${name};\n`;
|
|
1420
|
+
});
|
|
1421
|
+
} else {
|
|
1422
|
+
template = template.replace(
|
|
1423
|
+
/\/\*CACHE_ENTRY_BEGIN\*\/[^]+?\/\*CACHE_ENTRY_END\*\//, ''
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1383
1426
|
} else {
|
|
1384
1427
|
template = fs.readFileSync(__dirname + '/../../runtime/template.js', 'utf8');
|
|
1385
1428
|
}
|
package/lib/parser.js
CHANGED
package/lib/peg.js
CHANGED
package/lib/runtime/template.js
CHANGED
package/lib/runtime/template.php
CHANGED
|
@@ -1,53 +1,67 @@
|
|
|
1
1
|
<?php
|
|
2
|
-
|
|
2
|
+
/*HEADER_COMMENT*/
|
|
3
3
|
/*NAMESPACE*/
|
|
4
4
|
|
|
5
5
|
/*INITIALIZER0*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
7
|
+
/*CACHE_ENTRY_BEGIN*/
|
|
8
|
+
class CLASS_NAMECacheEntry {
|
|
9
|
+
public $nextPos;
|
|
10
|
+
public $result;
|
|
11
|
+
/*CACHE_ENTRY_DECLARE*/
|
|
12
|
+
|
|
13
|
+
public function __construct( $nextPos, $result/*CACHE_ENTRY_ARGS*/ ) {
|
|
14
|
+
$this->nextPos = $nextPos;
|
|
15
|
+
$this->result = $result;
|
|
16
|
+
/*CACHE_ENTRY_INIT*/
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/*CACHE_ENTRY_END*/
|
|
20
|
+
|
|
21
|
+
class CLASS_NAME extends \Wikimedia\WikiPEG\PEGParserBase {
|
|
22
|
+
// initializer
|
|
23
|
+
/*INITIALIZER*/
|
|
24
|
+
|
|
25
|
+
// cache init
|
|
26
|
+
/*CACHE_INIT*/
|
|
27
|
+
|
|
28
|
+
// expectations
|
|
29
|
+
protected $expectations = [
|
|
30
|
+
/*EXPECTATIONS*/
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
// actions
|
|
34
|
+
/*ACTIONS*/
|
|
35
|
+
|
|
36
|
+
// generated
|
|
37
|
+
/*GENERATED*/
|
|
38
|
+
|
|
39
|
+
public function parse( $input, $options = [] ) {
|
|
40
|
+
$this->initInternal( $input, $options );
|
|
41
|
+
$startRule = $options['startRule'] ?? '(DEFAULT)';
|
|
42
|
+
$result = null;
|
|
43
|
+
|
|
44
|
+
if ( !empty( $options['stream'] ) ) {
|
|
45
|
+
switch ( $startRule ) {
|
|
46
|
+
/*STREAM_CASES*/
|
|
47
|
+
default:
|
|
48
|
+
throw new \Wikimedia\WikiPEG\InternalError( "Can't stream rule $startRule." );
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
switch ( $startRule ) {
|
|
52
|
+
/*START_CASES*/
|
|
53
|
+
default:
|
|
54
|
+
throw new \Wikimedia\WikiPEG\InternalError( "Can't start parsing from rule $startRule." );
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if ( $result !== self::$FAILED && $this->currPos === $this->inputLength ) {
|
|
59
|
+
return $result;
|
|
60
|
+
} else {
|
|
61
|
+
if ( $result !== self::$FAILED && $this->currPos < $this->inputLength ) {
|
|
62
|
+
$this->fail( /*END_EXPECTATION*/ );
|
|
63
|
+
}
|
|
64
|
+
throw $this->buildParseException();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
53
67
|
}
|
package/package.json
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
2
|
+
"name": "wikipeg",
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"description": "Parser generator for JavaScript and PHP",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://gerrit.wikimedia.org/r/plugins/gitiles/wikipeg/",
|
|
7
|
+
"contributors": [
|
|
8
|
+
{
|
|
9
|
+
"name": "David Majda",
|
|
10
|
+
"email": "david@majda.cz",
|
|
11
|
+
"url": "http://majda.cz/"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Tim Starling",
|
|
15
|
+
"email": "tstarling@wikimedia.org"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"files": [
|
|
19
|
+
"CHANGELOG.md",
|
|
20
|
+
"LICENSE",
|
|
21
|
+
"README.md",
|
|
22
|
+
"VERSION",
|
|
23
|
+
"bin/wikipeg",
|
|
24
|
+
"examples/*.pegjs",
|
|
25
|
+
"examples/*.pegphp",
|
|
26
|
+
"lib/**/*.js",
|
|
27
|
+
"lib/**/*.php",
|
|
28
|
+
"src/**/*.php",
|
|
29
|
+
"tools/build-browser.js",
|
|
30
|
+
"package.json"
|
|
31
|
+
],
|
|
32
|
+
"main": "lib/peg",
|
|
33
|
+
"bin": "bin/wikipeg",
|
|
34
|
+
"scripts": {
|
|
35
|
+
"eslint": "make eslint",
|
|
36
|
+
"test": "make eslint && make test"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://gerrit.wikimedia.org/r/wikipeg"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"eslint": "8.31.0",
|
|
44
|
+
"jasmine-node": "3.0.0"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">= 6.0.0"
|
|
48
|
+
}
|
|
49
49
|
}
|
package/src/DefaultTracer.php
CHANGED
|
@@ -1,72 +1,73 @@
|
|
|
1
1
|
<?php
|
|
2
2
|
|
|
3
|
-
namespace WikiPEG;
|
|
3
|
+
namespace Wikimedia\WikiPEG;
|
|
4
|
+
|
|
5
|
+
use InvalidArgumentException;
|
|
4
6
|
|
|
5
7
|
class DefaultTracer implements Tracer {
|
|
6
|
-
|
|
8
|
+
private $indentLevel = 0;
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
public function trace( $event ) {
|
|
11
|
+
switch ( $event['type'] ) {
|
|
12
|
+
case 'rule.enter':
|
|
13
|
+
$this->log( $event );
|
|
14
|
+
$this->indentLevel++;
|
|
15
|
+
break;
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
case 'rule.match':
|
|
18
|
+
$this->indentLevel--;
|
|
19
|
+
$this->log( $event );
|
|
20
|
+
break;
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
case 'rule.fail':
|
|
23
|
+
$this->indentLevel--;
|
|
24
|
+
$this->log( $event );
|
|
25
|
+
break;
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
default:
|
|
28
|
+
throw new InvalidArgumentException( "Invalid event type {$event['type']}" );
|
|
29
|
+
}
|
|
30
|
+
}
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
32
|
+
private function log( $event ) {
|
|
33
|
+
print str_pad(
|
|
34
|
+
'' . $event['location'],
|
|
35
|
+
20
|
|
36
|
+
)
|
|
37
|
+
. str_pad( $event['type'], 10 ) . ' '
|
|
38
|
+
. str_repeat( ' ', $this->indentLevel ) . $event['rule']
|
|
39
|
+
. $this->formatArgs( $event['args'] ?? null )
|
|
40
|
+
. "\n";
|
|
41
|
+
}
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
private function formatArgs( $argMap ) {
|
|
44
|
+
if ( !$argMap ) {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
48
|
+
$argParts = [];
|
|
49
|
+
foreach ( $argMap as $argName => $argValue ) {
|
|
50
|
+
if ( $argName === '$silence' ) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if ( $argName === '$boolParams' ) {
|
|
54
|
+
$argParts[] = '0x' . base_convert( $argValue, 10, 16 );
|
|
55
|
+
} else {
|
|
56
|
+
$displayName = str_replace( '$param_', '', $argName );
|
|
57
|
+
if ( $displayName[0] === '&' ) {
|
|
58
|
+
$displayName = substr( $displayName, 1 );
|
|
59
|
+
$ref = '&';
|
|
60
|
+
} else {
|
|
61
|
+
$ref = '';
|
|
62
|
+
}
|
|
63
|
+
$argParts[] = "$displayName=$ref" .
|
|
64
|
+
json_encode( $argValue, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if ( $argParts ) {
|
|
68
|
+
return '<' . implode( ', ', $argParts ) . '>';
|
|
69
|
+
} else {
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
72
73
|
}
|