2013-01-23 30 views
1

以下工作對我所要做的事情來說很好,但它顯然是非常重複的。它應與下面的例子:如何幹這個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; 
} 

回答

0

OK,不知道這是爲什麼即使我奮鬥,但如下這很好地重構(而且很可能被超出了改進:

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]; } 
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; 
}