查找字符串行是嵌套的还是另一行的子行

Find if a string line is nested or is a child of another line

我想为某种文件编写一个小型解析器,我必须完成的其中一件事是查找一行是否在另一行中,用缩进(空格或制表符)定义它。

示例:

This is the main line
    This is a nested or child line

我试图通过读取行​​中的第一个字符位置并将其与前一个字符进行比较来确定这一点,如下所示:

var str = '      hello';
str.indexOf(str.match(/\S|$/).shift());

我确定这不是最好的方法,而且看起来很糟糕,我还有其他问题需要解决,例如检查缩进是否由空格(2 或 4)、制表符或 passing/maintaining 上一行(对象)的状态。

此外,行可以无限嵌套,当然我正在寻找一个好的和高性能的算法(或想法)或模式,而不是我认为相对容易做但容易出错的简单检查。我相信使用解析器和编译器的人已经解决了这个问题。


编辑:

str.search(/\S/);

@Oriol 提案看起来好多了

这通常是您编写解析器的目的,而不是纯粹依赖正则表达式。如果嵌套决定了深度,那么您有两件事要解决:1) 找到任意线条的深度,以及 2) 遍历线条集并跟踪每一行,哪一行的前一行具有较低的深度值。

如果您熟悉 Javascript 中的 RegExp 函数,那么第一个是微不足道的:

function getDepth(line) {
  // find leading white space
  var ws = str.match(/^(\s+)/);
  // no leading white space?
  if (ws === null) return 0;
  // leading white space -> count the white space symbols.
  // obviously this goes wrong for mixed spaces and tabs, and that's on you.
  return ws[0].split('').length;
}

第二部分比较简单,因此您有多种选择。您可以遍历所有行,并跟踪行号列表,在深入时推入列表并在返回时从列表中弹出,或者您可以构建一个简单的树结构(这通常要好得多,因为它使您可以更轻松地扩展其功能)使用标准的树构建方法。

function buildTree(lines, depths) {
  if (!depths) {
    var depths = lines.map(e => getDepth);
    return buildTree(lines, depths);
  }
  var root = new Node();
  for(var pos=0, end=lines.length; pos<end; pos++) {
    var line = lines[pos];
    var depth = depths[pos];
    root.insert(line, depth);  
  }
}

当然是用一个简单的Node对象

var Node = function(text, depth) {
  this.children = [];
  this.line = text.replace(/^\s+/,'');
  this.depth = depth;
}

Node.prototype = {
  insert: function(text, depth) {
    // this is where you become responsible: we need to insert
    // a new node inside of this one if the depths indicate that
    // is what should happen, but you're on the hook for determining
    // what you want to have happen if the indentation was weird, like
    // a line at depth 12 after a line at depth 2, or vice versa.
  }
}