Przeniesienie invRegex.py do Javascript (Node.js)

Próbowałem portowaćinvRegex.py do implementacji node.js przez jakiś czas, ale wciąż z tym walczę. Mam już drzewo analizujące wyrażenie regularne dziękiret.js tokenizer i działa całkiem nieźle, ale faktyczne generowanie i łączenie wszystkich odrębnych elementów w sposób, który jest wydajny pod względem pamięci, jest dla mnie bardzo trudne. Aby to było proste, powiedzmy, że mam następujące wyrażenie regularne:

[01]{1,2}@[a-f]

Podając toinvRegex.py produkuje następujące dane wyjściowe (tabbified zajmować mniej miejsca):

 0@a     0@b     0@c     0@d     0@e     0@f
00@a    00@b    00@c    00@d    00@e    00@f
01@a    01@b    01@c    01@d    01@e    01@f
 1@a     1@b     1@c     1@d     1@e     1@f
10@a    10@b    10@c    10@d    10@e    10@f
11@a    11@b    11@c    11@d    11@e    11@f

Biorąc pod uwagę, że jestem w stanie uzyskać każdy indywidualny token i utworzyć tablicę wszystkich ważnych indywidualnych wyników:

[01]{1,2} = function () {
    return ['0', '00', '01', '1', '10', '11'];
};

@ = function () {
    return ['@'];
};

[a-f] = function () {
    return ['a', 'b', 'c', 'd', 'e', 'f'];
};

Mogę obliczyćprodukt kartezjański wszystkich tablic i uzyskaj taką samą oczekiwaną wydajność:

var _ = require('underscore');

function cartesianProductOf() {
    return _.reduce(arguments, function(a, b) {
        return _.flatten(_.map(a, function(x) {
            return _.map(b, function(y) {
                return x.concat([y]);
            });
        }), true);
    }, [ [] ]);
};

var tokens = [
    ['0', '00', '01', '1', '10', '11'],
    ['@'],
    ['a', 'b', 'c', 'd', 'e', 'f'],
];

var result = cartesianProductOf(tokens[0], tokens[1], tokens[2]);

_.each(result, function (value, key) {
    console.log(value.join(''));
});

Problem polega na tym, że zawiera wszystkie 36 wartości w pamięci, jeśli miałbym nieco bardziej skomplikowane wyrażenie regularne, takie jak[a-z]{0,10} to się utrzyma146813779479511 wartości w pamięci, co jest całkowicie niewykonalne. Chciałbym przetworzyć tę ogromną listę w sposób asynchroniczny, przekazując każdą wygenerowaną kombinację do wywołania zwrotnego i pozwalając mi przerwać proces w dowolnym sensownym punkcie, który uważam za odpowiedni, podobnie jak invRegex.py lubten pakiet Haskell - niestety nie rozumiem Haskella i nie wiem jak naśladować zachowanie generatora w Pythonie na Javascript.

Próbowałem uruchomić kilka prostych eksperymentów generatora w węźle 0.11.9 (z--harmony) jak ten:

function* alpha() {
    yield 'a'; yield 'b'; yield 'c';
}

function* numeric() {
    yield '0'; yield '1';
}

function* alphanumeric() {
    yield* alpha() + numeric(); // what's the diff between yield and yield*?
}

for (var i of alphanumeric()) {
    console.log(i);
}

Nie trzeba dodawać, że powyższe nie działa. = /

Uderzając głową o ścianę tutaj, każda pomoc w rozwiązaniu tego problemu byłaby bardzo ceniona.

AKTUALIZACJA: Oto przykładowe drzewo analizowania ret.js dlab[a-z]{3}:

{
    "type": ret.types.ROOT,
    "stack": [
            {
                "type": ret.types.CHAR,
                "value": 98 // b
            },
            {
                "type": ret.types.REPETITION,
                "max": 3,
                "min": 3,
                "value": {
                    "type": ret.types.SET,
                    "not": false,
                    "set": [
                        {
                            "type": ret.types.RANGE,
                            "from": 97, // a
                            "to": 122   // z
                        }
                    ]
                }
            }
        ]
    ]
}

TheSET / RANGE typ powinien dawać 26 różnych wartości, a rodzicaREPETITION typ powinien przyjąć tę poprzednią wartość do potęgi 3, dając 17576 różnych kombinacji. Gdybym miał wygenerować spłaszczonetokens tablica jak wcześniejcartesianProductOf, pośrednie spłaszczone wartości zajęłyby tyle miejsca, co sam produkt kartezjański.

Mam nadzieję, że ten przykład lepiej wyjaśnia problem, przed którym stoję.

questionAnswers(6)

yourAnswerToTheQuestion