Skip to content

Commit

Permalink
pass current path to enter/leave callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinbarabash committed Jun 11, 2017
1 parent 283fdfe commit b582cc7
Show file tree
Hide file tree
Showing 5 changed files with 960 additions and 47 deletions.
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: node_js
node_js:
- "node"
notifications:
email: false
script:
- npm test
81 changes: 81 additions & 0 deletions lib/__test__/traverse.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import assert from 'assert'

import traverse from '../traverse'

describe('traverse', () => {
it('should pass the current path to enter and leave', () => {
const ast = {
type: 'Apply',
op: 'add',
args: [{
type: 'Number',
value: '5',
}, {
type: 'Identifier',
name: 'a',
}]
}

let enterPath = []
let leavePath = []

traverse(ast, {
enter(node, path) {
if (node.value === '5') {
enterPath = path
}
},
leave(node, path) {
if (node.name === 'a') {
leavePath = path
}
}
})

assert.deepEqual(enterPath, ['args', 0])
assert.deepEqual(leavePath, ['args', 1])
})

it('should pass the current path to enter and leave', () => {
const ast = {
type: 'Apply',
op: 'add',
args: [{
type: 'Apply',
op: 'add',
args: [
{
type: 'Number',
value: '5',
},
{
type: 'Number',
value: '10',
},
],
}, {
type: 'Identifier',
name: 'a',
}]
}

let enterPath = []
let leavePath = []

traverse(ast, {
enter(node, path) {
if (node.value === '5') {
enterPath = path
}
},
leave(node, path) {
if (node.value === '10') {
leavePath = path
}
}
})

assert.deepEqual(enterPath, ['args', 0, 'args', 0])
assert.deepEqual(leavePath, ['args', 0, 'args', 1])
})
})
37 changes: 20 additions & 17 deletions lib/traverse.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,51 @@
* traverse - walk all of the nodes in a tree.
*/

function traverse(node, {enter = () => {}, leave = () => {}}) {
function traverse(node, {enter = () => {}, leave = () => {}}, path = []) {
switch (node.type) {
// regular non-leaf nodes
case 'Apply':
enter(node)
node.args.forEach((arg) => traverse(arg, {enter, leave}))
leave(node)
enter(node, path)
node.args.forEach((arg, index) =>
traverse(arg, {enter, leave}, [...path, 'args', index]))
leave(node, path)
break

// leaf nodes
case 'Identifier':
case 'Number':
case 'Ellipsis':
enter(node)
leave(node)
enter(node, path)
leave(node, path)
break

// irregular non-leaf nodes
case 'Parentheses':
enter(node)
traverse(node.body, {enter, leave})
leave(node)
enter(node, path)
traverse(node.body, {enter, leave}, [...path, 'body'])
leave(node, path)
break

case 'List':
case 'Sequence':
enter(node)
node.items.forEach((item) => traverse(item, {enter, leave}))
leave(node)
enter(node, path)
node.items.forEach((item, index) =>
traverse(item, {enter, leave}, [...path, 'items', index]))
leave(node, path)
break

case 'System':
enter(node)
node.relations.forEach((rel) => traverse(rel, { enter, leave }))
leave(node)
enter(node, path)
node.relations.forEach((rel, index) =>
traverse(rel, {enter, leave}, [...path, 'relations', index]))
leave(node, path)
break

case 'Placeholder':
// TODO(kevinb) handle children of the placeholder
// e.g. we there might #a_0 could match x_0, y_0, z_0, etc.
enter(node)
leave(node)
enter(node, path)
leave(node, path)
break

default:
Expand Down
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "math-traverse",
"version": "0.2.1",
"version": "0.2.2",
"description": "Library for traversing and replacing nodes in a math-ast AST",
"main": "dist/math-traverse.js",
"scripts": {
"prepublish": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "jest"
},
"repository": "git+https://github.com/semantic-math/math-traverse.git",
"author": "Kevin Barabash <[email protected]>",
Expand All @@ -16,8 +16,17 @@
"homepage": "https://github.com/semantic-math/math-traverse#readme",
"devDependencies": {
"babel-core": "^6.24.1",
"babel-jest": "^20.0.3",
"babel-loader": "^7.0.0",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"jest": "^20.0.4",
"webpack": "^2.4.1"
},
"jest": {
"setupTestFrameworkScriptFile": "<rootDir>/node_modules/babel-polyfill/dist/polyfill.js",
"transform": {
"^.+\\.jsx?$": "babel-jest"
}
}
}
Loading

0 comments on commit b582cc7

Please sign in to comment.