现代编译原理——第0章

  转自:https://www.cnblogs.com/BlackWalnut/p/4420568.html

  《现代编译原理》,俗称,虎书。因为这本书对实践的要求比较高,所以选择了这本书来作为编译原理的学习书籍,想一步一步的记录下来,最终完成一个完整的编译器。但是,一个人看书总是感觉很孤独。今天看第一章的题目,看完了都不知道要干什么。无奈找了一本中文版的,翻译的也不如人意,还不如看英文的。最后去晚上找了半天才找到别人写的第一章作业运行后,才知道要实现什么功能。然后自己徒手开始写,居然没有逻辑bug的就完了。呵呵。突然感觉网上的资料太少,所以写这一个系列的文章也想把志同道合的聚集起来,大家一起来讨论虎书。本人毕业半年,有写的不对还希望大家指正。

  这本书的第一章,和其他外国书籍一样,先是讨论了一下本书的结构,需要有怎样的基础以及用到那些工具。然后介绍了编译器的各个方面。就个人而言,像这种总结和概述的章我一般喜欢看完全书以后再回头看看,那个时候就会对整本书有比较深刻的理解。但是这本书第一章给了一个小的练习,总结来说就是利用前面介绍的数据结构和文法规则创建一个计算print数量的函数和一个直线型程序语言翻译器。程序很简单,但是作为入门的练习,个人人为实在太好了。

  第一,这个作业让我开始关注编程语言本身。以前都是将程序语言作为整块去理解,理解其表达的逻辑含义和功能。但是在写这个程序的时候,它让我开始关注语言的每一句成分。首先,语言最基本的成分可以笼统的分为两类,语句(statement)和表达式(expression)。语句是执行完成后没有任何数值的产生,例如打印语句,转移语句,而表达式是有数值的产生的,算数操作,1+2 那么产生了3.

  第二,我然我了解到编程语言是怎么从文本变化到树状结构,如何对树状结构进行操作得到最后的结果。对编译器有了一个感性的了解。

  一下是代码:

计算print的数量

复制代码
#ifndef MAXARGS_H_
#define MAXARGS_H_
#include "slp.h"
int maxargs(A_exp) ;
int maxargs(A_expList) ;
int maxargs(A_stm a_stm) ;
#endif
复制代码
复制代码
#include "maxargs.h"
#include "slp.h"

int maxargs(A_stm a_stm) 
{
    if (a_stm == NULL)
    {
        return 0 ;
    }

    switch(a_stm->kind)
    {
    case A_stm_::A_assignStm :
        return maxargs(a_stm->u.assign.exp) ;
    case A_stm_::A_printStm :
        return 1 + maxargs(a_stm->u.print.exps) ;
    case A_stm_::A_compoundStm:
        return maxargs(a_stm->u.compound.stm1) + maxargs(a_stm->u.compound.stm2) ;
    }
    return 0 ;
}
int maxargs(A_exp a_exp)
{
    if (a_exp == NULL )
    {
        return 0 ;
    }
    switch(a_exp->kind)
    {
    case A_exp_::A_opExp:
        return maxargs(a_exp->u.op.left) + maxargs(a_exp->u.op.right) ;
    case A_exp_::A_eseqExp:
        return maxargs(a_exp->u.eseq.stm) + maxargs(a_exp->u.eseq.exp) ;
    }
    return 0 ;
}
int maxargs(A_expList a_explist)
{
    if (a_explist == NULL)
    {
        return 0 ;
    }
    switch(a_explist->kind)
    {
    case A_expList_::A_pairExpList :
        return maxargs(a_explist->u.pair.head)+maxargs(a_explist->u.pair.tail) ;
    case A_expList_::A_lastExpList:
        return  maxargs(a_explist->u.last) ;
    }
    return 0 ;
}
复制代码

将语言解释并且计算结果

复制代码
#ifndef INTERPRETES_H_
#define INTERPRETES_H_
#include "util.h"
#include "slp.h"
typedef struct table  *Table_ ;
struct table
{
  string id ;
  int value ;
  Table_ tail ;
};
typedef struct intAndTable_ *intAndTable ;
struct intAndTable_
{
    int i ;
    Table_ table ;
};
Table_ interStm(A_stm stm , Table_ t) ;
intAndTable interExp(A_exp exp , Table_ t) ;
intAndTable interExpList(A_expList expList , Table_ t) ;
Table_ update(Table_, string ,int ) ;
int  lookup(Table_ , string) ;
#endif
复制代码
复制代码
#include "interprets.h"
#include "util.h"
#include "slp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Table_ Table(string id ,  int value , Table_ *tail)
{
    Table_ t = Table_(malloc( sizeof(*t)) );
    t->id = id ;
    t->value = value ;
    t->tail = t ;
    return t ;
}

