2014-10-30 6 views
2

Мне нужно создать грамматику с помощью предиката. Нижеследующая грамматика не подходит для данного случая.PEGJS предикатная грамматика

startRule = a:namespace DOT b:id OPEN_BRACE CLOSE_BRACE {return {"namespace": a, "name": b}} 

namespace = id (DOT id)* 
DOT = '.'; 
OPEN_BRACE = '('; 
CLOSE_BRACE = ')'; 
id = [a-zA-Z]+; 

Это не выполняется для данного входа в

com.mytest.create(); 

, который должен был дать «создать» в качестве значения ключа «имя» в результате часть.

Любая помощь будет отличной.

ответ

1

Здесь есть несколько вещей.

Главное, что вы должны знать, что PEG является жадным. Это означает, что ваше правило (DOT id)* соответствует всем последовательностям идентификатора DOT, включая тот, который у вас есть в startRule, как DOT b:id.

Это можно решить с помощью lookahead.

Другое дело, что вы должны помнить, что используете join, так как по умолчанию он будет возвращать каждый символ в качестве члена массива.

Я также добавил правило для точек с запятой.

Попробуйте это:

start = 
    namespace:namespace DOT name:string OPEN_BRACE CLOSE_BRACE SM nl? 
    { 
     return { namespace : namespace, name : name }; 
    } 

/* Here I'm using the lookahead: (member !OPEN_BRACE)* */ 
namespace = 
    first:string rest:(member !OPEN_BRACE)* 
    { 
     rest = rest.map(function (x) { return x[0]; }); 
     rest.unshift(first); 
     return rest; 
    } 

member = 
    DOT str:string 
    { return str; } 

DOT = 
    '.' 

OPEN_BRACE = 
    '(' 

CLOSE_BRACE = 
    ')' 

SM = 
    ';' 

nl = 
    "\n" 

string = 
    str:[a-zA-Z]+ 
    { return str.join(''); } 

И насколько я могу сказать, я разбор этой строки правильно.

+1

Благодарим за помощь, это сработало. Я не знаю, что пэджы жадные. – djadmin