Matching bracket validator
Read a string, make sure brackets (e.g. {}, (), []) do not overlap.
by Renoir Boulanger
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<section class="container-fluid" style="margin-top:20px;">
<div class=jumbotron>
<h1>Matching bracket validator</h1>
<p>
A validator to check if brackets (e.g. <tt>(), {}, <>, etc</tt>) are closed correctly without overlapping.
</p>
</div>
<div class="row">
<form class="col-xs-12 col-md-12">
<div class="form-group">
<label for="text">Text to validate</label>
<textarea class="form-control" rows="3" id="text">Testing {[(if)]} brackets closes. This string (should) be valid.</textarea>
<span id="textResult" class="help-block"><strong>How to use:</strong> Edit in textarea, then click elsewhere to validate</span>
</div>
</form>
</div>
</section>
JavaScript
/**
* A validator to check if brackets are closed correctly without overlapping
**/
var Validator = (function iife(){
"use strict";
var defaultRules = [
['{','}']
,['(',')']
,['[',']']
,['<','>']
];
function openingTokenCheck(tokenList, inputChar) {
var out = {resultValue: false, match: null};
var matcher = tokenList.find((pair) => {
return inputChar === pair[0];
});
if (!matcher) {
return out;
}
out.resultValue = true;
out.match = matcher;
return out;
}
function closingTokenCheck(tokenList, inputChar) {
var out = {resultValue: false, match: null};
var matcher = tokenList.find((pair) => {
return inputChar === pair[1];
});
if (!matcher) {
return out;
}
out.resultValue = true;
out.match = matcher;
return out;
}
function looper(tokenPairs, inputString) {
let stack = []
, tokens = tokenPairs||[]
, i = 0;
do {
let stackLast = (stack.length > 0) ? stack[stack.length - 1] : null;
let isOpeningToken = openingTokenCheck(tokens, inputString[i]);
let isClosingToken = closingTokenCheck(tokens, inputString[i]);
if (isOpeningToken.resultValue === true) {
stack.push(isOpeningToken);
}
/**
* UNCOVERED CASE
* When a close bracket when we did not get
* an opening earlier. TODO.
**/
if (stackLast !== null) {
if (
isClosingToken.resultValue === true &&
stackLast.match[1] === inputString[i]
) {
stack.pop();
}
}
++i;
} while (i < inputString.length);
return {stack: stack};
}
class ParenthesisValidator {
constructor(rules) {
this.rules = rules || defaultRules;
}
validate(input) {
let validation = looper(this.rules, input);
validation.outcome = (validation.stack.length === 0) ? true : false;
return validation;
}
assert(expected,...