使用访问者模式时,如何将结构从树(即继承的属性)传递



我正在使用antlr4的C 版本为音乐产品开发DSL。我曾经(30年前!(手工做这种事情,所以拥有像Antlr这样的东西是一种荣幸,尤其是现在我不必在实际的语法定义中插入代码。

我想在函数调用中对实际VS正式ARG进行类型检查。在下面的语法段中,"实际参数"可以返回表达式的类型。但是,"实际参数列表"需要返回这些类型的数组(例如(,以便functionCall的代码可以与正式参数列表进行比较。

如果我是在手写,访问或Visitchildren的电话会在上下文之后进行额外的参数,以便我可以在适当的位置创建一个新数组,然后让子节点填写详细信息。

我想,我不仅可以在" vistactualparameterlist"中打电话给Visitchildren,我可以在那里创建阵列并手动打电话给每个孩子,而不仅仅是一个简单的Visitchildren,但这感觉就像是一个黑客,这对中的微小变化非常敏感语法。

有更好的方法吗?

functionCall: Identifier LeftParen actualParameterList? RightParen
;
actualParameterList:
   actualParameter anotherActualParameter
;
actualParameter:
   expression 
;
anotherActualParameter:
  Comma actualParameter anotherActualParameter
|
;   

您处在正确的路径上。我建议这样的东西:

functionCall: Identifier LPAREN actualParameterList RPAREN
;
actualParameterList:
    actualParameter (',' actualParameter)*
;
actualParameter:
   expression 
;
LPAREN : '(';
RPAREN : ')';

使用此信息,在actualParameterList的访问者中,您可以检查每个孩子是否是actualParameterContext的类型,如果是的,请在该孩子上明确致电访问,这将使您进入您的表达式评估代码(大概是在actualParameter的访问者中处理的(。正如您所说,这减轻了一般拜访儿童的需求。当您可以检查类型时,这是非常精确的。

这是我自己代码中这种模式的一个示例(在C#中,但您肯定会看到动作中的模式(:

for (int c = 0; c < context.ChildCount; c++)
{
    if (context.GetChild(c) is SystemParser.ServerContext) // make sure correct type
    {
        string serverinfo = Visit(context.GetChild(c));  // visit the specific child and save return value, string in this case
        sb.Append(serverinfo); // use result to fill array or do whatever
    }
}

现在您可以看到模式,返回代码。语法:

actualParameter (',' actualParameter)*

意味着参数列表具有一个actualParameter,其次是零或更多的*操作员。我只是把逗号扔到那里以示视觉清晰。

您建议,访问者是这样的理想模式,因为您可以明确访问所需的任何节点。它不会给您一个数组,但是您可以填充阵列或任何其他必要的结构,并带有访问孩子的结果,就像您从我的代码中看到的那样。我的访客返回字符串,我只是附加到了StringBuilder。您可以使用相同的模式来构建所需的一切。

相关内容

  • 没有找到相关文章

最新更新