作者:转化术治_953 | 来源:互联网 | 2023-02-01 19:51
我正在使用C++版本的ANTLR4为音乐产品开发DSL.我曾经(30年前!)手工做这种事情所以很高兴有一些像ANTLR这样的东西,特别是现在我不必在实际的语法定义中插入代码.
我想在函数调用中对实际与正式args进行类型检查.在下面的语法段中,'actualParameter'可以返回表达式的类型.但是,'actualParameterList'需要返回这些类型的数组(例如),以便functionCall的代码可以与形式参数列表进行比较.
如果我手写这个,那么访问或visitChildren的调用将在上下文之后获取额外的参数,这样我可以在适当的位置创建一个新数组,然后让子节点填充详细信息.
我想,不是只是在'visitActualParameterList'中调用visitChildren,我可以在那里创建数组并手动调用每个子进程,而不仅仅是一个简单的visitChildren,但这感觉就像一个hack,并且它对语法中的微小变化变得非常敏感.
有更好的方法吗?
functionCall: Identifier LeftParen actualParameterList? RightParen
;
actualParameterList:
actualParameter anotherActualParameter
;
actualParameter:
expression
;
anotherActualParameter:
Comma actualParameter anotherActualParameter
|
;
TomServo..
11
你走在正确的道路上.我会建议像:
functionCall: Identifier LPAREN actualParameterList RPAREN
;
actualParameterList:
actualParameter (',' actualParameter)*
;
actualParameter:
expression
;
LPAREN : '(';
RPAREN : ')';
使用此功能,在访问者中,actualParameterList
您可以检查每个孩子是否属于类型actualParameterContext
,如果是,请明确调用该孩子的访问,这将使您进入表达式评估代码(可能在访问者中处理actualParameter
).正如你所说,这可以减少一般性地探望儿童的需要.当你可以检查这样的类型时,它非常精确.
这是我自己的代码中的这种模式的一个例子(在C#中,但你肯定会看到模式在运行):
for (int c = 0; c
现在您可以看到模式,返回到您的代码.语法:
actualParameter (',' actualParameter)*
表示参数列表中有一个参数列表actualParameter
后跟零个或多个附加的*
操作符.为了清晰起见,我只是把逗号放在那里.
正如您所建议的,访问者是完美的模式,因为您可以明确访问您需要的任何节点.它不会给你一个数组,但你可以填充一个数组或任何其他必要的结构与访问孩子的结果,就像你在我的代码的剪辑中看到的那样.我的访问者返回字符串,我只是附加到StringBuilder.您可以使用相同的模式来构建您需要的任何内容.
1> TomServo..:
你走在正确的道路上.我会建议像:
functionCall: Identifier LPAREN actualParameterList RPAREN
;
actualParameterList:
actualParameter (',' actualParameter)*
;
actualParameter:
expression
;
LPAREN : '(';
RPAREN : ')';
使用此功能,在访问者中,actualParameterList
您可以检查每个孩子是否属于类型actualParameterContext
,如果是,请明确调用该孩子的访问,这将使您进入表达式评估代码(可能在访问者中处理actualParameter
).正如你所说,这可以减少一般性地探望儿童的需要.当你可以检查这样的类型时,它非常精确.
这是我自己的代码中的这种模式的一个例子(在C#中,但你肯定会看到模式在运行):
for (int c = 0; c
现在您可以看到模式,返回到您的代码.语法:
actualParameter (',' actualParameter)*
表示参数列表中有一个参数列表actualParameter
后跟零个或多个附加的*
操作符.为了清晰起见,我只是把逗号放在那里.
正如您所建议的,访问者是完美的模式,因为您可以明确访问您需要的任何节点.它不会给你一个数组,但你可以填充一个数组或任何其他必要的结构与访问孩子的结果,就像你在我的代码的剪辑中看到的那样.我的访问者返回字符串,我只是附加到StringBuilder.您可以使用相同的模式来构建您需要的任何内容.
这个答案正在讨论[关于meta](https://meta.stackoverflow.com/q/350371/962603).
是的,正如我在我的问题中提到的,我已经认为我可以通过明确检查和访问适当的孩子来做到这一点.但这种方法对我来说是错误的.特别是,在这种特殊情况下,这并不是什么大问题,因为只有一个级别的"孩子"需要检查.更复杂的示例可能需要更深的树.必须从"顶部"操纵它需要深入了解结构的全局知识.这反对能够传递一个属性(在这种情况下是一个数组)DOWN树,其中每个叶子(或子树)可以在本地做事.