javascript - JavaScript 中子字符串的行为存在明显问题

标签 javascript string substring state-machine

我正在编写一个递归算法,通过解析正则表达式来构建有限状态自动机。自动机迭代表达式,将字符插入堆栈,将运算符插入“运算符堆栈”。当我遇到“(”(表示分组操作)时,我将一个“子自动机”压入堆栈,并将模式的其余部分传递给子自动机进行解析。当该自动机遇到“)”时,它会将其余的模式传递给子自动机进行解析。字符串一直到父自动机以完成解析。这是代码:

var NFA = function(par) {
  this.stack = [];
  this.op_stack = [];
  this.parent = par;

};

NFA.prototype.parse = function(pattern) {
  var done = false;
  for(var i in pattern) {
    if (done === true) {
      break;
    }
    switch(pattern.charAt(i)) {
      case "(":
        var sub_nfa = new NFA(this);
        this.stack.push(sub_nfa);
        sub_nfa.parse(pattern.substring(i+1, pattern.length));
        done = true;
        break;
      case ")":
        if (this.parent !== null) {
          var len = pattern.length;
          /*TROUBLE SPOT*/
          this.parent.parse(pattern.substring(i, pattern.length));
          done = true;
          break;
        }
      case "*":
        this.op_stack.push(operator.KLEENE);
        break;
      case "|":
        this.op_stack.push(operator.UNION);
        break;
      default:
        if(this.stack.length > 0) {
          //only push concat after we see at least one symbol
          this.op_stack.push(operator.CONCAT);        
        }
        this.stack.push(pattern.charAt(i));
    }
  }
};

注意标有“麻烦点”的区域。给定正则表达式“(a|b)a”,调用 this.parent.parse 只会被调用一次:当子自动机遇到“)”时。此时,pattern.substring(i,pattern.length) = ")a"。这“有效”,但它不正确,因为在将字符串传递给父自动机之前我需要使用“)”输入。但是,如果我将调用更改为 this.parent.parse(pattern.substring(i+1,pattern.length),则解析会得到空字符串!我已尝试单步执行代码,但无法解释这种行为。什么是我失踪了?

根据 Juan 的建议,我制作了一个快速的 jsfiddle 来显示尝试使用此算法解析“(a|b)a”时的问题。在“)”情况下,它使用 i 索引处的子字符串和 i+1 索引处的子字符串填充一个空 div。可以看出,虽然 i 处的子串有 2 个字符,但 i+1 处的子串却是空串!链接如下:http://jsfiddle.net/XC6QM/1/

编辑:我编辑了这个问题以反射(reflect)使用 charAt(i) 不会改变算法的行为的事实。

最佳答案

我认为之前的答案是正确的。但在我看来,这也存在一个相差一的错误。您不应该增加子字符串的索引吗?您不想在父解析中包含“)”,对吗?

this.parent.parse(pattern.substring(i + 1, pattern.length));

但是由于 Juan 提到的错误,这仍然会失败。测试此问题的快速临时修复是将 i 转换为数字:

this.parent.parse(pattern.substring(+i + 1, pattern.length));

这可能适合你。但您可能应该返回并放弃字符串上的 for-in 循环。我认为这就是造成你问题的原因。使用str.split('')将其转为数组,然后使用整数进行循环。这将防止进一步出现此类问题。

关于javascript - JavaScript 中子字符串的行为存在明显问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14965020/

相关文章:

android - 如何从 android 中的 string.xml 读取值?

c - 在 C 中查找子字符串

javascript - 循环返回两个数组

javascript - (Javascript) 来自嵌入代码的 YouTube 视频 ID - 正则表达式?

javascript - 值属性类型自动类型转换

javascript - d3.js map 插图(缩放)

Android:res/strings.xml,包括另一个文件夹中的另一个字符串文件

Java 字符串用 (, ), 等字符替换问题?

r - 将分隔的字符串拆分为 R 数据框中的不同列

java - java中查找子字符串时字符串索引越界异常