出于这个问题的目的,我在C#中编写了一个带有函数调用支持的简单解释器。这只是
a = x(1, 'x', y: z());
现在,我已将此表达式解析为大约此形状和形式的AST:
AssignmentExpression
VariableReferenceExpression
FunctionCallExpression
Int64ConstantExpression
当我对此使用“完整Java”并使用ExpressionEvaluatorVisitor
遍历树时,我需要以某种方式调用所有FunctionCallExpression
中的函数。一个显而易见的选择是将函数名称映射到某个任意类中的静态方法,然后在正确的MethodInfo.Invoke()
实例上使用MethodInfo
。但是,这将完全混淆我自己的调用堆栈与解释表达式的调用堆栈。
有没有办法以某种方式在.NET中创建一个“备用”callstack,还是有其他方法来区分两个独立的callstack?
答案 0 :(得分:3)
解释器代表解释的代码执行任务,因此解释器的执行本质上耦合到解释的代码。但是,您可以通过简单地定义一个名为CallStackElement
的类来模拟调用堆栈(这对于调试解释的程序非常有用,如果您希望支持解释语言中的重入函数,则需要它)MethodName
1}},ParameterList
,LocalVariables
等等,并拥有Stack<CallStackElement>
。每当解释的代码调用一个函数(无论是用户定义的函数还是库函数)时,都要向该堆栈添加一个元素,并在函数完成时弹出它。如果您支持用户定义的函数,则应在调用堆栈的最顶层元素中查找局部变量和参数。