Table_ interStm(A_stm stm , Table_ t)
{
    if (stm == NULL )
    {
        return NULL ;
    }
    Table_ table ;
    intAndTable itable;
    A_expList tmpExplist ;
   switch(stm->kind)
   {
   case A_stm_::A_compoundStm:
     table = interStm(stm->u.compound.stm1 , t) ;
     return interStm(stm->u.compound.stm2 , table) ;
   case A_stm_::A_printStm:
       tmpExplist = stm->u.print.exps ;
       while(1)
       {
           if (tmpExplist->kind == A_expList_::A_lastExpList)
           {
               itable = interExp(tmpExplist->u.last , t) ;
               printf("   %d" , itable->i) ;
               break ;
           }
           else
           {
               itable = interExp(tmpExplist->u.pair.head , t) ;
               printf("  %d" , itable->i) ;
               tmpExplist = tmpExplist->u.pair.tail ;
           }
       }
     printf("\n" ) ;
     return itable->table ;
   case A_stm_::A_assignStm:
       itable = interExp(stm->u.assign.exp ,t) ;
       table = update(itable->table , stm->u.assign.id , itable->i) ;
       return table ;
   }
   return NULL ;
}

intAndTable interExpList(A_expList expList , Table_ t)
{
    if (expList == NULL)
    {
        return NULL ;
    }
    intAndTable tmp ;
    switch(expList->kind)
    {
    case A_expList_::A_lastExpList:
     tmp = interExp(expList->u.last , t) ;
     return tmp ;
    case A_expList_::A_pairExpList:
        tmp = interExp(expList->u.pair.head , t) ;
        tmp = interExpList(expList->u.pair.tail , tmp->table) ;
        return tmp ;
     }
    return NULL ;
}

intAndTable interExp(A_exp exp , Table_ t)
{
    if ( exp == NULL )
    {
        return NULL ;
    }
    intAndTable t1  =  intAndTable(malloc( sizeof(*t))) ;
    int tmp ;
   switch(exp->kind)
   {
   case A_exp_::A_idExp:
     t1->i = lookup(t , exp->u.id) ;
     t1->table = t ;
     return t1 ;
   case A_exp_::A_numExp:
       t1->i = exp->u.num ;
       t1->table = t ;
       return t1 ;
   case A_exp_::A_opExp:
      t1 = interExp(exp->u.op.left , t) ;
      tmp = t1->i ;
      t1 = interExp(exp->u.op.right , t1->table) ;
      switch(exp->u.op.oper)
      {
      case A_plus:
         tmp += t1->i ;
          break ;
      case A_minus:
          tmp -= t1->i ;
          break ;
      case A_times:
          tmp *= t1->i ;
          break ;
      case A_div:
          tmp /= t1->i ;
          break ;
      }
      t1->i = tmp ;
      return t1 ;
   case A_exp_::A_eseqExp:
          t = interStm(exp->u.eseq.stm , t) ;
          t1 = interExp(exp->u.eseq.exp , t) ;
          return t1 ;
   }
   return NULL ;
}

Table_ update(Table_ t, string s ,int v)
{
    Table_ t1 = Table_(malloc( sizeof(*t1))) ;
    t1->id = s ;
    t1->tail = t ;
    t1->value = v ;
    return t1 ;
}

int lookup(Table_ t, string c)
{
    Table_ tmp = t ;
    while(tmp)
    {
        if (tmp->id == c)
        {
            return tmp->value ;
        }
        tmp = tmp->tail ;
    }
    return -1 ;
}
复制代码

这是主函数

复制代码
/* This file is intentionally empty.  You should fill it in with your
solution to the programming exercise. */

#include "prog1.h"
#include "slp.h"
#include "util.h"
#include "interprets.h"
#include "maxargs.h"
void main()
{
    A_stm p ;
    p = prog() ;
    int a = maxargs(p) ;
    printf("the print number is %d\n" , a) ;
    Table_ t = NULL ;
    t = interStm(p , t) ;
}
复制代码

最后结果是 2   8  7  80

转载于:https://www.cnblogs.com/jacksplwxy/p/10052688.html

