以下工作对我正在尝试做的很好,但它显然非常重复。它应该与以下示例匹配:
使用
很诱人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 :(得分: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]; }