JSFiddle - React, Tailwind, and code Playground
by disfated
HTML
<textarea id="pattern" placeholder="Шаблон" autofocus="">а((белые|(странные&зеленые))облака&летят&прыгают)в голубой вышине</textarea>
<textarea id="output" placeholder="Результат"></textarea>
CSS
html, body {
height: 100%;
}
* {
box-sizing: border-box;
}
body {
background: #DEDAD3;
background: radial-gradient(ellipse at center, #EDECE9 0%,#CDC4B7 100%);
font-family: sans-serif;
font-size: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: stretch;
margin: 0;
padding: 10px 4%;
}
input, textarea {
font-family: PT Mono, monospace;
font-size: 16px;
line-height: normal;
outline: none;
border-radius: 2px;
background: #faf9f6;
color: #7E7469;
width: 100%;
padding: 0.5em 0.5em 0.5em 0.5em;
margin: 0;
border: solid 1px #aaa;
border-bottom-color: #bbb;
border-top-color: #999;
box-shadow: 0 1px 0 rgba(0,0,0,0.1) inset, 0 0 3px rgba(0,0,0,0.05) inset, 0 1px 0 rgba(255,255,255,0.7);
}
input::-webkit-input-placeholder,
textarea::-webkit-input-placeholder {
color: #D8D3CE;
}
input:focus,
textarea:focus {
background: #fff;
}
#output {
margin-top: 5px;
}
}
JavaScript
/*
Built with PEG.js (http://pegjs.majda.cz/)
Grammar:
{
Array.prototype.flatten = function() {
var r = [];
(function iterate(arr) {
for (var v, i = 0, l = arr.length; i < l; i++) {
Array.isArray(v = arr[i]) ? iterate(v) : r.push(v);
}
})(this);
return r;
};
var append = function(arr, str) {
var i = arr.length;
str = String(str);
while (i--) arr[i] += str;
return arr;
};
var multiply = function(arr, set) {
var clone = arr.concat(), i, n = set.length;
arr.length = 0;
for (i = 0; i < n; i++) {
arr.push.apply(arr, append(clone.concat(), set[i]));
}
};
var permute = function(set) {
var perms = [];
var used = [];
function p(set) {
var i, ch;
for (i = 0; i < set.length; i++) {
ch = set.splice(i, 1)[0];
used.push(ch);
if (set.length == 0) {
perms.push(used.slice().join(' '));
}
p(set);
set.splice(i, 0, ch);
used.pop();
}
return perms;
}
return p(set);
};
var expression = function(list) {
return '{' + list.map(function(exp) { return Array.isArray(exp) ? '[' + exp.join(',') + ']' : String(exp); }).join('') + '}';
};
var expression = function(list) {
var variants = [ '' ], exp;
if (!Array.isArray(list)) return list;
while (exp = list.shift()) Array.isArray(exp) ? multiply(variants, exp) : append(variants, exp);
return variants.length > 1 ? variants : variants[0];
}
}
start
= a:expression b:("\n" e:expression { return e })* { b.unshift(a); return b.flatten().join(""); }
expression
= a:(group / [^\n])* { return expression(a) }
group
= "(" g:( or_expression / and_expression ) ")" { return g }
or_expression
= a:or_literal b:( "|" a:or_literal { return a } )+ { b.unshift(a); return b.flatten(); }
or_literal
= a:(group / [^|)\n])+ { return expression(a) }
and_expression
= a:and_literal b:( "&" c:and_literal { return c } )+ { b.unshift(a); return permute(b.flatten()); }
and_literal
= a:(group / [^&)\n])+ { return...