编译/代码生成-变量声明问题

问题描述 投票:0回答:2

我最近一直在研究ANTLR和Java,并构建了一个简单的语法来解析此代码并生成AST。我还编写了一个内置的解释器来执行此代码,它似乎运行良好:

关于玩具语言的一些说明:

  • 我的语言只有一种类型的“双精度”
  • 所有变量在赋值时都隐式声明。
  • 所有变量都具有全局范围。即在分配变量后,即使在分配该变量的块之外,也可以使用该变量。
/* A sample program */
BEGIN
    j := 1;
    WHILE j <= 5 DO
        PRINT "ITERATION NO: "; PRINTLN j;
        sumA1 := 0;
        WHILE 1 = 1 DO 
            PRINT "Enter a number, 0 to quit: ";
            i := INPUT;
            IF i = 0 THEN
                BREAK;
            ENDIF
            sumA1 := ADD sumA1, i;
        ENDWHILE
        j := ADD j, 1;
        PRINT "The sum is: "; PRINTLN sumA1;
    ENDWHILE
    j := MINUS j;
    PRINTLN j;
END

然后我将代码生成函数写入AST,以将其从我的AST类输出到C,并得到此结果(美化):

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char * argv[]) {
  double j;
  j = 1.00000;
  while (j <= 5.0) {
    printf("ITERATION NO: ");
    printf("%g\n", j);
    double sumA1;
    sumA1 = 0.00000;
    while (1.0 == 1.0) {
      printf("Enter a number, 0 to quit: ");
      double i;
      scanf("%lf", & i);
      if (i == 0.0) {
        break;
      }
      sumA1 = sumA1 + i;
    }
    j = j + 1.00000;
    printf("The sum is: ");
    printf("%g\n", sumA1);
  }
  j = -j;
  printf("%g\n", j);
}

在代码生成期间,我首先检查变量名在HashMap中是否可用。如您所见,对于赋值语句/输入语句,我在赋值之前添加了变量声明。对于除赋值以外的变量使用,我在使用前抛出了一个用于未初始化变量的异常。

都很好。上面的代码适用于此示例,因为在我的源程序中,我没有在声明它的范围之外使用任何变量。

但是有一个问题。由于我正在块内初始化某些变量(例如while,因此它们不能在范围外使用),因此我需要一种方法来收集在源程序中使用的所有变量,这些变量在C中是全局变量(或至少在主变量之上)。 ()函数)。如果在块外我的程序中使用了变量,则在用C之前声明变量将导致源语言中的有效程序无法在C中编译。

我以为我可以通过以下方法解决它:首先解析所有变量,然后在C程序的开头声明它们,然后生成代码。

但是如果在生成代码之前更新符号表(HashMap),我将无法知道在使用之前是否确实分配了该变量。

重新设计此方法以确保确保质量的最佳方法是什么?

  • 代码生成器应在使用前检查分配。即如果在分配前找到用法,则应抛出异常/编译错误。
  • 同时,我的代码中的所有变量都应在C生成的源代码中作为全局变量提供。因此,如果以前在内部块中分配了变量,则甚至可以在块外部使用变量,因为在我的源语言中,这是可以接受的。
  • 这是我第一次尝试这样的事情。请为我提供任何可能解决方案的指示。

我最近一直在研究ANTLR和Java,并构建了一个简单的语法来解析此代码并生成AST。我还写了一个内置的解释器来执行此代码,它似乎可以工作...

compiler-construction antlr abstract-syntax-tree transpiler implicit-declaration
2个回答
1
投票

在一般情况下,不可能在分配前检测使用情况。考虑以下(不是很好)的C代码:


0
投票

我通过从各个分配节点中删除变量声明,而只是将分配节点中使用的变量添加到全局哈希图中,然后在遍历树后生成声明来解决了这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.