All files lookup.ts

96.77% Statements 30/31
91.67% Branches 11/12
100% Functions 3/3
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67  4x       4x 39x 39x                           4x 16x   16x 16x     12x     12x       12x     12x     12x   9x 9x           3x       3x         3x       16x   4x  
import { Word, SuggestedPattern } from './types'
import { Node, Match } from './node'
import { Suggestion } from './suggestion'
 
 
export class LookupNode extends Node {
    constructor(alias: string, readonly contexts: Node[]) {
        super(alias)
    }
 
    /**
     * Given a sequence of tokens, returns a list of the greatest common nodes in a pattern
     * and their corresponding remainders (see [[Node.matchPattern]] and [[Match]] for details).
     * 
     * However, unlike [[Node.matchPattern]], this method attempts to resolve any results with
     * remainders at this contextual-level. That is, if a result from a `matchPattern` call on
     * a sub-context has remainders, this method will attempt to extend the match by trying to
     * match the remainder token sequence with the subsequent words in the pattern.
     *
     * @param tokens input tokens we wish to pattern match.
     */
    public matchPattern(tokens: Word[]): Match[] {
        let matches: Match[] = []
 
        for (const context of this.contexts) {
            for (const match of context.matchPattern(tokens)) {
                // TODO PUSH THE CURRENT LOOKUP NODE TO THE END INSTEAD OF REPLACING
                // get top-most node in call-stack (i.e. least deep context)
                const node = match.nodes[match.nodes.length - 1]
 
                // was the matched node the end of a pattern?
                const isTerminalMatch: boolean = node.end
 
                // if the sub-context matched on a terminal node and it is a leaf node,
                // pop it off the call-stack.
                if (isTerminalMatch && node.isLeaf()) match.nodes.pop()
 
                // push this lookup node as the top-most node in the stack
                match.nodes.push(this)
 
                // complete match in sub-context. (tokens exhuasted)
                if (match.remainder.length === 0) {
                    // if the sub-context matched on a terminal node,
                    matches.push(match)
                    continue
                }
 
                // a remiander exists.
 
                // if it was not a terminal match in the sub-context, a match is impossible
                Iif (!isTerminalMatch) continue
 
                // the match was on a pattern terminal in the sub-context and this lookup node is
                // itself a terminal. the remainder may be able to be matched at a the context above.
                if (this.end) matches.push(match)
 
                // attempt to resolve a little more of the remainder on this contextual level.
                // even if this node is a terminal, it could have a continued pattern that we
                // could potentially match with.
                matches = matches.concat(super.matchPattern(match.remainder))
            }
        }
 
        return matches
    }
}