对于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;
};
我的问题是,当我只使用{{1}返回的a
时,b
和std::vector<>
出现的顺序会丢失}和SequenceContext::a()
成员函数。为了保留订单,ANTLR4语法中的最佳实践是什么?或者是否有另一种从解析树获取订单的方法?请注意,我不想广泛使用访问者或监听器界面,而是自己遍历解析树。
类似的例子是语法(仅显示相关部分):
SequenceContext::b()
规则的上下文仅向用户显示表达式列表。如果只给出了最后一个表达式,则上下文只给出了一个grammar U;
for_statement: 'for' '(' expr? ';' expr? ';' expr? ')' statement
的向量,其大小为1,并且没有一个简单的原因来确定是否给出了第一个,第二个或第三个表达式。
答案 0 :(得分:0)
一旦确定输入在语法上是正确的(通过解析它),您只需使用令牌流来遍历所有传入的令牌。它们按照最初给出的确切顺序排列。使用CommonTokenStream::getTokens()
作为列表。
答案 1 :(得分: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语法中有几个这样有用的函数可以使得解析树的行走更加健壮,只需要在语法改变时改变使用解析树的代码中的小部分。