Named captures

This commit is contained in:
Tony Garnock-Jones 2014-07-24 19:46:16 -07:00
parent 28405b544f
commit 80befd60eb
2 changed files with 61 additions and 13 deletions

View File

@ -15,17 +15,20 @@ function embeddedMatcher(matcher) {
return new $Embedded(matcher);
}
// The name argument should be a string or null; it defaults to null.
// The pattern argument defaults to wildcard, __.
function $Capture(pattern) {
function $Capture(name, pattern) {
this.name = name || null;
this.pattern = (typeof pattern === 'undefined' ? __ : pattern);
}
// Abbreviation: _$(x) <==> new $Capture(x)
function _$(pattern) {
return new $Capture(pattern);
// Abbreviation: _$(...) <==> new $Capture(...)
function _$(name, pattern) {
return new $Capture(name, pattern);
}
function isCapture(x) { return x instanceof $Capture || x === _$; }
function captureName(x) { return x instanceof $Capture ? x.name : null; }
function capturePattern(x) { return x instanceof $Capture ? x.pattern : __; }
var SOC = "__{{"; // start of capture
@ -745,15 +748,17 @@ function relabel(m, f) {
}
function compileProjection(/* projection, projection, ... */) {
var names = [];
var acc = [];
for (var i = 0; i < arguments.length; i++) {
walk(arguments[i]);
}
acc.push(EOA);
return acc;
return {names: names, spec: acc};
function walk(p) {
if (isCapture(p)) {
names.push(captureName(p));
acc.push(SOC);
walk(capturePattern(p));
acc.push(EOC);
@ -803,7 +808,8 @@ function projectionToPattern(p) {
}
}
function project(m, spec) {
function project(m, compiledProjection) {
var spec = compiledProjection.spec;
return walk(false, m, 0);
function walk(isCapturing, m, specIndex) {
@ -1031,6 +1037,20 @@ function matcherKeys(m) {
}
}
function matcherKeysToObjects(matcherKeysResult, compiledProjection) {
if (matcherKeysResult === null) return null;
var result = [];
for (var i = 0; i < matcherKeysResult.length; i++) {
var e = matcherKeysResult[i];
var d = {};
for (var j = 0; j < e.length; j++) {
d[compiledProjection.names[j] || j] = e[j];
}
result.push(d);
}
return result;
}
function prettyMatcher(m, initialIndent) {
var acc = [];
walk(initialIndent || 0, m);
@ -1505,6 +1525,7 @@ module.exports.compileProjection = compileProjection;
module.exports.projectionToPattern = projectionToPattern;
module.exports.project = project;
module.exports.matcherKeys = matcherKeys;
module.exports.matcherKeysToObjects = matcherKeysToObjects;
module.exports.matcherEquals = matcherEquals;
module.exports.prettyMatcher = prettyMatcher;
module.exports.serializeMatcher = serializeMatcher;

View File

@ -47,17 +47,17 @@ console.log("projections");
dumpM(r.project(r.union(r.compilePattern(r.arrayToSet(['A']), r.__),
r.compilePattern(r.arrayToSet(['B']), ['b'])),
r.compileProjection(r._$([[r.__]]))));
r.compileProjection(r._$("v", [[r.__]]))));
dumpM(r.project(r.union(r.compilePattern(r.arrayToSet(['A']), [1, 2]),
r.compilePattern(r.arrayToSet(['C']), [1, 3]),
r.compilePattern(r.arrayToSet(['B']), [3, 4])),
r.compileProjection([r._$(), r._$()])));
r.compileProjection([r._$, r._$])));
dump(r.matcherKeys(r.project(r.union(r.compilePattern(r.arrayToSet(['A']), [1, 2]),
r.compilePattern(r.arrayToSet(['C']), [1, 3]),
r.compilePattern(r.arrayToSet(['B']), [3, 4])),
r.compileProjection([r._$(), r._$()]))));
r.compileProjection([r._$, r._$]))));
var R1 = r.compilePattern(r.arrayToSet(['A']), [r.__, "B"]);
var R2 = r.compilePattern(r.arrayToSet(['B']), ["A", r.__]);
@ -185,9 +185,9 @@ dumpM(r.union(r.compilePattern(r.arrayToSet('A'), [2]),
var M = r.union(r.compilePattern(r.arrayToSet(['A']), [r.__, 2]),
r.compilePattern(r.arrayToSet(['C']), [1, 3]),
r.compilePattern(r.arrayToSet(['B']), [3, 4]));
dump(r.matcherKeys(r.project(M, r.compileProjection([r._$(), r._$()]))));
dump(r.matcherKeys(r.project(M, r.compileProjection([r._$, r._$]))));
dump(r.matcherKeys(r.project(M, r.compileProjection([r.__, r._$]))));
var M2 = r.project(M, r.compileProjection([r._$(), r._$()]));
var M2 = r.project(M, r.compileProjection([r._$, r._$]));
dump(r.matcherKeys(r.project(M2,
r.compileProjection(r.__, r._$))));
dump(r.matcherKeys(r.project(r.compilePattern(true, [r.embeddedMatcher(M2)]),
@ -201,9 +201,36 @@ dumpM(r.union(r.compilePattern(r.arrayToSet('A'), [2]),
var M = r.union(r.compilePattern(r.arrayToSet(['A']), [1, 2]),
r.compilePattern(r.arrayToSet(['C']), [1, 3]),
r.compilePattern(r.arrayToSet(['B']), [3, 4]));
var M2 = r.project(M, r.compileProjection([r._$(), r._$()]));
var proj = r.compileProjection([r._$, r._$]);
var M2 = r.project(M, proj);
dump(r.matcherKeys(M2));
dump(r.matcherKeys(r.project(M2, r.compileProjection(r._$(), r._$()))));
dump(r.matcherKeys(r.project(M2, r.compileProjection(r._$, r._$))));
dump(r.matcherKeysToObjects(r.matcherKeys(r.project(M2, r.compileProjection(r._$, r._$))),
proj));
})();
(function () {
console.log("matcherKeys using multiple-values in projections, with names");
var M = r.union(r.compilePattern(r.arrayToSet(['A']), [1, 2]),
r.compilePattern(r.arrayToSet(['C']), [1, 3]),
r.compilePattern(r.arrayToSet(['B']), [3, 4]));
var proj = r.compileProjection([r._$("fst"), r._$("snd")]);
var M2 = r.project(M, proj);
dump(r.matcherKeys(M2));
dump(r.matcherKeysToObjects(r.matcherKeys(r.project(M2, r.compileProjection(r._$, r._$))),
proj));
})();
(function () {
console.log("matcherKeys using multiple-values in projections, with partial names");
var M = r.union(r.compilePattern(r.arrayToSet(['A']), [1, 2]),
r.compilePattern(r.arrayToSet(['C']), [1, 3]),
r.compilePattern(r.arrayToSet(['B']), [3, 4]));
var proj = r.compileProjection([r._$, r._$("snd")]);
var M2 = r.project(M, proj);
dump(r.matcherKeys(M2));
dump(r.matcherKeysToObjects(r.matcherKeys(r.project(M2, r.compileProjection(r._$, r._$))),
proj));
})();
(function () {