wikipeg 6.1.2 → 6.1.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/HISTORY.md +9 -0
- package/README.md +41 -7
- package/bin/wikipeg +8 -0
- package/lib/compiler/passes/analyze-params.js +21 -8
- package/lib/compiler/passes/ast-to-code.js +23 -33
- package/lib/compiler/passes/transform-common-lang.js +4 -1
- package/lib/peg.js +1 -1
- package/lib/utils/transform-array.js +1367 -0
- package/package.json +7 -5
- package/VERSION +0 -1
package/HISTORY.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
## 6.1.3 (2026-06-03)
|
|
4
|
+
* Add array-transformation rules to --common-lang transformation,
|
|
5
|
+
which allows you to generate PHP and JavaScript parser from the same
|
|
6
|
+
grammar specification.
|
|
7
|
+
* Add --esm option to wikipeg binary to allow creation of a JavaScript
|
|
8
|
+
ESM module.
|
|
9
|
+
* Bug fix to parameter value assertions involving reference
|
|
10
|
+
parameters, which would previously incorrectly fail a type check.
|
|
11
|
+
|
|
3
12
|
## 6.1.2 (2026-05-07)
|
|
4
13
|
* Update jasmine to 7.0.0-pre.1. This removes the reported security
|
|
5
14
|
vulnerability in the glob package even though this is only used
|
package/README.md
CHANGED
|
@@ -589,12 +589,17 @@ All parameters referenced in the grammar have an initial value and can
|
|
|
589
589
|
be used before their first assignment.
|
|
590
590
|
|
|
591
591
|
Parameters have a type detected at compile time: boolean, integer,
|
|
592
|
-
|
|
592
|
+
or string. Initial values for each type are:
|
|
593
593
|
- boolean: false
|
|
594
594
|
- integer: 0
|
|
595
595
|
- string: ""
|
|
596
|
-
|
|
597
|
-
|
|
596
|
+
|
|
597
|
+
Parameters can also be a *reference* to a value of one of these types,
|
|
598
|
+
in which case they are initialized to `null`. Parameters can also be
|
|
599
|
+
set to the value of a labeled expression; these assignments are
|
|
600
|
+
ignored for the purpose of assigning a type and initial value. However,
|
|
601
|
+
if *every* assignment to the parameter is a labeled expression it is
|
|
602
|
+
given the initial value `null`.
|
|
598
603
|
|
|
599
604
|
The parameter namespace is global, but the value of a parameter reverts
|
|
600
605
|
to its previous value after termination of the assigning rule reference.
|
|
@@ -747,10 +752,39 @@ done to manage the memory cost of excessive caching of simple matches.
|
|
|
747
752
|
For more predictable caching, you may wish to use the `noInlining`
|
|
748
753
|
option.
|
|
749
754
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
755
|
+
Making a release
|
|
756
|
+
----------------
|
|
757
|
+
Each wikipeg release is made to the PHP ecosystem
|
|
758
|
+
(composer/packagist.org) and Node/JS ecosystem (npm/npmjs.org)
|
|
759
|
+
together.
|
|
760
|
+
|
|
761
|
+
1. Begin by running `composer update-history` which will
|
|
762
|
+
update the [`HISTORY.md`](./HISTORY.md) with the next patch version.
|
|
763
|
+
Update the release number in `HISTORY.md` if this is to be a minor or
|
|
764
|
+
major release.
|
|
765
|
+
|
|
766
|
+
2. Update the version number in [`package.json`](./package.json) and
|
|
767
|
+
at the top of [`lib/peg.js`](./lib/peg.js).
|
|
768
|
+
|
|
769
|
+
3. Run `npm install --package-lock-only` to update the version number
|
|
770
|
+
in [`package-lock.json`](./package-lock.json).
|
|
771
|
+
|
|
772
|
+
4. Commit these changes with the commit message "Release <version number>",
|
|
773
|
+
and push to gerrit. When merged, sign and tag the resulting commit
|
|
774
|
+
with the unprefixed version number; eg `git tag -s 6.1.3`. Push the
|
|
775
|
+
tag to the origin (`git push origin 6.1.3`) to complete the
|
|
776
|
+
PHP/composer/`packagist.org` release.
|
|
777
|
+
|
|
778
|
+
5. With the tagged release as your local HEAD, `npm publish` to push
|
|
779
|
+
the release to node/npm/`npmjs.org`.
|
|
780
|
+
|
|
781
|
+
6. Run `composer update-history` again, which should add an entry to
|
|
782
|
+
`HISTORY.md` for the next "not yet released" version. Add a `-git`
|
|
783
|
+
suffix to the version number in [`package.json`](./package.json) and
|
|
784
|
+
at the top of [`lib/peg.js`](./lib/peg.js).
|
|
785
|
+
Run `npm install --package-lock-only` to update `package-lock.json`.
|
|
786
|
+
Commit these changes with the commit message "Bump version after
|
|
787
|
+
release" and push to gerrit.
|
|
754
788
|
|
|
755
789
|
Development
|
|
756
790
|
-----------
|
package/bin/wikipeg
CHANGED
|
@@ -33,6 +33,7 @@ Options:
|
|
|
33
33
|
"module.exports")
|
|
34
34
|
--php force PHP mode regardless of extension
|
|
35
35
|
--class-name <name> specify generated PHP class name
|
|
36
|
+
--esm generate ESM module instead of CommonJS
|
|
36
37
|
--cache make generated parser cache results
|
|
37
38
|
--allowed-start-rules <rules> comma-separated list of rules the generated
|
|
38
39
|
parser will be allowed to start parsing
|
|
@@ -122,6 +123,7 @@ function readStream(inputStream, callback) {
|
|
|
122
123
|
|
|
123
124
|
/* This makes the generated parser a CommonJS module by default. */
|
|
124
125
|
var exportVar = "module.exports";
|
|
126
|
+
var sourceSuffix = "";
|
|
125
127
|
var options = {
|
|
126
128
|
cache: false,
|
|
127
129
|
output: "source",
|
|
@@ -142,6 +144,11 @@ while (args.length > 0 && isOption(args[0])) {
|
|
|
142
144
|
options.language = "php";
|
|
143
145
|
break;
|
|
144
146
|
|
|
147
|
+
case "--esm":
|
|
148
|
+
exportVar = "const api";
|
|
149
|
+
sourceSuffix = "\nexport default api;";
|
|
150
|
+
break;
|
|
151
|
+
|
|
145
152
|
case '--common-lang':
|
|
146
153
|
options.commonLang = true;
|
|
147
154
|
break;
|
|
@@ -318,6 +325,7 @@ readStream(inputStream, function(input) {
|
|
|
318
325
|
|
|
319
326
|
if (options.language === 'javascript') {
|
|
320
327
|
outputStream.write(exportVar !== "" ? `${exportVar} = ${source}\n` : `${source}\n`);
|
|
328
|
+
outputStream.write(sourceSuffix);
|
|
321
329
|
} else {
|
|
322
330
|
outputStream.write(source + "\n");
|
|
323
331
|
}
|
|
@@ -10,7 +10,7 @@ function analyzeParams(ast, options) {
|
|
|
10
10
|
var boolIndex = 0;
|
|
11
11
|
var refScopeIndex = 0;
|
|
12
12
|
|
|
13
|
-
function registerParamType(name, type, location) {
|
|
13
|
+
function registerParamType(name, isref, type, location) {
|
|
14
14
|
var paramInfo = getParamInfo(name);
|
|
15
15
|
if (
|
|
16
16
|
(paramInfo.type === 'labeled' && type === 'boolean') ||
|
|
@@ -18,12 +18,27 @@ function analyzeParams(ast, options) {
|
|
|
18
18
|
){
|
|
19
19
|
throw new GrammarError("Labeled expression parameters can't also be boolean: " + name, location);
|
|
20
20
|
}
|
|
21
|
+
if (paramInfo.isref === undefined ) {
|
|
22
|
+
paramInfo.isref = isref;
|
|
23
|
+
paramInfo.isrefLocation = location;
|
|
24
|
+
} else if (isref !== undefined ) {
|
|
25
|
+
if ( paramInfo.isref !== isref) {
|
|
26
|
+
throw new GrammarError(
|
|
27
|
+
"Reference type conflict in parameter " + name +
|
|
28
|
+
" (previous def at " + paramInfo.isrefLocation + ")",
|
|
29
|
+
location);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
21
32
|
if (paramInfo.type !== undefined && paramInfo.type !== 'labeled') {
|
|
22
33
|
if (paramInfo.type !== type && type !== 'labeled') {
|
|
23
|
-
throw new GrammarError(
|
|
34
|
+
throw new GrammarError(
|
|
35
|
+
"Type conflict in parameter " + name +
|
|
36
|
+
" (previous def at " + paramInfo.typeLocation + ")",
|
|
37
|
+
location);
|
|
24
38
|
}
|
|
25
39
|
} else {
|
|
26
40
|
paramInfo.type = type;
|
|
41
|
+
paramInfo.typeLocation = location;
|
|
27
42
|
if (type === 'boolean') {
|
|
28
43
|
if (boolIndex > 31) {
|
|
29
44
|
throw new GrammarError("A maximum of 32 boolean parameters may be defined", location);
|
|
@@ -118,14 +133,12 @@ function analyzeParams(ast, options) {
|
|
|
118
133
|
let assignment = node.assignments[i];
|
|
119
134
|
let type;
|
|
120
135
|
|
|
121
|
-
if (assignment.
|
|
122
|
-
type = 'reference';
|
|
123
|
-
} else if (assignment.type === 'increment') {
|
|
136
|
+
if (assignment.type === 'increment') {
|
|
124
137
|
type = 'integer';
|
|
125
138
|
} else {
|
|
126
139
|
type = assignment.type;
|
|
127
140
|
}
|
|
128
|
-
registerParamType(assignment.name, type, node.location);
|
|
141
|
+
registerParamType(assignment.name, assignment.isref || false, type, node.location);
|
|
129
142
|
assignment.paramInfo = getParamInfo(assignment.name);
|
|
130
143
|
|
|
131
144
|
let refScope = null;
|
|
@@ -142,12 +155,12 @@ function analyzeParams(ast, options) {
|
|
|
142
155
|
},
|
|
143
156
|
parameter_and: function(node) {
|
|
144
157
|
if (node.assert) {
|
|
145
|
-
registerParamType(node.parameter, node.assert.type, node.location);
|
|
158
|
+
registerParamType(node.parameter, undefined, node.assert.type, node.location);
|
|
146
159
|
}
|
|
147
160
|
},
|
|
148
161
|
parameter_not: function(node) {
|
|
149
162
|
if (node.assert) {
|
|
150
|
-
registerParamType(node.parameter, node.assert.type, node.location);
|
|
163
|
+
registerParamType(node.parameter, undefined, node.assert.type, node.location);
|
|
151
164
|
}
|
|
152
165
|
},
|
|
153
166
|
})(ast);
|
|
@@ -337,7 +337,7 @@ function generateJavascript(ast, options) {
|
|
|
337
337
|
let rule = currentRule;
|
|
338
338
|
// Add reference variables
|
|
339
339
|
for (let name in rule.passedParams) {
|
|
340
|
-
if (rule.passedParams[name].
|
|
340
|
+
if (rule.passedParams[name].isref) {
|
|
341
341
|
saved.refs.push({reg: allocReg([]), name: name});
|
|
342
342
|
}
|
|
343
343
|
}
|
|
@@ -595,7 +595,7 @@ function generateJavascript(ast, options) {
|
|
|
595
595
|
function makeActionFunc(code, context) {
|
|
596
596
|
var argNames = [];
|
|
597
597
|
Object.keys(context.env).forEach(function(argName) {
|
|
598
|
-
if (context.envTypes[argName]
|
|
598
|
+
if (context.envTypes[argName].isref) {
|
|
599
599
|
argNames.push(language.refArgActionDeclarator(argName));
|
|
600
600
|
} else {
|
|
601
601
|
argNames.push(language.valueArgActionDeclarator(argName));
|
|
@@ -641,7 +641,7 @@ function generateJavascript(ast, options) {
|
|
|
641
641
|
*/
|
|
642
642
|
function makeParamExpression(info) {
|
|
643
643
|
if (!currentRule || !currentRule.passedParams[info.name]) {
|
|
644
|
-
return makeInitialParamValue(info
|
|
644
|
+
return makeInitialParamValue(info);
|
|
645
645
|
}
|
|
646
646
|
if (info.type === undefined) {
|
|
647
647
|
throw new Error("Undefined parameter type");
|
|
@@ -649,7 +649,7 @@ function generateJavascript(ast, options) {
|
|
|
649
649
|
return [
|
|
650
650
|
'/*', info.name, '*/',
|
|
651
651
|
'(', language.boolParams, ' & 0x', (1 << info.index).toString(16), ') !== 0'].join('');
|
|
652
|
-
} else if (info.
|
|
652
|
+
} else if (info.isref) {
|
|
653
653
|
return language.refParamValue(info.name);
|
|
654
654
|
} else {
|
|
655
655
|
return language.paramArgName(info.name);
|
|
@@ -660,7 +660,7 @@ function generateJavascript(ast, options) {
|
|
|
660
660
|
* Return an expression which gives the parameter reference object
|
|
661
661
|
*/
|
|
662
662
|
function makeParamRefExpression(info) {
|
|
663
|
-
if (info.
|
|
663
|
+
if (!info.isref) {
|
|
664
664
|
throw new Error('Cannot make reference object for non-reference parameter ' + info.name);
|
|
665
665
|
}
|
|
666
666
|
return language.paramArgName(info.name);
|
|
@@ -669,20 +669,19 @@ function generateJavascript(ast, options) {
|
|
|
669
669
|
/**
|
|
670
670
|
* Get an expression giving the initial value of a parameter
|
|
671
671
|
*/
|
|
672
|
-
function makeInitialParamValue(info,
|
|
672
|
+
function makeInitialParamValue(info, refIsNull) {
|
|
673
673
|
let type = info.type;
|
|
674
|
+
let isref = info.isref;
|
|
675
|
+
if (isref) {
|
|
676
|
+
let val = refIsNull ? 'null' : makeInitialParamValue({type:type});
|
|
677
|
+
return language.newRef(val);
|
|
678
|
+
}
|
|
674
679
|
if (type === 'boolean') {
|
|
675
680
|
return 'false';
|
|
676
681
|
} else if (type === 'integer') {
|
|
677
682
|
return '0';
|
|
678
683
|
} else if (type === 'string') {
|
|
679
684
|
return '""';
|
|
680
|
-
} else if (type === 'reference') {
|
|
681
|
-
if (isref) {
|
|
682
|
-
return language.newRef('null');
|
|
683
|
-
} else {
|
|
684
|
-
return 'null';
|
|
685
|
-
}
|
|
686
685
|
} else if (type === 'labeled') {
|
|
687
686
|
return 'null';
|
|
688
687
|
} else {
|
|
@@ -861,10 +860,11 @@ function generateJavascript(ast, options) {
|
|
|
861
860
|
|
|
862
861
|
for (let name in rule.passedParams) {
|
|
863
862
|
let type = rule.passedParams[name].type;
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
} else if (type === 'reference') {
|
|
863
|
+
let isref = rule.passedParams[name].isref;
|
|
864
|
+
if (isref) {
|
|
867
865
|
args.push(language.refParamArgDeclarator(name));
|
|
866
|
+
} else if (type === undefined || type === 'boolean') {
|
|
867
|
+
continue;
|
|
868
868
|
} else {
|
|
869
869
|
args.push(language.paramArgName(name));
|
|
870
870
|
}
|
|
@@ -889,18 +889,7 @@ function generateJavascript(ast, options) {
|
|
|
889
889
|
args.push('0');
|
|
890
890
|
} else {
|
|
891
891
|
let paramName = language.paramNameFromArg(argName);
|
|
892
|
-
|
|
893
|
-
if (type === 'integer') {
|
|
894
|
-
args.push('0');
|
|
895
|
-
} else if (type === 'boolean') {
|
|
896
|
-
args.push('false');
|
|
897
|
-
} else if (type === 'string') {
|
|
898
|
-
args.push('""');
|
|
899
|
-
} else if (type === 'reference') {
|
|
900
|
-
args.push(language.newRef('null'));
|
|
901
|
-
} else {
|
|
902
|
-
throw new Error('Unknown param type: ' + type);
|
|
903
|
-
}
|
|
892
|
+
args.push(makeInitialParamValue(rule.passedParams[paramName], true));
|
|
904
893
|
}
|
|
905
894
|
}
|
|
906
895
|
return args;
|
|
@@ -926,10 +915,11 @@ function generateJavascript(ast, options) {
|
|
|
926
915
|
|
|
927
916
|
for (let name in rule.passedParams) {
|
|
928
917
|
let type = rule.passedParams[name].type;
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
} else if (type === 'reference') {
|
|
918
|
+
let isref = rule.passedParams[name].isref;
|
|
919
|
+
if (isref) {
|
|
932
920
|
args.push(language.refParamValue(name));
|
|
921
|
+
} else if (type === undefined || type === 'boolean') {
|
|
922
|
+
continue;
|
|
933
923
|
} else {
|
|
934
924
|
args.push(language.paramArgName(name));
|
|
935
925
|
}
|
|
@@ -945,7 +935,7 @@ function generateJavascript(ast, options) {
|
|
|
945
935
|
function getCacheLoadRefs(rule) {
|
|
946
936
|
var block = [];
|
|
947
937
|
for (let name in rule.passedParams) {
|
|
948
|
-
if (rule.passedParams[name].
|
|
938
|
+
if (rule.passedParams[name].isref) {
|
|
949
939
|
block.push(language.cacheLoadRef(name));
|
|
950
940
|
}
|
|
951
941
|
}
|
|
@@ -1323,7 +1313,7 @@ function generateJavascript(ast, options) {
|
|
|
1323
1313
|
var subresult = recurse(node.expression, newContext);
|
|
1324
1314
|
subresult.block.push(`// ${node.label} <- ${reg}`);
|
|
1325
1315
|
context.env[node.label] = reg;
|
|
1326
|
-
context.envTypes[node.label] = 'value';
|
|
1316
|
+
context.envTypes[node.label] = { type: 'value' };
|
|
1327
1317
|
return subresult;
|
|
1328
1318
|
},
|
|
1329
1319
|
|
|
@@ -1334,7 +1324,7 @@ function generateJavascript(ast, options) {
|
|
|
1334
1324
|
} else {
|
|
1335
1325
|
context.env[node.label] = makeParamExpression(node.paramInfo);
|
|
1336
1326
|
}
|
|
1337
|
-
context.envTypes[node.label] = node.paramInfo
|
|
1327
|
+
context.envTypes[node.label] = node.paramInfo;
|
|
1338
1328
|
result.condition = 'true';
|
|
1339
1329
|
result.expression = language.assertionSuccess;
|
|
1340
1330
|
return result;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var visitor
|
|
3
|
+
var visitor = require("../visitor");
|
|
4
|
+
var transformArray = require("../../utils/transform-array");
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Perform a few simple transformations to convert a special subset of PHP to
|
|
@@ -14,6 +16,7 @@ function transformCommonLang(ast, options) {
|
|
|
14
16
|
|
|
15
17
|
function transform(code) {
|
|
16
18
|
if (options.language === 'javascript') {
|
|
19
|
+
code = transformArray.parse(code);
|
|
17
20
|
code = code.replace(/\$this->/g, '');
|
|
18
21
|
code = code.replace(/\$(?=\w+)/g, '');
|
|
19
22
|
}
|