作者简介: Andrew W.Appel,美国普林斯顿大学计算机科学系教授,第26届ACM SIGPLAN-SIGACT程序设计原理年会大会执行主席,1998-1999年在贝尔实验室做研究工作。主要研究方向是计算机安全、编译器设计、程序设计语言等。 内容简介: 本全面讲述了现代编译器的各个组成部分,包括词法分析、语法分析、抽象语法、语义检查、中间代码表示、指令选择、数据流分析、寄存器分配以及运行时系统等。全分成两部分,第一部分是编译的基础知识,适用于第一门编译原理课程(一个学期);第二部分是高级主题,包括面向对象语言和函数语言、垃圾收集、循环优化、SSA(静态单赋值)形式、循环调度、存储结构优化等,适合于后续课程或研究生教学。中专门为学生提供了一个用C语言编写的实习项目,包括前端和后端设计,学生可以在一学期内创建一个功能完整的编译器。   本适用于高等院校计算机及相关专业的本科生或研究生,也可供科研人员或工程技术人员参考。 目录: 第一部分 编译基本原理 第1 绪论 1 1.1 模块接口 1 1.2 工具和软件 3 1.3 树语言的数据结构 3 程序设计:直线式程序解释器 7 推荐阅读 9 习题 9 第2 词法分析 10 2.1 词法单词 10 2.2 正则表达式 11 2.3 有限自动机 13 2.4 非确定有限自动机 15 2.4.1 将正则表达式转换为NFA 16 2.4.2 将NFA转换为DFA 18 2.5 Lex:词法分析器的生成器 20 程序设计:词法分析 22 推荐阅读 23 习题 23 第3 语法分析 27 3.1 上下文无关文法 28 3.1.1 推导 29 3.1.2 语法分析树 29 3.1.3 二义性文法 30 3.1.4 文件结束符 31 3.2 预测分析 32 3.2.1 FIRST集合和FOLLOW集合 33 3.2.2 构造一个预测分析器 35 3.2.3 消除左递归 36 3.2.4 提取左因子 37 3.2.5 错误恢复 37 3.3 LR分析 39 3.3.1 LR分析引擎 40 3.3.2 LR(0)分析器生成器 41 3.3.3 SLR分析器的生成 44 3.3.4 LR(1)项和LR(1)分析表 45 3.3.5 LALR(1)分析表 46 3.3.6 各类文法的层次 47 3.3.7 二义性文法的LR分析 47 3.4 使用分析器的生成器 48 3.4.1 冲突 49 3.4.2 优先级指导 50 3.4.3 语法和语义 53 3.5 错误恢复 54 3.5.1 用error符号恢复 54 3.5.2 全局错误修复 55 程序设计:语法分析 57 推荐阅读 58 习题 58 第4 抽象语法 62 4.1 语义动作 62 4.1.1 递归下降 62 4.1.2 Yacc生成的分析器 62 4.1.3 语义动作的解释器 64 4.2 抽象语法分析树 65 4.2.1 位置 67 4.2.2 Tiger的抽象语法 68 程序设计:抽象语法 71 推荐阅读 71 习题 72 第5 语义分析 73 5.1 符号表 73 5.1.1 多个符号表 74 5.1.2 高效的命令式风格符号表 75 5.1.3 高效的函数式符号表 76 5.1.4 Tiger编译器的符号 77 5.1.5 函数式风格的符号表 79 5.2 Tiger编译器的绑定 79 5.3 表达式的类型检查 82 5.4 声明的类型检查 84 5.4.1 变量声明 84 5.4.2 类型声明 85 5.4.3 函数声明 85 5.4.4 递归声明 86 程序设计:类型检查 87 习题 87 第6 活动记录 89 6.1 栈帧 90 6.1.1 帧指针 91 6.1.2 寄存器 92 6.1.3 参数传递 92 6.1.4 返回地址 94 6.1.5 栈帧内的变量 94 6.1.6 静态链 95 6.2 Tiger编译器的栈帧 96 6.2.1 栈帧描述的表示 98 6.2.2 局部变量 98 6.2.3 计算逃逸变量 99 6.2.4 临时变量和标号 100 6.2.5 两层抽象 100 6.2.6 管理静态链 102 6.2.7 追踪层次信息 102 程序设计:栈帧 103 推荐阅读 103 习题 103 第7 翻译成中间代码 106 7.1 中间表示树 106 7.2 翻译为树中间语言 108 7.2.1 表达式的种类 108 7.2.2 简单变量 111 7.2.3 追随静态链 112 7.2.4 数组变量 113 7.2.5 结构化的左值 114 7.2.6 下标和域选择 114 7.2.7 关于安全性的劝告 115 7.2.8 算术操作 116 7.2.9 条件表达式 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值