假设我们有三个元素a
b
和c
。
有效表达式使用这三个元素(和可选的空格)。
是否有一种惯用的方式来编写满足这三个要求的PEG语法?
我在http://pegjs.org/online玩了peg.js并解决了(1)(lookahead)和(2),但是(3)没有找到我。有什么建议吗?
e = &(a / b / c) (a? b? c?)
a = 'a' _
b = 'b' _
c = 'c' _
_ = [ \t]*
答案 0 :(得分:1)
由于peg.js非常棒,如果元素列表s
是某些元素集S
的组合,那么提供一个返回true(并使用输入)的检查函数并不太难。{ 1}}(不允许重复)。基本思想是计算S
的powerset并将s
的每个元素映射到素数。 S
的每个元素被映射到其对应元素的素数的乘积,即S
的幂集的每个元素被映射到唯一的数字。集合s
是S
中元素的组合,当且仅当s
中相应素数的乘积属于从S
计算的素数的乘积中时。 (我猜,执行此检查的方法不止一种:-))。以下是peg.js的解决方案,包含5个元素,我认为这些元素非常有效。 (使用& { predicate }
时有点烦恼:使用arguments对象中的所有命名表达式调用javascript里面,因此(a / b /c /d /e)+
必须有el:(a / b /c /d /e)+
}之类的名称。
{
// array of elements (expressions)
var data = ['a','b','c', 'd', 'e'];
// map elements to primes
var primemap = {
a: 2,
b: 3,
c: 5,
d: 7,
e: 11
};
// powerset of an array
function powerset(arr) {
var ps = [ [] ];
for (var i=0; i < arr.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(arr[i]));
}
}
return ps;
}
// compute the product of primes corresponding to each element of an array arr
function primeprod(arr) {
return arr.reduce( function(p,c) { return p * primemap[c] }, 1 );
}
// compute powerset and remove empty set at index 0 of the powerset
var ps = powerset(data);
ps.splice(0,1);
// map elements of powerset to products of primes
var prods = ps.map( function(el) { return primeprod(el); });
// returns true if an arr is a combination of the elements
function isCombination(arr) {
return prods.indexOf(primeprod(arr)) !== -1
}
}
expr = exp / blankline;
exp = (el:(a / b / c / d / e)+ &{ return isCombination(Array.prototype.slice.call(arguments)[0]); } {return el; } ) rest*
a = _ a:'a' {return a; }
b = _ b:'b' {return b; }
c = _ c:'c' {return c; }
d = _ d:'d' {return d; }
e = _ e:'e' {return e; }
rest = [^abcde]
blankline =
[ \t]* ("\n" / eof) { return []; }
_ = [ \t]*
eof = !.
答案 1 :(得分:0)
真正唯一可能的是列出所有六个可能的订单,因为PEG没有&#34;无序排列&#34;运营商。 (传统的上下文无法使用语法,因此大致相同的程序是必要的。
例如,您可以使用:
npm install jasmine-expect --save-dev
但构建大量替代品显然很乏味。
通常更容易解决a (b c? / c b?)? / b (a c? / c a?)? / c (a b? / b a?)?
,x
,...的列表,无论如何重复,而且不会重复#34;通过接受y
,x
,...的任意列表,然后检查语义动作中的重复,等等。这不仅使语法更容易编写,而且还允许更有意义的错误消息。