JSFiddle - React, Tailwind, and code Playground

HTML

<h2>Javascript port of invRegex.py</h2>
<p>Generates a list of strings that match a regex.</p>
<form name="input">
    Regex: <input type="text" name="regex" value="b[a-n]{3}" />
    Delay: <input type="text" name="delay" value="0" />
    <input type="submit" />
</form>
<ol id="matches"></ol>

JavaScript

var timer = null;

input.onsubmit = function() {
    if (timer) {
        window.clearTimeout(timer);
        timer = null;
    }
    var matches = document.getElementById('matches');
    matches.innerHTML = '';
    var show = function(match) {
        var li = document.createElement('li');
        li.appendChild(document.createTextNode(match));
        matches.appendChild(li);
    };
    var iterator = new ParseTreeMapper().mapToIterator(ret(this.regex.value));
    var delay = parseInt(this.delay.value);
    if (delay > 0) {
        iterator.first();
        var step = function() {
            timer = null;
            if (iterator.ok()) {
                show(iterator.get());
                iterator.next();
                timer = window.setTimeout(step, delay);
            }
        };
        step();
    }
    else {
        new Enumerator(iterator).each(show);
    }
    return false;
};

function Enumerator(iterator) {
	this.iterator = iterator;

	this.each = function(callback) {
		for (this.iterator.first(); this.iterator.ok(); this.iterator.next()) {
			callback(this.iterator.get());
		}
	};
}

//--------------------------------------------------
//  map parse tree to iterator
//--------------------------------------------------

function ParseTreeMapper() {
    this.capturingGroups = [];
}
ParseTreeMapper.prototype.mapToIterator = function(parseTree) {
    switch (parseTree.type) {
        case ret.types.ROOT:
        case ret.types.GROUP:
            var me = this;
            var mapToSequence = function(parseTrees) {
                return new Sequence(parseTrees.map(function(t) {
                    return me.mapToIterator(t);
                }));
            };
            var group = parseTree.options ?
                new Choice(parseTree.options.map(mapToSequence)) : 
                mapToSequence(parseTree.stack);
            if (parseTree.remember) {
                this.capturingGroups.push(group);
            }
            return group;
     ...