我希望能够检查返回值的类型是否与ANTLR中的方法类型相同。(即int processOperation()应返回类似int的返回(3-1*4))
我的语法如下:https://github.com/RodrigoZea/Lab00DDC/blob/fda787998e5ed1cc5e5d94e6506ed6ca08dbd955/Decaf/Decaf.g4
我使用ANTLR4的python实现,但我不确定如何在返回语句中检查操作的类型,例如(1+3*4)应该返回int。我使用的是Listener,所以我的逻辑如下:
- 首先检查值是否为基元(即返回"随机",返回1)
- 检查该值是运算还是单个变量
对于单个变量,在符号表中搜索它就足够了,但对于一个操作,我不确定如何处理它>但我不认为在ANTLR4的Python版本中有这样的实现,这似乎是我在ANTLR4权威参考中读到的最好的方法,因为它将保存节点(和操作子树)的数据类型,我可以很容易地检查它的类型并将其与我的方法类型进行比较。我猜我在输入运算符规则时需要进行检查,但我不确定该如何处理这些数据,也不确定是否有方法在Python中实现ParseTreeProperty。谢谢
因此,根据Mike和kaby的回答,我想出了一个解决方案。它非常简单,但功能性很强。在Python中复制ParseTreeProperty的最佳方法是创建一个字典,ctx对象将是关键,并且值是手动设置的,这取决于您希望值是什么(这就是Mike的答案派上用场的地方)。要更新字典值,您将在*Exit()方法上执行此操作,正如Mike所说。
例如,如果您正在退出一个int literal、char literal或其他任何东西(您可以将我的语法作为参考),您可以按如下方式向字典中添加一个条目:
def exitType_literal(self, ctx: DecafParser.Type_literalContext):
self.nodeTypes[ctx] = 'type'
例如,如果我想将一个节点保存为int值,我会执行以下操作。。。
def exitInt_literal(self, ctx: DecafParser.Int_literalContext):
self.parseTreePropertyDictionary[ctx] = 'int'
然而,如果你想获得一个变量的值,你必须在符号表的实现中搜索它。这就是我获取类型值的方法。
因此,一旦设置了每个节点,就可以简单地设置您想要如何处理操作。例如,如果您想要一个"+"如果要使用int运算符,您需要检查字典中第一个和第二个运算符的类型,检查两者是否都是int,如果是这样,则将其保存在字典中作为"int"类型节点,在该节点中处理您的"int"+"操作人员
然后,为了获得操作的类型,您只需访问该节点上的字典,它就会返回"int"或您设置的任何类型。
ParseTreeProperty
是一种方便"附加";属性到解析树的节点,这可能是跟踪树中每个节点的type
的有用方法。然而,正如评论所提到的,还有其他数据结构可以跟踪每个节点的类型并映射回它
使用监听器,您也可以只拥有一堆类型。当您退出每个表达式时,它会弹出所有子表达式的类型,为自己计算表达式类型,并将该类型推送到堆栈上。当然,您必须注意正确地管理推送和弹出(注意异常),但这可能是一个相当干净的实现。
您还可以实现表达式类型验证访问者。使用这种方法,您可以编写一个返回其类型的表达式访问者。对于每个overridenvisit*()
,您只需在每个子级上调用visit()
即可获得它的类型,然后决定您希望得到的类型是什么(可能还有它是否是一个有效的表达式)。请注意,"visit"在节点返回访问者的结果时,这是访问者和侦听器之间的关键区别之一(另一方面,对于访问者,您必须明确选择如何导航子节点)。
就";如何处理该数据";,在这一点上,你正在就你希望你的语言如何表现、什么是有效的等等做出设计决策。
例如:
7 * "string"
也许你认为CCD_ 6是CCD_;字符串";是CCD_ 8类型。在你的听众/访问者中,对于乘法表达式,这取决于你来决定这是一个错误(结果"type
"可能是InvalidType
),还是像Ruby一样,这是一种可爱的获取"CCD_10"的方式;字符串字符串字符串字符串";,在这种情况下,您将返回一个类型的String
。对于函数,您需要决定函数的返回类型。您是否要求明确定义它们?必须在引用之前定义(如果不是,则需要先通过解析树创建函数和返回类型的符号表以引用,然后才能导航树评估表达式类型)。也许,您有一种动态语言,不同的输入类型(甚至值)可能会导致函数的返回类型不同。
很明显,这已经深入到语言设计选择中,并且语言已经就如何处理它们做出了许多不同的决定。ANTLR只是你的解析技术,(除了提供像监听器和访问者这样的方便类之外)对你如何做出这些决定或如何实现它们没有什么好说的。而且,没有办法在语法中对它们进行编码,因为它们是语义问题,对解析或解析树的构建没有影响。