import { Node } from './latex_parser_types' ; import { find , findAll , getChildNodes } from './find_all' ; import type { Typeguard } from './find_all' ; /**
 * A matcher result.
 */ export type MatchResult < T extends Node , P extends Pattern < Node , any > | undefined > = { /**
     * The matched node.
     */ node : T ; /**
     * The parent node of the matched node.
     */ parent : P extends undefined ? undefined : MatchResult < NonNullable < P > [ 'target' ] , NonNullable < P > [ 'parentPattern' ] > ; } ; export type MatchOptions = { /**
     * If `true`, the pattern matching can begin within child nodes given
     * to  Pattern . match and  Pattern . matchAll .
     *
     *  default example example traverseAll : boolean ; } ; example export class Pattern < T extends Node , ParentPattern extends Pattern < Node , any > | undefined = undefined > { /**
     * Type guard to check whether nodes match.
     */ readonly typeguard : Typeguard < T > ; /**
     * Parent pattern.
     */ readonly parentPattern : ParentPattern ; ignore target : T ; ignore constructor ( typeguard , parentPattern ) { this . typeguard = typeguard ; this . parentPattern = parentPattern ; } param typeguard child < C extends Node > ( typeguard ) ; param typeguard child ( typeguard ) ; child ( typeguard ) { const childMatcher = new Pattern ( typeguard , this ) ; return childMatcher ; } /**
     * Returns a node in the child nodes if matched. Returns `undefined` if not matched.
     * Its parent node must match its  parentPattern .
     *
     *  param nodes param opt match ( nodes , opt = { traverseAll : false } ) { if ( ! this . parentPattern ) { if ( opt . traverseAll ) { const result = find ( nodes , this . typeguard ) ; if ( result ) { return { node : result . node , parent : undefined as any } ; } } else { for ( const node of nodes ) { if ( this . typeguard ( node ) ) { return { node , parent : undefined as any } ; } } } } else { const parentMatchResults = this . parentPattern . matchAll ( nodes , opt ) ; for ( const parentMatchResult of parentMatchResults ) { const parentNode = parentMatchResult . node ; const childNodes = getChildNodes ( parentNode ) ; for ( const node of childNodes ) { if ( this . typeguard ( node ) ) { return { node , parent : parentMatchResult as any } ; } } } } return undefined ; } /**
     * Returns the array of all the matched node. Returns an empty array if not matched.
     * Their parent node must match  parentPattern .
     *  param nodes param opt matchAll ( nodes , opt = { traverseAll : false } ) { const ret = [ ] ; if ( ! this . parentPattern ) { if ( opt . traverseAll ) { const results = findAll ( nodes , this . typeguard ) ; for ( const result of results ) { ret . push ( { node : result . node , parent : undefined as any } ) ; } } else { for ( const node of nodes ) { if ( this . typeguard ( node ) ) { ret . push ( { node , parent : undefined as any } ) ; } } } } else { const parentMatchResults = this . parentPattern . matchAll ( nodes , opt ) ; for ( const parentMatchResult of parentMatchResults ) { const parentNode = parentMatchResult . node ; const childNodes = getChildNodes ( parentNode ) ; for ( const node of childNodes ) { if ( this . typeguard ( node ) ) { ret . push ( { node , parent : parentMatchResult as any } ) ; } } } } return ret ; } } param typeguard export function pattern < T extends Node > ( typeguard ) ; param typeguard export function pattern ( typeguard ) ; export function pattern ( typeguard ) { return new Pattern ( typeguard , undefined ) ; }