编译技术图示(第二章 实现一个简单的编译器)
- 辨析:
- 表达式———————有值
- 语句———有分号————
- 语法和语义分开定义规则
- 源代码—(词法分析,分割分类)—>单词符号流—(语法分析,与BNF语法规则)—>抽象语法树/Token序列
1、词法分析
词法分析器所需函数
取一个字符 getChar
将当前字符加到当前已识别子串 addChar
跳过多余空格/注释 getNonBlank
关键字检查 checkKeywords
符号检查 checkSymbol
2、语法定义BNF
1.1描述方法
1)词法定义:词素/终结符(不可分解),eg:关键字
2)语法定义:非终结符,eg:while语句
3)用大小写区分这两类语法成分
4)语句先用汉语说出来,最后用英文描述(eg:“stmt”语句)
表示中用符号:“—>”表示(具有如下形式,左词素句/非终结符句,右语句名/非终结符名),“|”或者
1.2检验是否符合语言规则——规则放旁边“—>”
1)归约:由具体到抽象(自下而上)将所有终结符化为非终结符
2)推导:由抽象到具体(自上而下)将所有非终结符化为终结符
- 递归下降分析法
- 规则:
- 每个非终结符对应一个解析函数
- 语法规则右侧为其左侧非终结符对应的“函数体”
- ‘+’与‘-’属于ASCⅡ,可用match()
- 空串(|ε):遇到不符前规则则认为遇到空串,则判正(原本判负),但不消耗此终结符。(空串是想要多少个就有多少个)
- 递归调用A{A B }死循环,A{B A}
- 关于函数体:
- 右侧终结符对应从输入串中消耗(advance)该终结符
- 右侧非终结符对应函数调用
- “|”对应“if-else”语句
- 两个函数模式:
- 1)void:
- 终结符:if!match(){报错;结束}advance();消耗
- 函数调用:直接调用
- 2)int:
- 终结符:if!match(){报错,return 0}advance();消耗
- 函数调用:if!match(函数调用){报错;return 0}advance();消耗
- 最后位直接 return函数调用;
- 1)void:
- 串 i+i*i# 递归下降分析过程
- 规则:
1.3建立抽象语法树
抽象语法树AST
是源代码的抽象语法结构的树状表现
不保留仅语法用的符号
与具体语法树相对应
包括语法规则中的各种符号
抽象语法树 结点类型 设计
3、语义分析
1)符号表
2)类型检查
3)类型转换
隐式(自动)转换
显式(强制)转换
两种转换方式:(1)扩展(2)收缩
4)中间代码(三地址码)
三地址代码中的地址 既代表地址,又表示其对应的值,类似于高级语言
实际编译器的三地址代码类似于汇编语言,即:把地址 与 值 分开保存,要么是值,要么是地址
LLVM:clang -emit-llvm -S ./llvm_example.c
三地址代码生成