Создание узла AST наименьшим потомком рекурсивного правила - PullRequest
1 голос
/ 30 октября 2010

Я пытаюсь создать правило синтаксического анализа, которое учитывает ноль или более токена перед вторым правилом и для которого каждый последующий токен - из тех, которые были частью замыкания - является в AST дочерним элементомпредыдущий токен, а второе правило также является дочерним по отношению к последнему символу.

проще объяснить на примере ...

expression11 : ((NOT | COMPLEMENT)^)* expression12;

Например, с учетом приведенного выше правила синтаксического анализатора, если яиметь выражение !! x (где x - это идентификатор), я хочу, чтобы в моем AST x был дочерним по отношению к второму оператору взрыва, который является дочерним по отношению к первому.

Desired:

!
  \ child
    !
      \ child
       x

Вместо моего желаемого поведения, приведенная выше строка создает AST, для которого второй оператор взрыва является дочерним по отношению к первому, а x является дочерним по отношению к первому оператору взрыва, одноуровневым из второго,Очевидно, не то, что я хочу для унарного оператора.

Встречное поведение:

        !
child /   \ child
    x -sib- !

Если я добавлю третий оператор (как в «!!! x»), третий станет дочерним.второго, как и ожидалось, и x остается дочерним по отношению к первому, второму брату второго.

Я подумал, что, возможно, я мог бы исправить это, заключив в круглую скобку всю операторную часть и добавив еще одну вставку, например1018 *

expression11 : (((NOT | COMPLEMENT)^)*)^ expression12;

, пытаясь заставить выражение12 быть дочерним элементом всего замыкания операторов, напрасно надеясь, что это будет интерпретировано как «дочерний элемент полного замыкания означает дочерний элемент наиболее спущенного,«но это было не так, и это не изменило поведение.

Мой вопрос:« Как заставить синтаксический анализатор обрабатывать правило таким образом, чтобы результат выражения12 становился дочерним? »самого нисходящего узла 'NOT' или 'COMPLEMENT' вместо узла с наивысшим предком? "

Я бы подумал, что это будет просто, но я не могу понять этоиз ресурсов Antlr на antlr.org, ни с помощью Google.Это нужно делать постоянно, или есть другой способ полностью структурировать правило, которое я пропускаю?

Вот следующие правила для полноты.Они еще не закончены и будут изменены, но они завершены и работают для тестирования, и все хорошо с ними - как и ожидалось, поскольку они просты.12 для длины массива и вызовов методов, 13 для новых классов и массивов, 14 для индексации массива и 15 для терминалов / скобок.

expression12 : expression13 (DOT (LENGTH | (ID LPAREN (expression (COMMA expression)*)? RPAREN)))?;
expression13 : expression14 | (NEW^ ((ID LPAREN RPAREN) | (INTTYPE LSQBRACK expression RSQBRACK)));
expression14 : expression15 (LSQBRACK expression RSQBRACK)*;
expression15 : (LPAREN expression RPAREN) | INTLIT | TRUE | FALSE | ID | THIS;

Спасибо всем, кто может оказать помощь;Ваше время очень ценится.

1 Ответ

2 голосов
/ 30 октября 2010

Вы не должны использовать звезду Клини, если не хотите, чтобы операторы отображались как братья и сестры.Попробуйте что-то вроде (не проверено)

expression11 : (NOT | COMPLEMENT)^ expression11
             | expression12;
...