编译原理 - 语法制导翻译

简介: 编译原理 - 语法制导翻译

语法制导翻译


  • 编译器在做语法分析过程中除了回答程序语法是否合法外,还必须完成后续工作
  • 可能的工作包括(但是不限于)
  • 类型检查
  • 目标代码生成
  • 中间代码生成
  • …等等
  • 这些后续的工作一般可通过语法制导的翻译完成


LR分析中的语法制导翻译


在之前的加法中实现语法制导翻译

%{
    #include <stdio.h>
    #include <stdlib.h>
    int yylex();
    void yyerror();
%}

%left '+'

%%
lines: line
     | line lines
;
line: exp '\n' {printf("value=%d\n", $1);}
;
exp: n              {$$=$1;}
    | exp '+' exp   {$$=$1+$3;}
;
n: '1'  {$$=1;}
 | '2'  {$$=2;}
 | '3'  {$$=3;}
 | '4'  {$$=4;}
 | '5'  {$$=5;}
 | '6'  {$$=6;}
 | '7' | '8' | '9' | '0';

%%

int yylex()
{
    return getchar();
}

void yyerror(char *s)
{
    fprintf(stderr, "%s\n", s);
    return;
}

int main(int argc, char **argv)
{
   yyparse();
   return 0;
}


基本思想


  • 给每条产生式规则附加一个语义动作
  • 一个代码片段
  • 语义动作在产生式“归约”时执行
  • 即由右部的值计算左部的值
  • 以自底向上的技术为例进行讨论
  • 自顶向下的技术与此类似


抽象语法树


将分析树的浓缩过程生成的树是抽象语法树


分析树


  • 分析树编码了句子的推导过程


  • 但是包含很多不必要的信息

注意:这些节点要占用额外的存储空间


  • 本质上,这里的那些信息是重要的?

对于表达式而言,编译只需要知道运算符和运算数

优先级、结合性等已经在语法分析部分处理掉了

对于语句、函数等语言其他构造而言也一样

例如:编译器不关系赋值符号是=还是:=或者其他符号


具体语法和抽象语法


  • 具体语法是语法分析器使用的语法
  • 必须适合语法分析,如各种分隔符、消除左递归、提取左公因子等
  • 抽象语法是用来表达语法结构的内部表示
  • 现代编译器一般都采用抽象语法作为前端(词法语法分析)和后端(代码生成)的接口


抽象语法树的数据结构


  • 在编译器中,为了定义抽象语法树,需要使用实现语言来定义一组数据结构

和实现语言密切相关


  • 早期的编译器有的不采用抽象语法树数据结构

直接在语法制导翻译中生成代码

但现代的编译器一般采用抽象语法树作为语法分析器的输出

更好的系统支持

简化编译器的设计


抽象语法树的自动生成


  • 在语法动作当中,加入生成语法树的diam
  • 代码片段一般是语法树的构造函数
  • 在产生式归约的时候,会自底向上构造整棵树
  • 从叶子到根

抽象语法树是编译器前端和后端的接口

  • 程序一旦被转换为抽象语法树,则源代码即被丢弃
  • 后续的阶段只处理抽象语法树

所以抽象语法树必须编码足够多的源代码信息

  • 例如:它必须编码每个语法结构在原代码中的位置(文件,行号、列号等)
  • 这样,后续的检查阶段才能精确的报错
  • 或者获取程序的执行刨面

抽象语法书必须仔细设计

目录
相关文章
|
C++
C++语言学习基本语法应用案例
C++语言学习基本语法应用案例
67 0
|
8月前
|
存储 算法 C语言
【C 言专栏】C 语言中的字符串处理技巧
【5月更文挑战第5天】本文介绍了C语言中字符串处理的关键技巧,包括定义与初始化(如直接赋值和使用`strcpy()`)、输入输出(`scanf()`和`printf()`)、长度计算(`strlen()`)、比较(`strcmp()`)、查找与替换、拼接(`strcat()`)、截取(`strncpy()`)、转换(如`itoa()`和`atoi()`)、遍历以及注意事项(内存管理、边界检查和效率)。通过案例分析和探讨未来趋势,助力提升字符串处理能力。
164 2
【C 言专栏】C 语言中的字符串处理技巧
|
7月前
|
自然语言处理 容器
S语言词法分析器设计
还有很多需要优化的地方,作为小白发出了也和大家一起交流下,这次我是分文件写的,因为考虑到以后的实验都用这一套代码,分文件写方便一点,用的是C++14标准
40 0
|
8月前
|
程序员 编译器 C语言
【C 言专栏】C 语言中的预处理器指令
【5月更文挑战第6天】C 语言的预处理器指令在编译前起作用,提供代码灵活性。常见指令包括:`#define`(定义常量和宏)、`#include`(包含文件)、`#if` 等条件编译指令,以及`#pragma`(编译器特定指示)。合理使用能提升代码可读性和可维护性,但过度使用可能导致复杂性增加。注意其文本替换性质及顺序处理,避免头文件重复包含。预处理器在实际应用中用于实现不同功能和配置,是成为优秀 C 语言程序员的关键技能之一。
109 0
【C 言专栏】C 语言中的预处理器指令
|
自然语言处理 数据库连接
编译原理(五) 语言的定义
编译原理(五) 语言的定义
166 0
|
自然语言处理 网络安全 C语言
【编译原理】第二章,词法分析(更新)
【编译原理】第二章,词法分析
编译原理(四) 语言及其文法的基本概念
编译原理(四) 语言及其文法的基本概念
101 0
|
IDE 编译器 Linux
C语言编程语法—语法风格
在一个标准的C语言程序中,最特殊的莫过于main函数了,而说到底它就是一个函数而已,仅仅因为它地位特殊拥有第一执行权力,换句话说,难道因为一个人是省长它就不是人类了?所以函数该有的它都应该有,那么函数还有什么呢?
|
Python
Python编程语言基础_语法入门——文本和字符集
Python编程语言基础_语法入门——文本和字符集
94 0
Python编程语言基础_语法入门——文本和字符集
|
SQL JavaScript 前端开发
各种计算机语言简短简介
各种计算机语言简短简介
197 0

热门文章

最新文章