expexp
Version:
The express model io and express model and data representation.
397 lines (376 loc) • 12.8 kB
JavaScript
function traverseType(path, json, afterFct, beforeFct, afterArr, beforeArr) {
beforeFct(json, path, -1)
path.push(json)
if ('bounds' in json) {
traverseBounds(path, json.bounds, afterFct, beforeFct, afterArr, beforeArr)
}
if ('spec' in json) {
if (json.t != 'string' && json.t != 'binary') {
traverseType(path, json.spec, afterFct, beforeFct, afterArr, beforeArr)
} else {
// For string and binary the bounds are called spec.
traverseBounds(path, json.spec, afterFct, beforeFct, afterArr, beforeArr)
}
}
path.pop() // json
afterFct(json, path, -1)
}
function traverseBounds(path, json, afterFct, beforeFct, afterArr, beforeArr) {
beforeFct(json, path, -1)
path.push(json)
if ('from' in json) {
traverseSimpleExpression(path, json.from, afterFct, beforeFct, afterArr, beforeArr)
}
if ('to' in json) {
traverseSimpleExpression(path, json.to, afterFct, beforeFct, afterArr, beforeArr)
}
path.pop() // json
afterFct(json, path, -1)
}
function traverseExpression(path, json, afterFct, beforeFct, afterArr, beforeArr) {
if (json) { // can be null (for local assignment)
beforeFct(json, path, -1)
path.push(json)
traverseSimpleExpression(path, json.arg0, afterFct, beforeFct, afterArr, beforeArr)
if (json.op) {
beforeFct(json.op, path, -1)
afterFct(json.op, path, -1)
}
if (json.arg1) {
traverseSimpleExpression(path, json.arg1, afterFct, beforeFct, afterArr, beforeArr)
}
path.pop()
afterFct(json, path, -1)
}
}
function traverseSimpleExpression(path, json, afterFct, beforeFct, afterArr, beforeArr) {
beforeArr(json, path, -1)
path.push(json)
for (const [i, too] of json.entries()) { // term or add_like_op
if (Array.isArray(too)) { // term is an array
beforeArr(too, path, i)
path.push(too)
for (const [j, fom] of too.entries()) { // factor or multiplication_like_op
beforeFct(fom, path, j)
path.push(fom)
if (fom.t == 'factor') {
traverseSimpleFactor(path, fom.arg0, afterFct, beforeFct, afterArr, beforeArr)
beforeArr(fom.quals0, path, -1)
path.push(fom.quals0)
for (const [k, q] of fom.quals0.entries()) {
traverseQualifier(path, k, q, afterFct, beforeFct, afterArr, beforeArr)
}
path.pop() // quals0
afterArr(fom.quals0, path, -1)
if (fom.arg1) {
traverseSimpleFactor(path, fom.arg1, afterFct, beforeFct, afterArr, beforeArr)
}
if (Array.isArray(fom.quals1)) {
beforeArr(fom.quals1, path, -1)
path.push(fom.quals1)
for (const [k, q] of fom.quals1.entries()) {
traverseQualifier(path, k, q, afterFct, beforeFct, afterArr, beforeArr)
}
path.pop() // fom.quals1
afterArr(fom.quals1, path, -1)
}
//} else { // multiplication_like_op (visited as fom)
}
path.pop() // fom
afterFct(fom, path, j)
}
path.pop() // too
afterArr(too, path, i)
} else { // add_like_op
beforeFct(too, path, i)
afterFct(too, path, i)
}
}
path.pop() // json
afterArr(json, path, -1)
}
function traverseSimpleFactor(path, json, afterFct, beforeFct, afterArr, beforeArr) {
beforeFct(json, path, -1)
path.push(json)
switch (json.t) {
case 'bifct':
case 'func_call':
case 'foeot': // Support also traversal of the original tree from the parser.
// if json is unfortunately an array it has a function named values
beforeArr(json.values, path, -1)
path.push(json.values)
for (const [i, vj] of json.values.entries()) {
traverseExpression(path, vj, afterFct, beforeFct, afterArr, beforeArr) // recur
}
path.pop() // json.values
afterArr(json.values, path, -1)
break
case 'parenthesis':
traverseExpression(path, json.expr, afterFct, beforeFct, afterArr, beforeArr)
break
case 'unary':
traverseSimpleFactor(path, json.arg, afterFct, beforeFct, afterArr, beforeArr)
beforeFct(json.op, path, -1)
afterFct(json.op, path, -1)
break
case 'aggr':
// has values like bifct and foeot but the elements are different
beforeArr(json.values, path, -1)
path.push(json.values)
for (const [i, vj] of json.values.entries()) {
traverseElement(path, i, vj, afterFct, beforeFct, afterArr, beforeArr)
}
path.pop() // json.values
afterArr(json.values, path, -1)
break
case 'query':
traverseSimpleExpression(path, json.src, afterFct, beforeFct, afterArr, beforeArr) // recur
traverseExpression(path, json.cond, afterFct, beforeFct, afterArr, beforeArr) // recur
break
case 'interval':
traverseSimpleExpression(path, json.argl, afterFct, beforeFct, afterArr, beforeArr) // recur
traverseSimpleExpression(path, json.arg, afterFct, beforeFct, afterArr, beforeArr) // recur
traverseSimpleExpression(path, json.argr, afterFct, beforeFct, afterArr, beforeArr) // recur
break
}
path.pop() // json
afterFct(json, path, -1)
}
function traverseQualifier(path, i, json, afterFct, beforeFct, afterArr, beforeArr) {
beforeFct(json, path, i)
if (json.t == 'idx_qual') {
path.push(json)
traverseSimpleExpression(path, json.idxStart, afterFct, beforeFct, afterArr, beforeArr) // recur
traverseSimpleExpression(path, json.idxEnd, afterFct, beforeFct, afterArr, beforeArr) // recur
path.pop() // json
}
afterFct(json, path, i)
}
function traverseElement(path, i, json, afterFct, beforeFct, afterArr, beforeArr) {
beforeFct(json, path, i)
path.push(json)
traverseExpression(path, json.arg, afterFct, beforeFct, afterArr, beforeArr)
traverseSimpleExpression(path, json.mult, afterFct, beforeFct, afterArr, beforeArr)
path.pop() // json
afterFct(json, path, i)
}
function traverseWhere(path, json, afterFct, beforeFct, afterArr, beforeArr) {
// The json is visited externally.
if ('wheres' in json) {
beforeArr(json.wheres, path, -1)
path.push(json.wheres)
for (const [i, wj] of json.wheres.entries()) {
beforeFct(wj, path, i)
path.push(wj)
traverseExpression(path, wj.expr, afterFct, beforeFct, afterArr, beforeArr)
beforeFct(wj.id, path, -1)
afterFct(wj.id, path, -1)
path.pop() // wj
afterFct(wj, path, i)
}
path.pop() // json.wheres
afterArr(json.wheres, path, -1)
}
}
function traverseContent(path, content, afterFct, beforeFct, afterArr, beforeArr) {
beforeArr(content, path, -1)
path.push(content)
for (const [i,json] of content.entries()) {
beforeFct(json, path, i)
path.push(json)
if ('spec' in json) {
path.push(json.spec)
if ('values' in json.spec) {
beforeArr(json.spec.values, path, -1)
path.push(json.spec.values)
for (const [k, vl] of json.spec.values.entries()) {
beforeFct(vl, path, k)
afterFct(vl, path, k)
}
path.pop() // json.spec.values
afterArr(json.spec.values, path, -1)
}
if ('refs' in json.spec) {
beforeArr(json.spec.refs, path, -1)
path.push(json.spec.refs)
for (const [k,ref] of json.spec.refs.entries()) {
beforeFct(ref, path, k)
afterFct(ref, path, k)
}
path.pop() // json.spec.refs
afterArr(json.spec.refs, path, -1)
}
path.pop() // json.spec
traverseType(path, json.spec, afterFct, beforeFct, afterArr, beforeArr)
}
// entity
if ('attrs' in json) {
beforeArr(json.attrs, path, -1)
path.push(json.attrs)
for (const [k,aj] of json.attrs.entries()) {
beforeFct(aj, path, k)
path.push(aj)
beforeArr(aj.ids, path, -1)
path.push(aj.ids)
for (const [l, ij] of aj.ids.entries()) {
beforeFct(ij, path, l)
afterFct(ij, path, l)
}
path.pop() // aj.ids
afterArr(aj.ids, path, -1)
traverseType(path, aj.type, afterFct, beforeFct, afterArr, beforeArr)
path.pop() // aj
afterFct(aj, path, k)
}
path.pop() // json.attrs
afterArr(json.attrs, path, -1)
}
if ('derives' in json) {
beforeArr(json.derives, path, -1)
path.push(json.derives)
for (const [k, dj] of json.derives.entries()) {
beforeFct(dj, path, k)
path.push(dj)
beforeFct(dj.id, path, -1)
if ('nttRef' in dj.id) {
path.push(dj.id)
beforeFct(dj.id.nttRef, path, -1)
afterFct(dj.id.nttRef, path, -1)
path.pop() // dj.id
}
afterFct(dj.id, path, -1)
traverseType(path, dj.type, afterFct, beforeFct, afterArr, beforeArr)
traverseExpression(path, dj.expr, afterFct, beforeFct, afterArr, beforeArr)
path.pop() // dj
afterFct(dj, path, k)
}
path.pop() // json.derives
afterArr(json.derives, path, -1)
}
if ('inverses' in json) {
beforeArr(json.inverses, path, -1)
path.push(json.inverses)
for (const [k, ij] of json.inverses.entries()) {
beforeFct(ij, path, k)
path.push(ij)
beforeFct(ij.id, path, -1)
afterFct(ij.id, path, -1)
traverseBounds(path, ij.aggrBnds, afterFct, beforeFct, afterArr, beforeArr)
beforeFct(ij.invRef, path, -1)
afterFct(ij.invRef, path, -1)
beforeFct(ij.nttRef, path, -1)
afterFct(ij.nttRef, path, -1)
path.pop() // ij
afterFct(ij, path, k)
}
path.pop() // json.inverses
afterArr(json.inverses, path, -1)
}
if ('uniques' in json) {
beforeArr(json.uniques, path, -1)
path.push(json.uniques)
for (const [k, uj] of json.uniques.entries()) {
beforeFct(uj, path, k)
path.push(uj)
beforeArr(uj.args, path, -1)
path.push(uj.args)
for (const [l, ua] of uj.args.entries()) {
beforeFct(ua, path, l)
path.push(ua)
// TODO also here recur into a qualifier chain
if ('nttRef' in ua && ua.nttRef) { // qual_attr
beforeFct(ua.nttRef, path, -1)
afterFct(ua.nttRef, path, -1)
}
path.pop() // ua
afterFct(ua, path, l)
}
path.pop() // uj.args
afterArr(uj.args, path, -1)
path.pop() // uj
afterFct(uj, path, k)
}
path.pop() // json.uniques
afterArr(json.uniques, path, -1)
}
traverseWhere(path, json, afterFct, beforeFct, afterArr, beforeArr) // entity or types where
// function or procedure
if ('params' in json) {
beforeArr(json.params, path, -1)
path.push(json.params)
for (const [k, pj] of json.params.entries()) {
beforeFct(pj, path, k)
path.push(pj)
beforeArr(pj.ids, path, -1)
path.push(pj.ids)
for (const [l, ij] of pj.ids.entries()) {
beforeFct(ij, path, l)
afterFct(ij, path, l)
}
path.pop() // pj.ids
afterArr(pj.ids, path, -1)
traverseType(path, pj.type, afterFct, beforeFct, afterArr, beforeArr)
path.pop() // pj
afterFct(pj, path, k)
}
path.pop() // json.params
afterArr(json.params, path, -1)
}
if ('locals' in json) {
beforeArr(json.locals, path, -1)
path.push(json.locals)
for (const [k,lj] of json.locals.entries()) {
beforeFct(lj, path, k)
path.push(lj)
beforeArr(lj.ids, path, -1)
path.push(lj.ids)
for (const [l,ij] of lj.ids.entries()) {
beforeFct(ij, path, l)
afterFct(ij, path, l)
}
path.pop() // lj.ids
afterArr(lj.ids, path, -1)
traverseType(path, lj.type, afterFct, beforeFct, afterArr, beforeArr)
traverseExpression(path, lj.expr, afterFct, beforeFct, afterArr, beforeArr)
path.pop() // lj
afterFct(lj, path, k)
}
path.pop() // json.locals
afterArr(json.locals, path, -1)
}
if ('result' in json) {
traverseType(path, json.result, afterFct, beforeFct, afterArr, beforeArr)
}
path.pop() // json
afterFct(json, path, i)
}
path.pop() // content
afterArr(content, path, -1)
}
const noOp = function(){}
function traverseContentExternal(content, afterFct, beforeFct = noOp, afterArr = noOp, beforeArr = noOp, path = []) {
traverseContent(path, content, afterFct, beforeFct, afterArr, beforeArr)
}
function traverseSimpleExpressionExternal(json, afterFct, beforeFct = noOp, afterArr = noOp, beforeArr = noOp, path = []) {
traverseSimpleExpression(path, json, afterFct, beforeFct, afterArr, beforeArr)
}
function traverseExpressionExternal(json, afterFct, beforeFct = noOp, afterArr = noOp, beforeArr = noOp, path = []) {
traverseExpression(path, json, afterFct, beforeFct, afterArr, beforeArr)
}
function traverseSimpleFactorExternal(content, afterFct, beforeFct = noOp, afterArr = noOp, beforeArr = noOp, path = []) {
traverseSimpleFactor(path, content, afterFct, beforeFct, afterArr, beforeArr)
}
function traverseTypeExternal(json, afterFct, beforeFct = noOp, afterArr = noOp, beforeArr = noOp, path = []) {
traverseType(path, json, afterFct, beforeFct, afterArr, beforeArr)
}
function traverseBoundsExternal(json, afterFct, beforeFct = noOp, afterArr = noOp, beforeArr = noOp, path = []) {
traverseBounds(path, json, afterFct, beforeFct, afterArr, beforeArr)
}
export {
traverseContentExternal as traverseContent,
traverseSimpleExpressionExternal as traverseSimpleExpression,
traverseExpressionExternal as traverseExpression,
traverseSimpleFactorExternal as traverseSimpleFactor,
traverseTypeExternal as traverseType,
traverseBoundsExternal as traverseBounds
}