编译原理 符合表和语法分析

符号表和语义分析

 

一、语义分析的内容

1. 遇到名称 (变量名,函数名) 定义时

检查是否重定义。(redefined)

 

2. 遇到名称使用时

检查是否未定义。(undefined)

 

3. 类型检查

表达式中的运算,赋值,函数调用中的参数,都要检查类型是否匹配或相容。

 

二、符号表

为了实现语义分析,使用符号表。

当定义一个名称时,需要查询符号表,看该名称是否重定义。若是,报错 redefined;否则把该名称插入到符号表中。

当使用一个名称时,需要查询符号表,看该名称是否未定义。若是,报错 undefined。

为简单起见,用链表实现符号表。产品级编译器中,通常使用hash表来实现符号表。

 

三、作用域 (scope)

为了减少名称的冲突,编程语言中使用作用域的概念。作用域指名称(变量名,函数名等)的有效引用范围。

在不同作用域中,可定义相同的名称。在内层作用域中,可定义与外层作用域相同的名称。

 

四、C语言中的作用域

有三种:

1. 全局作用域

1) 全局变量

2) 函数

函数内不能定义函数,所有函数是全局的。从定义处直到文件结束的范围内,函数有效、可以引用。

 

2. 函数作用域

包括函数参数和函数内定义的局部变量。只在该函数范围内有效。

 

3. 块作用域。

在块语句(花括号)内定义的变量。只在该块语句范围内有效。

 

示例。

1 #include <stdio.h>

  2                       // 进入全局作用域:level = 0

  3 int a, b;

  4

  5 int add(int a, int b) { //从参数表开始,进入函数作用域:level = 1

  6     int c;

  7     c = a + b;

  8     return c;

  9 }                         // 退出函数作用域:level = 0

 10

 11 int main() {            // 从参数表开始,进入函数作用域:level = 1

 12     int a, c;

 13     a = 90;  b = 20;

 14     c = add(a, b) / b;

 15

 16     if ( a > b )

 17     {                  // 进入块作用域:level = 2

 18         int c = a;

 19         while ( c > b )

 20             c = c - b;

 21         a = c;

 22     }                  // 退出块作用域:level = 1

 23

 24     printf("a=%d  b=%d  c=%d\n", a, b, c);

 25 }                       // 退出函数作用域:level = 0

 

五、最内嵌套作用域规则

在外层作用域定义的名称,在内层作用域里可见,除非内层作用域里定义了相同的名称。

在使用一个名称时,按照从内层到外层的顺序,来查找该名称的定义之处。

满足这种规则的作用域,称静态作用域,也称词法作用域。

 

六、符号表的实现

用链表实现。每次插入符号,插入到表头。

设置一个全局变量 level,记录当前作用域的层次 (深度)。

 

用一例加以说明。

$ cat -n t4.cmm

     1  int a, b;

     2

     3  int add(int a, int b) {

     4      int c;

     5      c = a + b;

     6      return c;

     7  }

     8

     9  int main() {

    10      int a, y;

    11      a = 100;  b= 20;

    12      y = a / b;

    13      print y;

14  }

 

    1) 一开始,进入全局作用域, level = 0;

 

    2) 分析到一个函数,从参数表开始,进入函数作用域,level++;

分析完第4行后,符号表:

 

3) 每退出一个函数,释放该函数加入到符号表的符号,level--;

分析完第7行后,符号表:(一个函数结束后,)

 

4) 进入下一个函数

分析完第10行后,符号表:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值