保留ANTLR4语法中的顺序

时间:2017-06-21 16:11:13

标签: c++ parsing antlr 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;
};

我的问题是,当我只使用{{1}返回的a时,bstd::vector<>出现的顺序会丢失}和SequenceContext::a()成员函数。为了保留订单,ANTLR4语法中的最佳实践是什么?或者是否有另一种从解析树获取订单的方法?请注意,我不想广泛使用访问者或监听器界面,而是自己遍历解析树。

类似的例子是语法(仅显示相关部分):

SequenceContext::b()

规则的上下文仅向用户显示表达式列表。如果只给出了最后一个表达式,则上下文只给出了一个grammar U; for_statement: 'for' '(' expr? ';' expr? ';' expr? ')' statement 的向量,其大小为1,并且没有一个简单的原因来确定是否给出了第一个,第二个或第三个表达式。

2 个答案:

答案 0 :(得分:0)

一旦确定输入在语法上是正确的(通过解析它),您只需使用令牌流来遍历所有传入的令牌。它们按照最初给出的确切顺序排列。使用CommonTokenStream::getTokens()作为列表。

答案 1 :(得分:0)

我使用语法的以下修改解决了主要示例:

grammar T;

sequence: direction*;

direction: a | b;

a: FORWARD;
b: RIGHT;

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

direction上下文中提供sequence规则上下文的向量。在direction规则上下文中,设置了aba() != nullptrb() != nullptr)。

对于后一个例子,可以使用ANTLR语法的特殊函数修改语法,该函数允许我们命名不同的expr部分:

grammar U;

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

如果给出了第一个表达式,则for_statement上下文具有first_expr() != nullptrfirst_expr()返回指向UParser::First_exprContext类型的指针,并提供正常的expr上下文。在ANTLR4语法中有几个这样有用的函数可以使得解析树的行走更加健壮,只需要在语法改变时改变使用解析树的代码中的小部分。