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

时间:2015-12-13 21:55:39

标签: javascript parsing compiler-construction

我正在寻找为某种文件编写一个小解析器,我要做的一件事就是找到一行是否在另一行内,用缩进(空格或制表符)定义它。

示例:

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

我试图通过读取该行中的第一个字符位置并将其与前一个字符位置进行比较来建立这个:

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

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

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

修改

str.search(/\S/);

@Oriol提案看起来好多了

1 个答案:

答案 0 :(得分:1)

这通常是你编写解析器的东西,而不是纯粹依赖正则表达式。如果嵌套确定深度,则需要解决两个问题: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.
  }
}