regexp-tree
Advanced tools
Comparing version 0.0.78 to 0.0.79
@@ -153,3 +153,3 @@ /** | ||
// state is accepting as well. | ||
if (states.includes(nfaAcceptingState)) { | ||
if (states.indexOf(nfaAcceptingState) !== -1) { | ||
_this._acceptingStateNumbers.add(states.join(',')); | ||
@@ -156,0 +156,0 @@ break; |
@@ -67,3 +67,3 @@ /** | ||
* | ||
* A `handler` is an object containing handler function for needed | ||
* Each `handler` is an object containing handler function for needed | ||
* node types. Example: | ||
@@ -76,5 +76,8 @@ * | ||
* }); | ||
* | ||
* The value for a node type may also be an object with functions pre and post. | ||
* This enables more context-aware analyses, e.g. measuring star height. | ||
*/ | ||
traverse: function traverse(ast, handlers) { | ||
return _traverse.traverse(ast, handlers); | ||
traverse: function traverse(ast, handlers, options) { | ||
return _traverse.traverse(ast, handlers, options); | ||
}, | ||
@@ -81,0 +84,0 @@ |
@@ -108,9 +108,14 @@ /** | ||
* | ||
* @param Array<Object>|Object handlers: | ||
* @param Object | Array<Object> handlers: | ||
* | ||
* an object (or an array of objects) | ||
* containing handler function per node. In case of an array of | ||
* handlers, they are applied in order. A handler may return a | ||
* transformed node (or a different type). | ||
* | ||
* Each such object contains a handler function per node. | ||
* In case of an array of handlers, they are applied in order. | ||
* A handler may return a transformed node (or a different type). | ||
* | ||
* The per-node function may instead be an object with functions pre and post. | ||
* pre is called before visiting the node, post after. | ||
* If a handler is a function, it is treated as the pre function, with an empty post. | ||
* | ||
* @param Object options: | ||
@@ -138,2 +143,3 @@ * | ||
if (!Array.isArray(handlers)) { | ||
@@ -143,3 +149,3 @@ handlers = [handlers]; | ||
// Filter out handlers by result of `shouldRun`, if the method presents. | ||
// Filter out handlers by result of `shouldRun`, if the method is present. | ||
handlers = handlers.filter(function (handler) { | ||
@@ -161,5 +167,11 @@ if (typeof handler.shouldRun !== 'function') { | ||
function getPathFor(node, parent, prop, index) { | ||
var parentPath = NodePath.getForNode(parent); | ||
var nodePath = NodePath.getForNode(node, parentPath, prop, index); | ||
return nodePath; | ||
} | ||
// Handle actual nodes. | ||
astTraverse(ast, { | ||
/** | ||
@@ -169,9 +181,5 @@ * Handler on node enter. | ||
pre: function pre(node, parent, prop, index) { | ||
var parentPath = void 0; | ||
var nodePath = void 0; | ||
if (!options.asNodes) { | ||
parentPath = NodePath.getForNode(parent); | ||
nodePath = NodePath.getForNode(node, parentPath, prop, index); | ||
nodePath = getPathFor(node, parent, prop, index); | ||
} | ||
@@ -189,5 +197,3 @@ | ||
if (typeof handler['*'] === 'function') { | ||
if (options.asNodes) { | ||
handler['*'](node, parent, prop, index); | ||
} else { | ||
if (nodePath) { | ||
// A path/node can be removed by some previous handler. | ||
@@ -201,2 +207,4 @@ if (!nodePath.isRemoved()) { | ||
} | ||
} else { | ||
handler['*'](node, parent, prop, index); | ||
} | ||
@@ -206,9 +214,14 @@ } | ||
// Per-node handler. | ||
var handlerFuncPre = void 0; | ||
if (typeof handler[node.type] === 'function') { | ||
if (options.asNodes) { | ||
handler[node.type](node, parent, prop, index); | ||
} else { | ||
handlerFuncPre = handler[node.type]; | ||
} else if (typeof handler[node.type] === 'object' && typeof handler[node.type].pre === 'function') { | ||
handlerFuncPre = handler[node.type].pre; | ||
} | ||
if (handlerFuncPre) { | ||
if (nodePath) { | ||
// A path/node can be removed by some previous handler. | ||
if (!nodePath.isRemoved()) { | ||
var _handlerResult = handler[node.type](nodePath); | ||
var _handlerResult = handlerFuncPre.call(handler, nodePath); | ||
// Explicitly stop traversal. | ||
@@ -219,5 +232,7 @@ if (_handlerResult === false) { | ||
} | ||
} else { | ||
handlerFuncPre.call(handler, node, parent, prop, index); | ||
} | ||
} | ||
} | ||
} // Loop over handlers | ||
} catch (err) { | ||
@@ -238,4 +253,63 @@ _didIteratorError = true; | ||
}, | ||
// pre func | ||
/** | ||
* Handler on node exit. | ||
*/ | ||
post: function post(node, parent, prop, index) { | ||
if (!node) { | ||
return; | ||
} | ||
var nodePath = void 0; | ||
if (!options.asNodes) { | ||
nodePath = getPathFor(node, parent, prop, index); | ||
} | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
try { | ||
for (var _iterator2 = handlers[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var handler = _step2.value; | ||
// Per-node handler. | ||
var handlerFuncPost = void 0; | ||
if (typeof handler[node.type] === 'object' && typeof handler[node.type].post === 'function') { | ||
handlerFuncPost = handler[node.type].post; | ||
} | ||
if (handlerFuncPost) { | ||
if (nodePath) { | ||
// A path/node can be removed by some previous handler. | ||
if (!nodePath.isRemoved()) { | ||
var handlerResult = handlerFuncPost.call(handler, nodePath); | ||
// Explicitly stop traversal. | ||
if (handlerResult === false) { | ||
return false; | ||
} | ||
} | ||
} else { | ||
handlerFuncPost.call(handler, node, parent, prop, index); | ||
} | ||
} | ||
} // Loop over handlers | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
} | ||
}, | ||
// post func | ||
/** | ||
@@ -242,0 +316,0 @@ * Skip locations by default. |
{ | ||
"name": "regexp-tree", | ||
"version": "0.0.78", | ||
"version": "0.0.79", | ||
"license": "MIT", | ||
@@ -11,2 +11,3 @@ "description": "Regular Expressions parser in JavaScript", | ||
"build": "node scripts/build.js", | ||
"watch": "node scripts/build.js --watch", | ||
"test": "jest", | ||
@@ -13,0 +14,0 @@ "prepublish": "npm run build && npm test", |
@@ -66,2 +66,4 @@ # regexp-tree | ||
> NOTE: JS code transpilation is used to support older versions of Node. For faster development cycle you can use `npm run watch` command, which continuously transpiles JS code. | ||
### Usage as a CLI | ||
@@ -295,4 +297,15 @@ | ||
The [traverse](https://github.com/DmitrySoshnikov/regexp-tree/tree/master/src/traverse) module allows handling needed AST nodes using _visitor_ pattern. In Node the module is exposed as `regexpTree.traverse` method. Handlers receive an instance of [NodePath](https://github.com/DmitrySoshnikov/regexp-tree/blob/master/src/traverse/README.md#nodepath-class) class, which encapsulates `node` itself, its `parent` node, `property`, and `index` (in case if a node is a part of a collection). | ||
The [traverse](https://github.com/DmitrySoshnikov/regexp-tree/tree/master/src/traverse) module allows handling needed AST nodes using the _visitor_ pattern. In Node the module is exposed as the `regexpTree.traverse` method. Handlers receive an instance of the [NodePath](https://github.com/DmitrySoshnikov/regexp-tree/blob/master/src/traverse/README.md#nodepath-class) class, which encapsulates `node` itself, its `parent` node, `property`, and `index` (in case the node is part of a collection). | ||
Visiting a node follows this algorithm: | ||
- call `pre` handler. | ||
- recurse into node's children. | ||
- call `post` handler. | ||
For each node type of interest, you can provide either: | ||
- a function (`pre`). | ||
- an object with members `pre` and `post`. | ||
You can also provide a `*` handler which will be executed on every node. | ||
Example: | ||
@@ -306,5 +319,10 @@ | ||
// Handle nodes. | ||
// Traverse AST nodes. | ||
regexpTree.traverse(ast, { | ||
// Visit every node before any type-specific handlers. | ||
'*': function({node}) { | ||
... | ||
}, | ||
// Handle "Quantifier" node type. | ||
@@ -314,2 +332,13 @@ Quantifier({node}) { | ||
}, | ||
// Handle "Char" node type, before and after. | ||
Char: { | ||
pre({node}) { | ||
... | ||
}, | ||
post({node}) { | ||
... | ||
} | ||
} | ||
}); | ||
@@ -316,0 +345,0 @@ |
@@ -6,11 +6,29 @@ /** | ||
const colors = require('colors'); | ||
const shell = require('shelljs'); | ||
// Whether we're in the watch mode (continuous JS code transpiling). | ||
const watchMode = process.argv[2] || ''; | ||
let watchMsg = ''; | ||
if (watchMode) { | ||
watchMsg = ` (watch mode)`; | ||
} | ||
console.info(colors.bold(`Building${watchMsg}...\n`)); | ||
// ---------------------------------------------------------- | ||
// Rebuild parser. | ||
console.info(colors.bold('[1/3] Generating parser module...\n')); | ||
shell.exec(`node node_modules/syntax-cli/bin/syntax -g src/parser/regexp.bnf -o src/parser/generated/regexp-tree.js -m lalr1 --loc`); | ||
// Transform code for older Node versions. | ||
shell.exec(`node node_modules/.bin/babel ${process.argv[2] || ''} src/ --out-dir dist/ --ignore __tests__`); | ||
// ---------------------------------------------------------- | ||
// Git hooks. | ||
console.info(colors.bold('[2/3] Installing Git hooks...\n')); | ||
// Setup pre-commit hook. | ||
console.info(' - pre-commit: .git/hooks/pre-commit'); | ||
if (!shell.test('-f', '.git/hooks/pre-commit')) { | ||
@@ -21,4 +39,14 @@ shell.ln('-s', '../../scripts/git-pre-commit', '.git/hooks/pre-commit'); | ||
// Setup pre-push hook. | ||
console.info(' - pre-push: .git/hooks/pre-push\n'); | ||
if (!shell.test('-f', '.git/hooks/pre-push')) { | ||
shell.ln('-s', '../../scripts/git-pre-push', '.git/hooks/pre-push'); | ||
} | ||
} | ||
// ---------------------------------------------------------- | ||
// Transform code for older Node versions. | ||
console.info(colors.bold('[3/3] Transpiling JS code...\n')); | ||
shell.exec(`"node_modules/.bin/babel" ${process.argv[2] || ''} src/ --out-dir dist/ --ignore __tests__`); | ||
console.info(colors.bold('\nAll done.\n')); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
251299
5751
1930
0