Skip to content

Instantly share code, notes, and snippets.

@nadrane
Created December 11, 2017 21:36
Show Gist options
  • Save nadrane/eca5de5ed52c3c0d2632626fcfc6a163 to your computer and use it in GitHub Desktop.
Save nadrane/eca5de5ed52c3c0d2632626fcfc6a163 to your computer and use it in GitHub Desktop.
A very simple regular expression engine
//A walkthrough of this solution exists here: https://nickdrane.com/build-your-own-regex/
function matchOne(pattern, text) {
if (!pattern) return true;
if (!text) return false;
return pattern === "." || text === pattern;
}
function search(pattern, text) {
if (pattern[0] === "^") {
return match(pattern.slice(1), text);
} else {
return match(".*" + pattern, text);
}
}
function match(pattern, text) {
if (!pattern) return true;
else if (!text && pattern === "$") return true;
else if (pattern[1] === "?") {
return matchQuestion(pattern, text);
} else if (pattern[1] === "*") {
return matchStar(pattern, text);
} else if (pattern[0] === "(") {
return matchGroup(pattern, text);
} else {
return matchOne(pattern[0], text[0]) && match(pattern.slice(1), text.slice(1));
}
}
function matchQuestion(pattern, text) {
return (
(matchOne(pattern[0], text[0]) && match(pattern.slice(2), text.slice(1))) ||
match(pattern.slice(2), text)
);
}
function matchStar(pattern, text) {
return (
(matchOne(pattern[0], text[0]) && match(pattern, text.slice(1))) ||
match(pattern.slice(2), text)
);
}
// Does not support nested groups
function matchGroup(pattern, text) {
const groupEnd = pattern.indexOf(")");
const groupPattern = pattern.slice(1, groupEnd);
if (pattern[groupEnd + 1] === "?") {
const remainderPattern = pattern.slice(groupEnd + 2); // +2 needed to slice off the ')?'
return (
(match(groupPattern, text.slice(0, groupPattern.length)) &&
match(remainderPattern, text.slice(groupPattern.length))) ||
match(remainderPattern, text)
);
} else if (pattern[groupEnd + 1] === "*") {
const remainderPattern = pattern.slice(groupEnd + 2); // +2 needed to slice off the ')*'
return (
(match(groupPattern, text.slice(0, groupPattern.length)) &&
match(pattern, text.slice(groupPattern.length))) ||
match(remainderPattern, text)
);
} else {
const remainderPattern = pattern.slice(groupEnd + 1); // +1 needed to slice off the ')'
return (
match(groupPattern, text.slice(0, groupPattern.length)) &&
match(remainderPattern, text.slice(groupPattern.length))
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment