import * as AST from "./ast" ; export function visit ( ast , callback ) { let queue = ast . body . map ( ( node , index ) => ( { node , nodeList : ast . body , index , parent : ast , } ) ) ; while ( queue . length !== 0 ) { const { node , nodeList , index , parent } = queue . shift ( ) ! ; callback ( node , nodeList , index , parent ) ; if ( node . type === "group" || node . type === "lookAroundAssertion" ) { queue = queue . concat ( node . children . map ( ( child , index ) => ( { node : child , nodeList : node . children , index , parent : node , } ) ) ) ; } if ( node . type === "choice" ) { const branches = node . branches ; for ( let i = 0 ; i < branches . length ; i ++ ) { const branch = branches [ i ] ; queue = queue . concat ( branch . map ( ( child , index ) => ( { node : child , nodeList : branch , index , parent : node , } ) ) ) ; } } } } export function getNodeById ( ast , id ) { const { body } = ast ; let queue = body . map ( ( node , index ) => ( { node , parent : ast , nodeList : body , index , } ) ) ; while ( queue . length !== 0 ) { const item = queue . shift ( ) ! ; const { node } = item ; if ( node . id === id ) { return item ; } if ( node . type === "group" || node . type === "lookAroundAssertion" ) { const { children } = node ; queue = queue . concat ( children . map ( ( cur , index ) => ( { node : cur , parent : node , nodeList : children , index , } ) ) ) ; } if ( node . type === "choice" ) { const branches = node . branches ; for ( let i = 0 ; i < branches . length ; i ++ ) { const branch = branches [ i ] ; queue = queue . concat ( branch . map ( ( cur , index ) => ( { node : cur , parent : node , nodeList : branch , index , } ) ) ) ; } } } throw new Error ( "unreachable" ) ; } export function getNodesByIds ( ast , ids ) { const { parent , nodeList , index } = getNodeById ( ast , ids [ 0 ] ) ; return { nodes : nodeList . slice ( index , index + ids . length ) , parent , nodeList , index , } ; }