Skip to content

Instantly share code, notes, and snippets.

@raganwald
Last active November 10, 2018 19:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raganwald/d5005beb167f075f2c90898143f4e116 to your computer and use it in GitHub Desktop.
Save raganwald/d5005beb167f075f2c90898143f4e116 to your computer and use it in GitHub Desktop.
Balanced parentheses via pattern matching
// Prelude: Composeable Functional Pattern Matchers
const just =
target =>
input =>
input.startsWith(target) &&
target;
const cases =
(...patterns) =>
input => {
const matches = patterns.map(p => p(input)).filter(m => m !== false);
if (matches.length === 0) {
return false;
} else {
return matches.sort((a, b) => a.length > b.length ? -1 : +1)[0]
}
};
const follows =
(...patterns) =>
input => {
let matchLength = 0;
let remaining = input;
for (const pattern of patterns) {
const matched = pattern(remaining);
if (matched === false) return false;
matchLength = matchLength + matched.length;
remaining = input.slice(matchLength);
}
return input.slice(0, matchLength);
};
const zeroOrMore =
pattern =>
input => {
let matchedLength = 0;
let remaining = input;
while (remaining.length > 0) {
const matched = pattern(remaining);
if (matched === false || matched.length === 0) break;
matchedLength = matchedLength + matched.length;
remaining = remaining.slice(matched.length);
}
return input.slice(0, matchedLength);
};
const oneOrMore =
pattern =>
input => {
let matchedLength = 0;
let remaining = input;
while (remaining.length > 0) {
const matched = pattern(remaining);
if (matched === false || matched.length === 0) break;
matchedLength = matchedLength + matched.length;
remaining = remaining.slice(matched.length);
}
return matchedLength > 0 && input.slice(0, matchedLength);
};
const entirely =
pattern =>
input => {
const matched = pattern(input);
return matched !== false &&
matched === input &&
matched;
};
// Full Solution
const balanced =
input =>
zeroOrMore(
cases(
follows(just('('), balanced, just(')')),
follows(just('['), balanced, just(']')),
follows(just('{'), balanced, just('}'))
)
)(input);
const entirelyBalanced = entirely(balanced);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment