Mirror: The magical sticky regex-based parser generator 🧙
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge quantifiers into astQuantifier() and simplify opts

+61 -92
+61 -92
src/codegen.js
··· 9 9 return body.trim(); 10 10 } 11 11 12 - const makeOpts = (prev, next) => { 13 - const output = {}; 14 - for (const key in prev) output[key] = prev[key]; 15 - for (const key in next) output[key] = next[key]; 16 - return output; 12 + const copy = (prev) => { 13 + const next = {}; 14 + for (const key in prev) next[key] = prev[key]; 15 + return next; 17 16 }; 18 17 19 18 const assignIndex = (depth) => ··· 66 65 const astGroup = (ast, depth, opts) => { 67 66 const capture = !!opts.capture && !ast.capture; 68 67 68 + opts = copy(opts); 69 + opts.capture = capture; 70 + 69 71 let group = ''; 70 72 if (!opts.length && capture) { 73 + opts.length = depth; 71 74 return js` 72 75 ${js`var length_${depth} = ${_node}.length;`} 73 - ${astSequence( 74 - ast.sequence, 75 - depth + 1, 76 - makeOpts(opts, { 77 - length: depth, 78 - capture, 79 - }) 80 - )} 76 + ${astSequence(ast.sequence, depth + 1, opts)} 81 77 `; 82 78 } 83 79 84 - return astSequence( 85 - ast.sequence, 86 - depth + 1, 87 - makeOpts(opts, { 88 - capture, 89 - }) 90 - ); 80 + return astSequence(ast.sequence, depth + 1, opts); 91 81 }; 92 82 93 83 const astChild = (ast, depth, opts) => 94 84 ast.expression ? astExpression(ast, depth, opts) : astGroup(ast, depth, opts); 95 85 96 - const astRepeating = (ast, depth, opts) => { 97 - const label = `loop_${depth}`; 86 + const astQuantifier = (ast, depth, opts) => { 87 + const { index, abort, onAbort } = opts; 88 + const invert = `invert_${depth}`; 89 + const loop = `loop_${depth}`; 98 90 const count = `count_${depth}`; 99 - return js` 100 - ${label}: for (var ${count} = 0; true; ${count}++) { 101 - ${assignIndex(depth)} 102 - ${astChild( 103 - ast, 104 - depth, 105 - makeOpts(opts, { 106 - onAbort: js` 107 - if (${count}) { 108 - ${restoreIndex(depth)} 109 - break ${label}; 110 - } else { 111 - ${opts.onAbort || ''} 112 - } 113 - `, 114 - }) 115 - )} 116 - } 117 - `; 118 - }; 119 91 120 - const astMultiple = (ast, depth, opts) => { 121 - const label = `loop_${depth}`; 122 - return js` 123 - ${label}: while (true) { 124 - ${assignIndex(depth)} 125 - ${astChild( 126 - ast, 127 - depth, 128 - makeOpts(opts, { 129 - length: 0, 130 - index: depth, 131 - abort: js`break ${label};`, 132 - onAbort: '', 133 - }) 134 - )} 135 - } 136 - `; 137 - }; 138 - 139 - const astOptional = (ast, depth, opts) => js` 140 - ${assignIndex(depth)} 141 - ${astChild( 142 - ast, 143 - depth, 144 - makeOpts(opts, { 145 - index: depth, 146 - abort: '', 147 - onAbort: '', 148 - }) 149 - )} 150 - `; 151 - 152 - const astQuantifier = (ast, depth, opts) => { 153 - const { index, abort } = opts; 154 - const label = `invert_${depth}`; 155 - 92 + opts = copy(opts); 156 93 if (ast.capture === '!') { 157 - opts = makeOpts(opts, { 158 - index: depth, 159 - abort: js`break ${label};`, 160 - }); 94 + opts.index = depth; 95 + opts.abort = js`break ${invert}`; 161 96 } 162 97 163 98 let child; 164 99 if (ast.quantifier === '+') { 165 - child = astRepeating(ast, depth, opts); 166 - } else if (ast.quantifier === '*') child = astMultiple(ast, depth, opts); 167 - else if (ast.quantifier === '?') child = astOptional(ast, depth, opts); 168 - else child = astChild(ast, depth, opts); 100 + opts.onAbort = js` 101 + if (${count}) { 102 + ${restoreIndex(depth)} 103 + break ${loop}; 104 + } else { 105 + ${onAbort} 106 + } 107 + `; 108 + 109 + child = js` 110 + ${loop}: for (var ${count} = 0; true; ${count}++) { 111 + ${assignIndex(depth)} 112 + ${astChild(ast, depth, opts)} 113 + } 114 + `; 115 + } else if (ast.quantifier === '*') { 116 + opts.length = 0; 117 + opts.index = depth; 118 + opts.abort = js`break ${loop};`; 119 + opts.onAbort = ''; 120 + 121 + child = js` 122 + ${loop}: while (true) { 123 + ${assignIndex(depth)} 124 + ${astChild(ast, depth, opts)} 125 + } 126 + `; 127 + } else if (ast.quantifier === '?') { 128 + opts.index = depth; 129 + opts.abort = ''; 130 + opts.onAbort = ''; 131 + 132 + child = js` 133 + ${assignIndex(depth)} 134 + ${astChild(ast, depth, opts)} 135 + `; 136 + } else { 137 + child = astChild(ast, depth, opts); 138 + } 169 139 170 140 if (ast.capture === '!') { 171 141 return js` 172 - ${label}: { 142 + ${invert}: { 173 143 ${assignIndex(depth)} 174 144 ${child} 175 145 ${restoreIndex(index)} ··· 196 166 197 167 let childOpts = opts; 198 168 if (ast.alternation) { 199 - childOpts = makeOpts(opts, { 200 - index: depth, 201 - abort: js`break ${block};`, 202 - onAbort: '', 203 - }); 169 + childOpts = copy(opts); 170 + childOpts.index = depth; 171 + childOpts.abort = js`break ${block};`; 172 + childOpts.onAbort = ''; 204 173 } 205 174 206 175 let sequence = '';