JSFiddle - React, Tailwind, and code Playground
HTML
<h2>Results</h2>
<div id="selfTestPanel">
<h3>Try it yourself</h3>
<table>
<tr><td>Left</td><td colspan="2">right</td></tr>
<tr>
<td><input type="text" id="testLeft" /></td>
<td><input type="text" id="testRight" /></td>
<td><button id="selfTryButton">Try</button></td>
</tr>
</table>
</div>
<br />
<div id="tablePanel" >
<h3>Positive Tests</h3>
<table class="resultsTable" id="positiveOutput">
<thead>
<tr><th>left</th><th>right</th><th>Result</th><th>Comment</th></tr>
</thead>
<tbody />
</table>
<br />
<h3>Negative Tests</h3>
<table class="resultsTable" id="negativeOutput">
<thead>
<tr><th>left</th><th>right</th><th>Result</th><th>Comment</th></tr>
</thead>
<tbody />
</table>
</div>
<div id="logPanel">
<h3>Tokens</h3>
<table id="logHead">
<tr><td>Left:</td><td id="logLeft" ></td></tr>
<tr><td>Right:</td><td id="logRight" ></td></tr>
<tr><td>Result:</td><td id="logResult" ></td></tr>
<tr><td>Comment:</td><td id="logComment" ></td></tr>
</table>
<table id="logOutput">
<thead>
<tr><th>left</th><th>right</th></tr>
</thead>
<tbody />
</table>
</div>
CSS
body {
font-family: verdana;
}
th {
text-align: left;
text-transform: uppercase;
}
table {
border-collapse:collapse;
}
td {
text-align: left;
padding: 4px 20px 4px 0px;
}
tr
{
cursor: pointer;
}
h3
{
margin: 0 0 5px 0;
border-bottom: 1px solid #ddd;
}
.resultsTable tbody tr:nth-child(2n+1) {
background:#f8f8f8;
}
.resultsTable tbody tr:hover
{
background: #f0f0f0;
}
#logOutput tbody tr:nth-child(2n+1)
{
background: #f8f8e8;
}
#logOutput, .resultsTable
{
width: 100%;
}
#positiveOutput .bad, #negativeOutput .good {
color: red;
}
#logPanel
{
position:absolute;
top: 10px;
left: 20px;
border: 1px #e8e8ee solid;
border-radius: 3px;
padding: 5px;
background: #fffff0;
width: 400px;
max-height: 300px;
overflow-y: scroll;
}
.nulltoken
{
color: red;
}
JavaScript
var trueInput = [
{ left: '[abcd]d', right: '*d', comment: 'Recursive Backtracking', expects: true },
{ left: 'abc', right: 'abc', comment: 'literal', expects: true },
{ left: '*', right: 'abc', comment: 'base *', expects: true },
{ left: '?', right: 'a', comment: 'base ?', expects: true },
{ left: '[abc]', right: 'a', comment: 'base set', expects: true },
{ left: 'prefix*', right: 'prefix:extended*', comment: 'from question', expects: true },
{ left: '*suffix', right: '*:extended:suffix', comment: 'from question', expects: true },
{ left: 'left*right', right: 'left*middle*right', comment: 'from question', expects: true },
{ left: 'a*b*c', right: 'a*b*d*b*c', comment: 'from question', expects: true },
{ left: 'hello*', right: '*ok', comment: 'from question', expects: true },
{ left: 'pre[ab]fix*', right: 'pre[bc]fix*', comment: 'from question', expects: true },
{ left: '***', right: '***', comment: 'mirror *', expects: true },
{ left: '???', right: '???', comment: 'mirror ?', expects: true },
{ left: 'abc?efg?ijk?n?p', right: 'abcdefg[hijk]ijk*mnop', comment: '? vs all', expects: true },
{ left: 'abc[def]efg[hij]ijk[lmn]mno[pqr]q', right: 'abcdefg[hij]ijk*lmno?q', comment: 'set vs all', expects: true },
{ left: 'abc*fgh*ijklmn*pqr*tu', right: 'abcdefgh[ijk]jklmn?qr*u', comment: 'any vs all', expects: true },
{ left: '[abc][cde][efg]', right: '[abc][cde][efg]', comment: 'mirror set', expects: true },
{ left: '[abc]*[def]*[abc]', right: 'cda', comment: 'zero length *', expects: true },
{ left: 'ab*?*de', right: 'abcde', comment: 'zero length *', expects: true },
{ left: '[abc]*[cde]*[efg]', right: 'abcde', comment: '1 length *', expects: true },
{ left: 'ab*?*de', right: 'abcde', comment: '1 length *', expects: true },
{ left: 'abc*def*hij', right: 'abc*def*hij', comment: 'recursive *', expects: true },
{ left: 'abc[def]hij', right: 'a*j', comment: 'set in any', expects:...