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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | 15x 15x 15x 1530x 1530x 1530x 1530x 1530x 100408x 100408x 100408x 1444x 1444x 1444x 98964x 109291x 109291x 109291x 107177x 8032x 8032x 99145x 86x 15x 109291x 109291x 109291x 109291x 9840x 1485x 1356x 1356x 1356x 9840x 99451x 14567x 14567x 4480x 4480x 1295x 3185x 4480x 4480x 109291x 15458x 93833x 109291x 109291x 107177x 93833x 79351x 14482x 93833x 93833x 13344x 13344x 5312x 5312x 5312x 5312x 8032x 1444x 1444x 1444x 42141x 37410x 37410x 4670x 4670x 37410x 42141x 42141x 1444x 1444x | import isProblem from "../../utils/isProblem"; import isStr from "../../preds/isStr"; export default function simulate( nfa, rawInput, walkFn, walkOpts ) { var r: any = { matched: false, chain: null, }; const inputType = typeof rawInput; var initial = { state: 0, offset: 0, input: [ rawInput ], groupCount: 0, arrayed: false }; var frontier = [ initial ]; while ( frontier.length > 0 ) { var current = frontier.shift(); const { offset: currentOffset, input } = current; if ( current.state === nfa.finalState && currentOffset === input.length ) { r.matched = true; r.chain = _getChain( nfa, current, inputType ); return r; } for ( var nextStateStr in nfa.transitions[ current.state ] ) { var nextState = parseInt( nextStateStr ); var m = _getNextMove( nfa, nextState, current, walkFn, walkOpts ); if ( m ) { if ( m.isProblem ) { let { name, problem, position } = m; r.lastProblem = { name, problem, position }; } else { frontier.push( m ); } } } } return r; } function _getNextMove( nfa, nextState, current, walkFn, walkOpts ) { var { input, offset: currentOffset, groupCount, arrayed } = current; var observed = input[ currentOffset ]; var transition = nfa.transitions[ current.state ][ nextState ]; if ( transition.group === 'in' ) { if ( groupCount === 0 ) { if ( Array.isArray( input[ 0 ] ) || isStr( input [ 0 ] ) ) { input = input[ 0 ]; currentOffset = 0; arrayed = true; } } groupCount += 1; } else if ( transition.group === 'out' ) { groupCouEnt -= 1; if ( groupCount === 0 ) { if ( arrayed ) { if ( currentOffset === input.length ) { currentOffset = 1; } else { currentOffset = 0; } input = [ input ]; } arrayed = false; } } var nextOffset; var move; if ( !transition.isEpsilon ) { nextOffset = currentOffset + 1; } else { nextOffset = currentOffset; } var validateResult, next; var name = transition.name || current.move && current.move.name; if ( nextOffset <= input.length ) { if ( transition.isEpsilon ) { if ( transition.dir ) { move = { dir: transition.dir, name: transition.name, op: transition.op, group: transition.group }; } else { move = null; } next = { input, groupCount, arrayed, state: nextState, offset: nextOffset, move: move, clause: transition, prev: current, isEpsilon: true, }; return next; } else { validateResult = walkFn( transition, observed, walkOpts ); //E validateResult = walkFn(transition, observed, walkOpts); if ( !isProblem( validateResult ) ) { if ( currentOffset < input.length ) { move = { dir: 'clause' }; next = { input, groupCount, arrayed, state: nextState, offset: nextOffset, move: move, prev: current, isEpsilon: false, clause: transition, guide: validateResult, }; return next; } } else { return { isProblem: true, problem: validateResult, name: name, position: currentOffset }; } } } } function _getChain( nfa, finalState, inputType ) { var chain: any = []; var curr = finalState; var prev; while ( curr ) { if ( !prev || ( curr.state !== prev.state ) && curr.move ) { var o: any = { isEpsilon: curr.isEpsilon, move: curr.move, state: curr.state, }; if ( !curr.isEpsilon ) { o.guide = curr.guide; o.clause = curr.clause; } chain.unshift( o ); } prev = curr; curr = curr.prev; } chain.inputType = inputType; return chain; } |