Сохранение порядка в грамматиках ANTLR4

Для грамматики ANTLR4 (просто MWE)

grammar T;

sequence: ( a | b )*;

a: FORWARD;
b: RIGHT;

FORWARD: 'f';
RIGHT: 'r';

бэкэнд ANTLR4 C ++ генерирует парсер TParser вытекающий из antlr4::Parser, Я заинтересован в классе TParser::SequenceContext, происходит от antlr4::ParserRuleContext:

class  SequenceContext : public antlr4::ParserRuleContext {
public:
SequenceContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *EOF();
std::vector<AContext *> a();
AContext* a(size_t i);
std::vector<BContext *> b();
BContext* b(size_t i);

virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;

virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};

Моя проблема в том, что порядок из случаев a а также b теряется, когда я использую только std::vector<>с возвращенными SequenceContext::a() а также SequenceContext::b() функции-члены. Что лучшая практика в формулировке ANTLR4, чтобы сохранить порядок? Или есть другой способ получить заказ из дерева разбора? Обратите внимание, что я не хочу широко использовать интерфейсы посетителя или слушателя, а скорее сам иду по дереву разбора.

Подобный пример будет похож на грамматику (показаны только соответствующие части):

grammar U;

for_statement: 'for' '(' expr? ';' expr? ';' expr? ')' statement

Контекст для правила предоставит пользователю только список выражений. Если дано только последнее выражение, контекст дает нам только вектор expr с размером 1 и без простого, почему бы определить, было ли дано первое, второе или третье выражение.

0

Решение

После того, как вы определили, что ваши входные данные синтаксически верны (анализируя их), вы можете просто использовать поток токенов, чтобы просмотреть все входящие токены. Они находятся в точном порядке, как указано изначально. использование CommonTokenStream::getTokens() для списка.

0

Другие решения

Я решил основной пример, используя следующие модификации грамматики:

grammar T;

sequence: direction*;

direction: a | b;

a: FORWARD;
b: RIGHT;

FORWARD: 'f';
RIGHT: 'r';

который дает вектор direction правила контекстов в sequence контекст. в direction контекст правила, либо a или же b установлено (a() != nullptr или же b() != nullptr).

В последнем примере грамматику можно изменить, используя специальную функцию грамматики ANTLR, которая позволяет нам называть разные expr части:

grammar U;

for_statement: 'for' '(' first_expr=expr? ';' second_expr=expr? ';' third_expr=expr? ')' statement

for_statement контекст тогда имеет first_expr() != nullptr если первое выражение было дано. first_expr() возвращает указатель на тип UParser::First_exprContext и обеспечивает нормальный expr контекст. В грамматике ANTLR4 есть несколько таких полезных функций, которые могут сделать обход дерева синтаксического анализа более надежным с точки зрения необходимости только изменения небольших частей в коде, который использует дерево синтаксического анализа, когда грамматика изменяется.

0