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();
который должен был дать "create" как значение ключа "name" в результирующей части.
Любая помощь будет отличной.
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(''); }
И, насколько я могу судить, я правильно разбираю эту строку.