1

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

  • #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;
}
4

2 回答 2

1

这就是 And 谓词的用处

仅当 id 未定义、classes 不是空数组或 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;
}
于 2013-12-31T01:31:58.340 回答
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]; }
于 2013-01-23T03:42:11.160 回答