【问题标题】:How do I DRY this PEGjs rule?我如何干燥这个 PEGjs 规则?
【发布时间】:2013-12-31 09:31:58
【问题描述】:

以下内容非常适合我正在尝试做的事情,但它显然非常重复。它应该与以下示例匹配:

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

【问题讨论】:

    标签: peg pegjs


    【解决方案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;
    }
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-18
        • 1970-01-01
        • 2013-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多