我如何干这个PEGjs规则?

时间:2013-01-23 03:21:10

标签: peg pegjs

以下工作对我正在尝试做的很好,但它显然非常重复。它应该与以下示例匹配:

  • #id.class1.class2 attr =“asdsa”
  • .class1.class2 attr =“asdsad”
  • ATTR = “ASDS”

使用

很诱人
id:idShortcut? classes:classShortcut* attrs:fullAttribute* 

但如果不存在所有三个组件,我不希望它匹配。如何指定3个可选组件的规则,但至少必须存在一个?

attributes = id:idShortcut classes:classShortcut* attrs:fullAttribute* 
{ 
  var ret = [['id', id]];
  for(var i = 0; i < classes.length; ++i ) {
    ret.push(['class', classes[i]]);
  }

  for(var i = 0; i < attrs.length; ++i ) {
    ret.push(attrs[i]);
  }

  return ret;
}
/ classes:classShortcut+ attrs:fullAttribute* { 

  // TODO: how to dry this with the above?

  var ret = [];
  for(var i = 0; i < classes.length; ++i ) {
    ret.push(['class', classes[i]]);
  }

  for(var i = 0; i < attrs.length; ++i ) {
    ret.push(attrs[i]);
  }

  return ret;
}
/ attrs:fullAttribute+ { 
  var ret = [];
  for(var i = 0; i < attrs.length; ++i ) {
    ret.push(attrs[i]);
  }
  return ret;
}

2 个答案:

答案 0 :(得分:1)

这就是和谓词对

有用的东西

如果id未定义,或者类不是空数组,或者attrs不是空数组,则属性仅匹配。

attributes = 
    id:idShortcut? classes:classShortcut* attrs:fullAttribute* &{return id !== undefined || classes.length > 0 || attrs.length > 0;} 
    {
        var ret = [];
        if (id) {
            ret.push(['id', id]);
        }
        for (var x=0; x < classes.length;x++) {
            ret.push(['class', classes[x]);
        }
        for (var y=0; y < attrs.length;y++) {
            ret.push([attrs[y]);
        }
        return ret;
}

答案 1 :(得分:0)

好的,不知道为什么这对我来说甚至是一场挣扎,但是这很好地重构如下(并且可能会进一步改进:

attributes 
  = a:( attributesAtLeastID
    / attributesAtLeastClass
    / attributesAtFullAttr ) 
{
  var id = a[0];
  var classes = a[1];
  var attrs = a[2];
  var ret = [];

  if(id) { ret.push(['id', id]); }

  for(var i = 0; i < classes.length; ++i ) {
    ret.push(['class', classes[i]]);
  }

  for(var i = 0; i < attrs.length; ++i ) {
    ret.push(attrs[i]);
  }
}

attributesAtLeastID = id:idShortcut classes:classShortcut* attrs:fullAttribute* { return [id, classes, attrs]; }
attributesAtLeastClass = classes:classShortcut+ attrs:fullAttribute* { return [null, classes, attrs]; }
attributesAtFullAttr = attrs:fullAttribute+ { return [null, [], attrs]; }