Я пытаюсь создать правило синтаксического анализа, которое учитывает ноль или более токена перед вторым правилом и для которого каждый последующий токен - из тех, которые были частью замыкания - является в 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;
Спасибо всем, кто может оказать помощь;Ваше время очень ценится.