A better version of regex 101
made a much simpler parser
3 files changed, +88 -1
+49-0rec.js
| @@ -0,0 +1,49 @@ | ||
| 1 | +let sample = `a:b | |
| 2 | +\tc:d | |
| 3 | +\t:w | |
| 4 | +\t\te:n | |
| 5 | +:w | |
| 6 | +g:h`; | |
| 7 | + | |
| 8 | +// split data by lines | |
| 9 | +const parseBuilder = (str) => { | |
| 10 | + let lines = str.split("\n"); | |
| 11 | + const ref = {}; | |
| 12 | + for (let line of lines) { | |
| 13 | + const lineData = | |
| 14 | + /^(?<tabs>\s*)(?<name>\w*)(?<optional>\??):(?<regex>.*)/.exec( | |
| 15 | + line | |
| 16 | + ).groups; | |
| 17 | + const tabs = lineData.tabs.length; | |
| 18 | + if (!ref[tabs]) ref[tabs] = [lineData]; | |
| 19 | + else ref[tabs].push(lineData); | |
| 20 | + if (tabs) { | |
| 21 | + const parentRefInd = ref[tabs - 1].length - 1; | |
| 22 | + let parent = ref[tabs - 1][parentRefInd]; | |
| 23 | + if (!parent.children) parent.children = [lineData]; | |
| 24 | + else parent.children.push(lineData); | |
| 25 | + } | |
| 26 | + } | |
| 27 | + return ref[0]; | |
| 28 | +}; | |
| 29 | + | |
| 30 | +const buildToRegex = (build) => { | |
| 31 | + const re = buildToRegexRecursion(build, ""); | |
| 32 | + return re; | |
| 33 | +}; | |
| 34 | + | |
| 35 | +const buildToRegexRecursion = (build, re) => { | |
| 36 | + if (!build?.length) return re; | |
| 37 | + const val = build.shift(); | |
| 38 | + if (val.name) re += `(?P<${val.name}>${val.regex}`; | |
| 39 | + else re += `(?:${val.regex}`; | |
| 40 | + if (val.children) re += buildToRegexRecursion(val.children, ""); | |
| 41 | + re += `${val.optional})`; | |
| 42 | + | |
| 43 | + return buildToRegexRecursion(build, re); | |
| 44 | +}; | |
| 45 | + | |
| 46 | +const d = parseBuilder(sample); | |
| 47 | + | |
| 48 | +const b = buildToRegex(d); | |
| 49 | +console.log(b); |
+3-1src/App.jsx
| @@ -10,13 +10,15 @@ group1Delim:\\n | ||
| 10 | 10 | |
| 11 | 11 | const buildToRegex = (build) => { |
| 12 | 12 | const re = buildToRegexRecursion(build, ""); |
| 13 | + console.log(re); | |
| 13 | 14 | return re; |
| 14 | 15 | }; |
| 15 | 16 | |
| 16 | 17 | const buildToRegexRecursion = (build, re) => { |
| 17 | 18 | if (!build?.length) return re; |
| 18 | 19 | const val = build.shift(); |
| 19 | - re += `(?P<${val.name}>${val.regex}`; | |
| 20 | + if (val.name) re += `(?P<${val.name}>${val.regex}`; | |
| 21 | + else re += `(?:${val.regex}`; | |
| 20 | 22 | if (val.children) re += buildToRegexRecursion(val.children, ""); |
| 21 | 23 | re += `${val.optional})`; |
| 22 | 24 |
+36-0src/builder.js
| @@ -0,0 +1,36 @@ | ||
| 1 | +export const parseBuilder = (str) => { | |
| 2 | + let lines = str.split("\n"); | |
| 3 | + const ref = {}; | |
| 4 | + for (let line of lines) { | |
| 5 | + const lineData = | |
| 6 | + /^(?<tabs>\s*)(?<name>\w*)(?<optional>\??):(?<regex>.*)/.exec( | |
| 7 | + line | |
| 8 | + ).groups; | |
| 9 | + const tabs = lineData.tabs.length; | |
| 10 | + if (!ref[tabs]) ref[tabs] = [lineData]; | |
| 11 | + else ref[tabs].push(lineData); | |
| 12 | + if (tabs) { | |
| 13 | + const parentRefInd = ref[tabs - 1].length - 1; | |
| 14 | + let parent = ref[tabs - 1][parentRefInd]; | |
| 15 | + if (!parent.children) parent.children = [lineData]; | |
| 16 | + else parent.children.push(lineData); | |
| 17 | + } | |
| 18 | + } | |
| 19 | + return ref[0]; | |
| 20 | +}; | |
| 21 | + | |
| 22 | +export const buildToRegex = (build) => { | |
| 23 | + const re = buildToRegexRecursion(build, ""); | |
| 24 | + return re; | |
| 25 | +}; | |
| 26 | + | |
| 27 | +const buildToRegexRecursion = (build, re) => { | |
| 28 | + if (!build?.length) return re; | |
| 29 | + const val = build.shift(); | |
| 30 | + if (val.name) re += `(?P<${val.name}>${val.regex}`; | |
| 31 | + else re += `(?:${val.regex}`; | |
| 32 | + if (val.children) re += buildToRegexRecursion(val.children, ""); | |
| 33 | + re += `${val.optional})`; | |
| 34 | + | |
| 35 | + return buildToRegexRecursion(build, re); | |
| 36 | +}; |