保留 ANTLR4 语法中的顺序
Retaining order in ANTLR4 grammars
对于 ANTLR4 语法(只是一个 MWE)
grammar T;
sequence: ( a | b )*;
a: FORWARD;
b: RIGHT;
FORWARD: 'f';
RIGHT: 'r';
ANTLR4 C++ 后端生成从 antlr4::Parser
派生的解析器 TParser
。我对来自 antlr4::ParserRuleContext
:
的 class TParser::SequenceContext
感兴趣
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;
};
我的问题是,当我只使用返回的 std::vector<>
时,出现 a
和 b
的 顺序 丢失了通过 SequenceContext::a()
和 SequenceContext::b()
成员函数。 ANTLR4 语法公式中保留顺序的最佳实践 是什么?还是有另一种方法可以从解析树中获取顺序?请注意,我不想广泛使用访问者或侦听器接口,而是自己遍历解析树。
一个类似的例子是这样的语法(只显示相关部分):
grammar U;
for_statement: 'for' '(' expr? ';' expr? ';' expr? ')' statement
规则的上下文将只向用户显示一个表达式列表。如果只给出最后一个表达式,上下文只给我们一个大小为 1 的 expr
向量,并且没有简单的原因来确定是否给出了第一个、第二个或第三个表达式。
一旦您确定您的输入在语法上是正确的(通过解析),您可以简单地使用您的令牌流遍历所有传入的令牌。它们的顺序与最初给出的顺序完全一致。使用 CommonTokenStream::getTokens()
作为列表。
我使用以下语法修改解决了主要示例:
grammar T;
sequence: direction*;
direction: a | b;
a: FORWARD;
b: RIGHT;
FORWARD: 'f';
RIGHT: 'r';
在 sequence
上下文中给出了 direction
规则上下文的向量。在 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()
returns 指向类型 UParser::First_exprContext
的指针并提供正常的 expr
上下文。 ANTLR4 语法中有几个这样的有用函数,可以使遍历解析树更加健壮,因为当语法发生变化时,只需更改使用解析树的代码中的一小部分。
对于 ANTLR4 语法(只是一个 MWE)
grammar T;
sequence: ( a | b )*;
a: FORWARD;
b: RIGHT;
FORWARD: 'f';
RIGHT: 'r';
ANTLR4 C++ 后端生成从 antlr4::Parser
派生的解析器 TParser
。我对来自 antlr4::ParserRuleContext
:
TParser::SequenceContext
感兴趣
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;
};
我的问题是,当我只使用返回的 std::vector<>
时,出现 a
和 b
的 顺序 丢失了通过 SequenceContext::a()
和 SequenceContext::b()
成员函数。 ANTLR4 语法公式中保留顺序的最佳实践 是什么?还是有另一种方法可以从解析树中获取顺序?请注意,我不想广泛使用访问者或侦听器接口,而是自己遍历解析树。
一个类似的例子是这样的语法(只显示相关部分):
grammar U;
for_statement: 'for' '(' expr? ';' expr? ';' expr? ')' statement
规则的上下文将只向用户显示一个表达式列表。如果只给出最后一个表达式,上下文只给我们一个大小为 1 的 expr
向量,并且没有简单的原因来确定是否给出了第一个、第二个或第三个表达式。
一旦您确定您的输入在语法上是正确的(通过解析),您可以简单地使用您的令牌流遍历所有传入的令牌。它们的顺序与最初给出的顺序完全一致。使用 CommonTokenStream::getTokens()
作为列表。
我使用以下语法修改解决了主要示例:
grammar T;
sequence: direction*;
direction: a | b;
a: FORWARD;
b: RIGHT;
FORWARD: 'f';
RIGHT: 'r';
在 sequence
上下文中给出了 direction
规则上下文的向量。在 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()
returns 指向类型 UParser::First_exprContext
的指针并提供正常的 expr
上下文。 ANTLR4 语法中有几个这样的有用函数,可以使遍历解析树更加健壮,因为当语法发生变化时,只需更改使用解析树的代码中的一小部分。