92 lines
1.8 KiB
JavaScript
92 lines
1.8 KiB
JavaScript
|
/**
|
||
|
* The MIT License (MIT)
|
||
|
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
|
||
|
*/
|
||
|
|
||
|
'use strict';
|
||
|
|
||
|
/**
|
||
|
* A regexp-tree plugin to replace single char group disjunction to char group
|
||
|
*
|
||
|
* a|b|c -> [abc]
|
||
|
* [12]|3|4 -> [1234]
|
||
|
* (a|b|c) -> ([abc])
|
||
|
* (?:a|b|c) -> [abc]
|
||
|
*/
|
||
|
|
||
|
module.exports = {
|
||
|
Disjunction: function Disjunction(path) {
|
||
|
var node = path.node,
|
||
|
parent = path.parent;
|
||
|
|
||
|
|
||
|
if (!handlers[parent.type]) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var charset = new Map();
|
||
|
|
||
|
if (!shouldProcess(node, charset) || !charset.size) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var characterClass = {
|
||
|
type: 'CharacterClass',
|
||
|
expressions: Array.from(charset.keys()).sort().map(function (key) {
|
||
|
return charset.get(key);
|
||
|
})
|
||
|
};
|
||
|
|
||
|
handlers[parent.type](path.getParent(), characterClass);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var handlers = {
|
||
|
RegExp: function RegExp(path, characterClass) {
|
||
|
var node = path.node;
|
||
|
|
||
|
|
||
|
node.body = characterClass;
|
||
|
},
|
||
|
Group: function Group(path, characterClass) {
|
||
|
var node = path.node;
|
||
|
|
||
|
|
||
|
if (node.capturing) {
|
||
|
node.expression = characterClass;
|
||
|
} else {
|
||
|
path.replace(characterClass);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
function shouldProcess(expression, charset) {
|
||
|
if (!expression) {
|
||
|
// Abort on empty disjunction part
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
var type = expression.type;
|
||
|
|
||
|
|
||
|
if (type === 'Disjunction') {
|
||
|
var left = expression.left,
|
||
|
right = expression.right;
|
||
|
|
||
|
|
||
|
return shouldProcess(left, charset) && shouldProcess(right, charset);
|
||
|
} else if (type === 'Char') {
|
||
|
var value = expression.value;
|
||
|
|
||
|
|
||
|
charset.set(value, expression);
|
||
|
|
||
|
return true;
|
||
|
} else if (type === 'CharacterClass') {
|
||
|
return expression.expressions.every(function (expression) {
|
||
|
return shouldProcess(expression, charset);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|