如何使用基于NFA的正则表达式“a * b * a +”

时间:2017-06-19 07:44:33

标签: node.js regex parsing graph nfa

我在JS中编写了一个简单的正则表达式解析器,解析器只支持“*”和“+”,然后我发现了一个问题。

“aa”匹配/ a * b * a + /的结果是错误的。

这是我的过程。

  1. 首先,我通过RE字符串新建了一个NFA图。

    my NFA graph 如图所示,状态5有一个计数器,如果计数器> = 1,状态5将指向“_end”,图形将被连接。

  2. 从状态0开始并执行DFS,记录每个访问过的节点。

  3. 匹配字符串,如果两者相等,则下一个状态的计数器+ 1,然后DFS从下一个状态开始。

  4. 当字符串结束时,检查被访问节点,如果它有状态6,则返回true,否则返回false。

  5. 这是我的代码。

    var Graph = require(__dirname + '/../Graph.js');
    var DFS = require(__dirname + '/../DFS.js');
    
    var NFA = module.exports = function(regexp) {
        var ops = new Array(); // stack
        this.re = regexp;
        this.M = this.re.length;
        this.G = new Graph(this.M + 1, regexp);
    
        for (var i = 0; i < this.M; i++) {
            if (this.re[i] == '*' || this.re[i] == '+') {
                this.G.addEdge(i, i - 1);
                this.G.addEdge(i - 1, i);
            }
            if (this.re[i] == '*')
                this.G.addEdge(i, i + 1);
        }
    };
    
    NFA.prototype.recognize = function(txt) {
        var pc = new Array();
        var dfs = new DFS(this.G, 0);
        for (var v = 0; v < this.G.getV(); v++) {
            if (dfs.marked[v] == true) {
                pc.push(v);
            }
        }
        for (var i = 0; i < txt.length; i++) {
            var match = new Array();
            for (var v = 0; v < pc.length; v++) {
                if (pc[v] < this.M) {
                    if (this.re[pc[v]] == txt[i]) {
                        match.push(pc[v] + 1);
                        this.G.counter[pc[v] + 1]++;
                        var cnt = this.G.counter[pc[v] + 1]++;
                        if (cnt == 1) {
                            this.G.addEdge(pc[v] + 1, pc[v] + 2);
                        }
                    }
                }
            }
            pc = new Array();
            dfs = new DFS(this.G, match);
            for (var v = 0; v < this.G.getV(); v++) {
                if (dfs.marked[v] == true) {
                    pc.push(v);
                }
            }
        }
        for (var v = 0; v < pc.length; v++) {
            if (pc[v] == this.M) {
                return true;
            }
        }
        return false;
    };

    结果:

    • “aa”匹配/ a * b * a + / true
    • “aab”匹配/ a * b * a + / true(应该是假的)
    • “aab”匹配/ a * b * aa * / false(这是我的临时处理方法)
    • “aa”匹配/ a * b * aa * / true

    我想知道如何修复这个bug,我不想使用临时处理方法。 非常感谢。

0 个答案:

没有答案