Mirror: The magical sticky regex-based parser generator 🧙

Remove special logic for "+" quantifier

Instead it'll generate code for `${x} ${x}*` on the fly.

+38 -49
+33 -29
src/babel/__snapshots__/plugin.test.js.snap
··· 185 185 break alt_3; 186 186 } 187 187 188 - loop_3: for (var j3 = 0; 1; j3++) { 188 + if ((x = _node_expression3(state)) != null) {} else { 189 + state.y = y1; 190 + state.x = x1; 191 + node.length = ln2; 192 + return; 193 + } 194 + 195 + loop_3: for (;;) { 189 196 var y3 = state.y, 190 197 x3 = state.x; 191 198 192 199 if ((x = _node_expression3(state)) != null) {} else { 193 - if (j3) { 194 - state.y = y3; 195 - state.x = x3; 196 - break loop_3; 197 - } else {} 198 - 199 - state.y = y1; 200 - state.x = x1; 201 - node.length = ln2; 202 - return; 200 + state.y = y3; 201 + state.x = x3; 202 + break loop_3; 203 203 } 204 204 } 205 205 } ··· 269 269 var y2 = state.y, 270 270 x2 = state.x; 271 271 272 - loop_2: for (var j2 = 0; 1; j2++) { 272 + if ((x = _node_expression(state)) != null) { 273 + node.push(x); 274 + } else { 275 + state.y = y2; 276 + state.x = x2; 277 + break block_2; 278 + } 279 + 280 + loop_2: for (;;) { 273 281 var y2 = state.y, 274 282 x2 = state.x; 275 283 276 284 if ((x = _node_expression(state)) != null) { 277 285 node.push(x); 278 286 } else { 279 - if (j2) { 280 - state.y = y2; 281 - state.x = x2; 282 - break loop_2; 283 - } else {} 284 - 285 287 state.y = y2; 286 288 state.x = x2; 287 - break block_2; 289 + break loop_2; 288 290 } 289 291 } 290 292 291 293 break alt_2; 292 294 } 293 295 294 - loop_2: for (var j2 = 0; 1; j2++) { 296 + if ((x = _node_expression2(state)) != null) { 297 + node.push(x); 298 + } else { 299 + state.y = y1; 300 + state.x = x1; 301 + return; 302 + } 303 + 304 + loop_2: for (;;) { 295 305 var y2 = state.y, 296 306 x2 = state.x; 297 307 298 308 if ((x = _node_expression2(state)) != null) { 299 309 node.push(x); 300 310 } else { 301 - if (j2) { 302 - state.y = y2; 303 - state.x = x2; 304 - break loop_2; 305 - } else {} 306 - 307 - state.y = y1; 308 - state.x = x1; 309 - return; 311 + state.y = y2; 312 + state.x = x2; 313 + break loop_2; 310 314 } 311 315 } 312 316
+5 -20
src/codegen.js
··· 35 35 if ((${_match} = ${ast.expression.id}(${_state})) != null) { 36 36 ${capture ? js`${_node}.push(${_match})` : ''} 37 37 } else { 38 - ${opts.onAbort} 39 38 ${restoreIndex(opts.index)} 40 39 ${restoreLength} 41 40 ${opts.abort} ··· 64 63 ast.expression ? astExpression(ast, depth, opts) : astGroup(ast, depth, opts); 65 64 66 65 const astQuantifier = (ast, depth, opts) => { 67 - const { index, abort, onAbort } = opts; 66 + const { index, abort } = opts; 68 67 const invert = `inv_${depth}`; 69 68 const loop = `loop_${depth}`; 70 - const count = `j${depth}`; 71 69 72 70 opts = copy(opts); 73 71 if (ast.capture === '!') { ··· 77 75 78 76 let child; 79 77 if (ast.quantifier === '+') { 80 - opts.onAbort = js` 81 - if (${count}) { 82 - ${restoreIndex(depth)} 83 - break ${loop}; 84 - } else { 85 - ${onAbort} 86 - } 87 - `; 88 - 78 + const starAst = copy(ast); 79 + starAst.quantifier = '*'; 89 80 child = js` 90 - ${loop}: for (var ${count} = 0; 1; ${count}++) { 91 - ${assignIndex(depth)} 92 - ${astChild(ast, depth, opts)} 93 - } 81 + ${astChild(ast, depth, opts)} 82 + ${astQuantifier(starAst, depth, opts)} 94 83 `; 95 84 } else if (ast.quantifier === '*') { 96 85 opts.length = 0; 97 86 opts.index = depth; 98 87 opts.abort = js`break ${loop};`; 99 - opts.onAbort = ''; 100 88 101 89 child = js` 102 90 ${loop}: for (;;) { ··· 107 95 } else if (ast.quantifier === '?') { 108 96 opts.index = depth; 109 97 opts.abort = ''; 110 - opts.onAbort = ''; 111 98 112 99 child = js` 113 100 ${assignIndex(depth)} ··· 149 136 childOpts = copy(opts); 150 137 childOpts.index = depth; 151 138 childOpts.abort = js`break ${block};`; 152 - childOpts.onAbort = ''; 153 139 } 154 140 155 141 let sequence = ''; ··· 188 174 ${astSequence(ast, 2, { 189 175 index: 1, 190 176 length: 0, 191 - onAbort: '', 192 177 abort: js`return;`, 193 178 capture: true, 194 179 })}