TINY部分源码分析报告
TINY词法分析编译程序的部分实现

TINY编译程序的部分实现TINY的程序结构很简单,它在语法上与Ada或Pascal的语法相似:仅是一个由分号分隔开的语句序列。
另外,它既无过程也无声明。
所有的变量都是整型变量,通过对其赋值可较轻易地声明变量(类似FORTRAN或BASIC)。
它只有两个控制语句:if语句和repeat语句,这两个控制语句本身也可包含语句序列。
if语句有一个可选的else部分且必须由关键字end结束。
除此之外,read语句和write语句完成输入/输出。
在花括号中可以有注释,但注释不能嵌套。
TINY的表达式也局限于布尔表达式和整型算术表达式。
布尔表达式由对两个算术表达式的比较组成,比较使用<与=比较算符。
算术表达式可以包括整型常数、变量、参数以及4个整型算符+、-、*、/,此外还有一般的数学属性。
布尔表达式可能只作为测试出现在控制语句中——而没有布尔型变量、赋值或I/O。
虽然T I N Y缺少真正程序设计语言所需要的许多特征——过程、数组和浮点值,是一些较大的省略——但它足可以用来例证编译器的主要特征了。
TINY编译器简单说明TINY编译器包括以下的C文件,(为了包含而)把它的头文件放在左边,它的代码文件放在右边:globals.h main.cutil.h util.cscan.h scan.cparse.h parse.csymtab.h symtab.canalyze.h analyze.ccode.h code.ccgen.h cgen.c除了将main.c放在globals.h的前面之外,这些文件的源代码及其行号都按顺序列在附录B中了。
任何代码文件都包含了globals.h头文件,它包括了数据类型的定义和整个编译器均使用的全程变量。
main.c 文件包括运行编译器的主程序,它还分配和初始化全程变量。
其他的文件则包含了头/代码文件对、在头文件中给出了外部可用的函数原型以及在相关代码文件中的实现(包括静态局部函数)。
TinyOS学习笔记1

TinyOS学习笔记1-TinyOS安装1、Ubuntu系统的安装安装TinyOS可以在Windows中利用Cygwin进行安装,经过测试在XP中可以正确安装,但是安装的步骤过于麻烦,可以参考官方网站的安装步骤。
在Win7中安装后有问题,不能正确编译。
因此最好使用Linux系统来安装TinyOS,安装过程简单。
安装Ubuntu系统1.Ubuntu的官方网站下载iso镜像,我安装的是10.04版本2.可以有两种方式进行Ubuntu安装。
(1)传统方式安装:在系统中划分出空闲分区,利用U盘制作启动盘,官网有,可下载。
重启系统选择U盘启动。
进行安装。
(2)wubi方式进行安装:以文件形式进行安装,下载wubi,将镜像与wubi放于同一文件夹。
点击wubi进行安装。
3.更新Ubuntu更行Ubuntu时需要注意,更新时grub不更新。
利用wubi安装,我选择了更新grub,重新启动系统出现错误。
解决方法如下:1.另一台电脑,到Ubuntu网站下载镜像,安装到U盘中,制作启动盘。
2.开机,选择从U盘启动,在Boot里设置不好使,像我的ASUS A8,开机按ESC,选择U盘启动。
3.看到Ubuntu的欢迎界面,选择第一项,进入U盘中的Ubuntu系统。
4.在终端中,输入sudo apt-get install lilosudo lilo -M /dev/SD a mbr5.重启系统,问题解决4.使用root登录系统2、在Ubuntu系统下安装TinyOS我安装的时TinyOS2.1.1,安装过程参考TinOS官网的安装指导,但有问题,具体步骤如下:1)在系统的“/etc/apt/sources.list”中,添加如下代码:deb /tinyo ... lt;distribution> main<distribution>可以为(edgy,feisty,gutsy,hardy,jaunty,k ARM ic,lucid)例如 deb /tinyos/dists/ubuntu hardy main以上的源可能有问题,在安装是提示tinyos-2.1.1依赖的包找不到或无法安装,更新源如下解决此问题:deb /tinyos/dists/ubuntu hardy maindeb /tinyos oneiric main2)更新知识库,打开终端,输入sudo apt-get update3)安装TinyOSsudo apt-get install tinyos提示可选的tinyos的版本,选择最新的版本2.1.1sudo apt-get install tinyos-2.1.14)设置环境变量在~/.bashrc或者~/.profile中加入如下代码#Sourcing the tinyos environment variable setup scriptsource /opt/tinyos-2.1.1/tinyos.sh可用如下方法打开~/.bashrc或者~/.profilegedit ~/.bashrc添加成功后需要重新启动终端5)测试是否安装成功cd /opt/tinyos-2.1.1/apps/Blink/(若当前文件夹没有权限创建文件,将Blink复制到当前用户的目录进行运行)make telosb显示如下则安装成功:mkdir -p build/telosbcompiling BlinkAppC to a telosb binaryncc -obuild/telosb/main.exe -Os-O -mdisable-hwmul -fnesc-separator=__ -Wall -Wshadow -Wnesc-all-target=telosb -fnesc-cfile=build/telosb/app.c -board=-DDEFINED_TOS_AM_GROUP=0x22-DIDENT_APPNAME=/"BlinkAppC/"-DIDENT_USERNAME=/"root/"-DIDENT_HOSTNAME=/"ubuntu/"-DIDENT_USERHASH=0xa3473ba6L-DIDENT_TIMESTAMP=0x4c566efbL-DIDENT_UIDHASH=0xd972ea96L BlinkAppC.nc -lmcompiled BlinkAppC to build/telosb/main.exe2648 bytes in ROM54 bytes in RAMMSP430-objcopy --output-target=ihexbuild/telosb/main.exe build/telosb/main.ihexwriting TOS imageTinyOS学习笔记2-TinyOS的IDE-Yeti23.测试TinyOS中的Toosim∙make micaz sim∙提示找不到python2.5∙查看本机python的版本,我的版本为2.6∙进入/opt/tinyos-2.1.1/support/make/sim.extra∙修改python的版本PYTHON_VERSION=2.6∙重新make micazsim∙提示*** Successfullybuilt micaz TOSSIM library.则可运行tossim。
byconity 源码编译

Byconity 源码编译一、引言源码编译是将人类可读的程序代码转换为机器可执行的二进制代码的过程,是软件开发的重要环节。
Byconity 作为一种广泛应用的开源软件,其源码编译过程对于深入理解其功能和性能优化具有重要意义。
本文将详细探讨Byconity 的源码编译过程及其重要性。
二、 Byconity 源码编译的重要性Byconity 源码编译的重要性主要体现在以下几个方面:1.性能优化:通过源码编译,可以生成更加高效的机器代码,从而提高程序的运行速度。
2.安全性增强:源码编译可以隐藏原始代码,增强软件的安全性,防止代码被轻易篡改或窃取。
3.跨平台兼容性:通过调整编译参数,可以在不同操作系统和硬件平台上编译出适应特定环境的二进制文件。
4.定制化功能实现:通过修改源代码和编译选项,可以实现定制化的功能和模块。
三、 Byconity 源码编译的工作原理Byconity 源码编译的过程涉及多个环节,每个环节都有其特定的作用和工作原理。
下面将详细介绍 Byconity 源码编译的工作原理:1.词法分析:源码编译的第一步是将源代码分解成一个个的记号(token),这一过程称为词法分析。
词法分析器将源代码按照语法规则拆分成记号,为后续的语法分析做准备。
2.语法分析:语法分析是源码编译的第二步,其主要任务是将记号组合成语法结构,如表达式、语句、控制流等。
在这个过程中,编译器会检查源代码是否符合语法规则,并构建一棵语法树(parse tree)来表示程序的语法结构。
3.语义分析:语义分析阶段主要进行类型检查、符号表管理以及语义检查等工作。
编译器会检查语法树中的语义是否符合语言规范,并进行相应的类型检查和语义分析。
4.中间代码生成:在语义分析之后,编译器会生成中间代码。
中间代码是一种抽象的代码表示,介于源代码和目标代码之间。
常见的中间代码形式包括三地址码、抽象语法树(AST)等。
5.优化:编译器在生成中间代码之后会进行一系列的优化操作,以提高生成代码的性能。
10.Tiny词法分析器

– 通常在程序中分配一块缓冲区(分配字符串) 之后使用系统方法将文件内的内容读入该缓 冲区,之后分析里面的字符
TINY语言词法分析器实现
字符的读取
使用C语言读取
– 包含头文件 – 打开文件(当前程序与文件建立链接,得到文 件句柄) – 读取(根据句柄调用函数) – 关闭(根据句柄调用函数)
TINY语言词法分析器实现
几个变量的说明
– char tokenString[MAXTOKENLEN];存储单 词的内容,因为单词是由字符组成的,而且 字符是一个一个分析的,所以用一个指针指 向已经存了几个字符 – int tokenStringIndex=0; – 有时分析的字符不是单词,所以用一个变量 来标记当前分析的字符是单词的一部分。 – int save;
• char buf[LEN] • source.getline(buf,LEN-1)
– 判断文件读取是否结束 if(source.eof()) – 关闭文件 source.close();
TINY语言词法分析器实现
getNextChar函数实现
TINY语言词法分析器实现
getToken函数实现
TINY语言词法分析器实现
getToken函数实现,START状态
break;
TINY语言词法分析器实现
getToken函数实现,INCOMMENT状态
TINY语言词法分析器实现
getToken函数实现,INASSIGN状态
TINY语言词法分析器实现
getToken函数实现,INNUM状态
TINY语言词法分析器实现
getToken函数实现,INID状态
TINY语言词法分析器实现
getToken函数实现,其它状态
tcc研究tinyccompiler最小的c语言编译器自己编译自己

TCC研究(1) Tiny C Compiler最小的C语言编译器,自己编译自己原创2015年03月22日02:16:55最近,在学习编译器技术,研究了一下TCC,记录一下。
Tiny C Compiler(简称TCC, 或Tiny CC)是世界上最小的C 语言编译器,而且是开源的,小到只有约100K. (VC, GCC 动不动几十M几百M的, 汗)别看它小, 功能还是很强. 可以编译所有C99标准的ANSI C 程序, 支持CPU包括:X86 32或64位, ARM,支持Windows, Linux, OSX.(跨平台跨系统的能力,比VC强)TCC是由大牛Fabrice Bellard开发的,这位大牛还开发过Qemu, FFMpeg (没有FFMpeg, 就没有抄它的腾讯视频,暴风影音...)一、下载TCC主页:/tcc/下载页:/releases/tinycc/TCC最新版本是0.9.26下载执行程序:tcc-0.9.26-win32-bin.zip 无需安装的,只需要解压即可。
解压缩到c:\tcc , 可见目录下有tcc.exe, 这个是编译器命令行程序,没有IDE界面的将c:\tcc 加入到系统路径中(PATH)后,则可以在任何命令行窗口中使用了。
二、使用TCC用notepad写一个测试用的c程序,如下,存盘为hello.c [html] view plain copy #include <stdio.h> main() { printf("hello,world\n"); }用tcc编译,命令如下:tcc hello.c则将生成hello.exe , 运行hello.exe看看TCC可以不编译C程序,而是把它直接运行,就像脚本解释语言那样。
命令行如下:tcc -run hello.c效果:hello.c不需编译,直接运行了这个将C程序直接运行的功能,是TCC独有的,其它C编译器都不行。
TINY部分源码分析报告

TINY部分源码分析报告TINY是一种简单的编程语言,用于教学目的。
它的语法规则非常简单,只有几个基本的关键字和语句。
在这篇报告中,我将对TINY的部分源码进行分析。
首先,让我们来看一下TINY的词法分析器部分的源码。
TINY的词法分析使用了一种基于有限自动机的方法。
源码中定义了几个关键字和运算符的正则表达式模式,并使用这些模式进行匹配。
如果匹配成功,就返回对应的记号。
接下来是语法分析器部分的源码。
TINY的语法分析使用了递归下降的方法。
源码中定义了几个非终结符的函数,每个函数对应语法中的一个产生式。
函数根据当前输入的记号,选择适当的产生式,并继续递归下降,直到匹配整个输入。
TINY的语法规则非常简单,只有if语句、while语句、表达式、赋值语句等几个基本的语法结构。
在语法分析器的源码中,每个函数都对应一个语法规则。
例如,函数parseStatement用于解析语句,它根据当前输入的记号,选择适当的产生式,例如if语句的产生式或赋值语句的产生式。
为了简化语法分析过程,TINY使用了LL(1)文法。
LL(1)文法是指,对于任意一个非终结符X和一个记号a,最多只有一个产生式可以选择。
这样可以使得语法分析过程更加简单和高效。
除了词法分析器和语法分析器,TINY还包括了一个解释器部分的源码。
解释器使用了递归下降的方法,根据语法分析的结果进行解释执行。
解释器遵循TINY的语义规则,例如执行赋值语句将变量的值更新为表达式的值。
总结起来,TINY是一种简单的编程语言,它的源码包括词法分析器、语法分析器和解释器部分。
词法分析器负责将源代码转化为记号序列,语法分析器负责根据记号序列生成抽象语法树,解释器负责执行抽象语法树中的操作。
TINY的源码采用了有限自动机和递归下降的方法,通过正则表达式模式和LL(1)文法来进行匹配和选择。
整个源码非常简洁,适合用于教学和学习。
tinycbor例子-概述说明以及解释

tinycbor例子-概述说明以及解释1.引言1.1 概述概述部分的内容可以包括对于tinycbor的基本介绍和背景说明。
可以提及tinycbor是一个用于在嵌入式系统中解析和生成CBOR(Concise Binary Object Representation,一种轻量级二进制数据格式)数据的开源库,旨在提供一种高效、可靠的方式来处理CBOR数据。
CBOR是一种字节节省、速度快的二进制数据序列化格式,被广泛应用于网络通信、数据存储和设备间的数据交换。
而tinycbor作为一个轻量级的库,旨在简化CBOR数据的处理,使得开发人员能够更快速、更高效地解析和生成CBOR格式的数据。
相比于其他CBOR库,tinycbor具有体积小、资源消耗低和解析效率高的特点,适用于各种嵌入式设备和资源受限的环境。
它提供了简洁的API,使得开发人员能够轻松地将CBOR数据集成到自己的应用程序中。
本文将介绍tinycbor的基本原理、应用场景以及其在嵌入式系统中的优势。
通过分析它的价值和意义,我们可以更好地了解其在实际应用中的作用,并展望tinycbor在未来的发展前景。
结尾部分将对整篇文章进行总结,给出本文的观点和意见。
在接下来的章节中,我们将逐一深入探讨tinycbor的各个方面,希望能给读者带来一定的启发和帮助。
1.2文章结构1.2 文章结构本文将按照以下结构进行介绍和讨论tinycbor的相关内容:1. 引言:首先,我们将对文章进行一个简单的引言,介绍tinycbor 的背景和基本概述。
2. 正文:接下来,我们将深入探讨tinycbor的不同方面。
具体而言,我们将重点介绍:2.1 什么是tinycbor:首先,我们将对tinycbor进行详细的定义,阐述其核心概念和主要特征。
我们将讨论其轻量级的特性和对数据的高效编码能力。
2.2 tinycbor的应用场景:在本节中,我们将介绍tinycbor在实际应用中的一些典型场景。
Tiny+编译器

10. true
false
or
and
not
int
bool
string
while
do
if
then
else
end
repeat
until
read
write
11. All keywords are reserved and must be written in lowcase
12. 2.
Special symbols are the following:
17.
Identifier is letter followed by letters and digits
18. NUM=digit digit*
19. STRING=' any character except ' '
20. A STRING is enclosed in brackets '…', any character except ' can appear in a
39. 12
read‐stmt
‐> read identifier
40. 13
write‐stmt
‐> write exp
41. 14
exp
‐> arithmetic‐exp | bool‐exp | string‐exp| comparison‐exp
42. 15
comparison‐exp ‐> arithmetic‐exp comparison‐op arithmetic‐exp
30. 3
decl
‐> type‐specifier varlist
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
TINY源码分析一、文件概述MAIN.C: 主函数GLOBALS.H:全局定义的文件SCAN.C/SCAN.H: 词法分析PARSE.C/PARSE.H:语法分析UTIL.C/UTIL.H:构造树SYMTAB.C/SYMTAB.H:符号表CGEN.C/CGEN.H:生成"汇编代码"CODE.C/CODE.H:这个只是用来把分析过程输出到屏幕的.二、各个文件的分析1.MAIN.C:主要有三个FILE*句柄:source--源代码文件。
listing--显示分析过程的文件,这里重定向到stdout。
code--目标汇编代码文件。
从该文件中可知程序运行的流程:检查参数正确否(tiny.exe filename)->构造语法树(调用parse函数)->根据语法树生成代码(调用codeGen函数,该函数又调用cGen函数。
2.GLOBALS.H:定义了关键字个数8个。
定义了关键字,运算符等内容的枚举值。
定义了语句类型的枚举值,这个决定树的结点。
定义了变量类型(也就三种,void, integer, boolean)。
定义了树的节点--这个最重要了!!其结构如下所示:typedef struct treeNode{struct treeNode * child[MAXCHILDREN];struct treeNode * sibling;int lineno;NodeKind nodekind;union { StmtKind stmt; ExpKind exp;} kind;union { TokenType op;int val;char * name; } attr;ExpType type; /* for type checking of exps */} TreeNode;3.UTIL.C/UTIL.H主要函数TreeNode * newStmtNode(StmtKind kind)此函数创建一个有关语法树的声明节点TreeNode * newExpNode(ExpKind kind)此函数创建一个有关语法树的表述节点char * copyString(char * s)此函数分配和创建一个新的已存在树的复制void printTree( TreeNode * tree )输出一个语法树这两个文件主要是关于语法树的创建和输出4.SCAN.c/SCAN.H主要有这么几个函数:static int getNextChar(void);static void ungetNextChar(void);static TokenType reservedLookup (char * s);TokenType getToken(void);reservedLookup函数是查找关键字的,在符号表中找。
这里还定义了一个保存关键字的结构:static struct{ char* str;TokenType tok;} reservedWords[MAXRESERVED]={{"if",IF},{"then",THEN},{"else",ELSE},{"end",END},{"repeat",REPEAT},{"until",UNTIL},{"read",READ},{"write",WRITE}};最重要的是getToken(void)函数。
这个相当于lex的功能,进行词法分析。
也就是一个DFA,switch后面跟了一堆的case。
其中getNextChar(void)函数的思路,以下列出:static int getNextChar(void){if (!(linepos < bufsize)){lineno++;if (fgets(lineBuf,BUFLEN-1,source)){if (EchoSource) fprintf(listing,"%4d: %s",lineno,lineBuf); bufsize = strlen(lineBuf);linepos = 0;return lineBuf[linepos++];}else{EOF_flag = TRUE;return EOF;}}else return lineBuf[linepos++];}4.PARSE.C/PARSE.H有这么几个函数:TreeNode * parse(void)static TreeNode * stmt_sequence(void);static TreeNode * statement(void);static TreeNode * if_stmt(void);static TreeNode * repeat_stmt(void);static TreeNode * assign_stmt(void);static TreeNode * read_stmt(void);static TreeNode * write_stmt(void);static TreeNode * exp(void);static TreeNode * simple_exp(void);static TreeNode * term(void);static TreeNode * factor(void);最重要的是parse这个函数,就是用来构造整个程序的语法树的。
下面的一堆私有函数构造相应语法的语法树,然后parse最后把它们这些子树整合成一个大树。
5.SYMTAB.C/SYMTAB.H这个是符号表操作的,也就是词法分析的时候查找表,看该token是不是关键字。
如果不是,就当作表识符添加进去。
在语法分析的时候也要用到,看变量有没有声明的时候用的。
三、实验心得:通过这次实验,仔细地去查看和分析了TINY编译器的部分源码。
了解到了编译器的运行:检查参数正确否(tiny.exe filename)->构造语法树(调用parse函数)->根据语法树生成代码(调用codeGen函数),同时熟悉了编译器是如何使用prase函数进行语法树的构建以及语法树生成代码的转化,最主要的是进一步清晰了解到编译器的构造和运行原理,加深了对课本知识的运用和拓展,感觉收获很大!Main.c/****************************************************//* File: main.c *//* Main program for TINY compiler *//* Compiler Construction: Principles and Practice *//* Kenneth C. Louden *//****************************************************/#include "globals.h"/* set NO_PARSE to TRUE to get a scanner-only compiler ,NO_PARSE为true时创建一个只扫描的编译器*/#define NO_PARSE FALSE/* set NO_ANALYZE to TRUE to get a parser-only compiler ,NO_ANALYZE为true 时创建一个只分析和扫描的编译器*/#define NO_ANALYZE FALSE/* set NO_CODE to TRUE to get a compiler that does not* generate code NO_CODE为true时创建一个执行语义分析,但不生成代码的编译器*/#define NO_CODE FALSE#include "util.h"#if NO_PARSE#include "scan.h" //如果NO_PARSE为true,调用头文件scan.h#else#include "parse.h" //否则调用头文件prase.h#if !NO_ANALYZE#include "analyze.h" //如果NO_ANALYZE为true,调用头文件analyze.h#if !NO_CODE#include "cgen.h" //如果NO_CODE为true,调用头文件cgen.h#endif#endif#endif //结束预处理语句符号/* allocate global variables 分配全局变量*/int lineno = 0;FILE * source; //指针指向源代码文件地址FILE * listing; //指针指向显示分析过程的文件的地址FILE * code; //指针指向目标汇编代码文件的地址/* allocate and set tracing flags 分配和设置跟踪标志*/int EchoSource = FALSE;int TraceScan = FALSE;int TraceParse = FALSE;int TraceAnalyze = FALSE;int TraceCode = FALSE;int Error = FALSE; //跟踪标志全部初始化为falsemain( int argc, char * argv[] ){ TreeNode * syntaxTree;char pgm[120]; /* source code file name */if (argc != 2){ fprintf(stderr,"usage: %s <filename>\n",argv[0]);exit(1); //如果argv不为2,打印显示信息并退出}strcpy(pgm,argv[1]) ; //复制argv[1]地址以null为退出字符的存储器区块到另一个存储器区块品pgm内if (strchr (pgm, '.') == NULL)strcat(pgm,".tny"); //把.tyn文件所指字符串添加到pgm结尾处并添加'\0'。
source = fopen(pgm,"r"); //以只读的方式打开pgm文件,并将指向pgm文件的指针返回给sourceif (source==NULL){ fprintf(stderr,"File %s not found\n",pgm);exit(1); //如果源代码文件为空,打印显示信息并退出}listing = stdout; /* send listing to screen 清单发送到屏幕*/fprintf(listing,"\nTINY COMPILATION: %s\n",pgm); //答应显示语句#if NO_PARSEwhile (getToken()!=ENDFILE); //如果输入流没有结束就继续进行循环,直至结束#elsesyntaxTree = parse();//调用prase()函数构造语法树if (TraceParse) {fprintf(listing,"\nSyntax tree:\n");printTree(syntaxTree); // 如果语法分析追踪标志为TRUE且没有语法错误,则将生成的语法树输出到屏幕}#if !NO_ANALYZEif (! Error){ if (TraceAnalyze) fprintf(listing,"\nBuilding Symbol Table...\n");buildSymtab(syntaxTree); //输出含符号表信息的语法树if (TraceAnalyze) fprintf(listing,"\nChecking Types...\n");typeCheck(syntaxTree);//输出含类型检查的语法树if (TraceAnalyze) fprintf(listing,"\nType Checking Finished\n");//打印结束信息}#if !NO_CODEif (! Error){ char * codefile;int fnlen = strcspn(pgm,".");codefile = (char *) calloc(fnlen+4, sizeof(char));strncpy(codefile,pgm,fnlen);strcat(codefile,".tm"); //将源文件名,去掉扩展名,添加扩展名.tmcode = fopen(codefile,"w");//以只写的方式打开目标汇编代码文件,并返回地址给codez指针if (code == NULL){ printf("Unable to open %s\n",codefile);exit(1); //如果code指针为空,打印显示信息并退出}codeGen(syntaxTree,codefile);//目标代码生成fclose(code);}#endif#endif#endif//结束之前对应的条件编译fclose(source); //关闭源代码文件return 0;}GLOBALS.H/****************************************************//* File: globals.h *//* Global types and vars for TINY compiler *//* must come before other include files *//* Compiler Construction: Principles and Practice *//* Kenneth C. Louden *//****************************************************/#ifndef _GLOBALS_H_#define _GLOBALS_H_ //宏定义#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h> //头文件引用#ifndef FALSE#define FALSE 0 //定义FALSE为0#endif#ifndef TRUE#define TRUE 1 //定义TRUE为1#endif/* MAXRESERVED = the number of reserved words */#define MAXRESERVED 8 //定义了关键字个数8个typedef enum/* book-keeping tokens */{ENDFILE,ERROR,/* reserved words */IF,THEN,ELSE,END,REPEAT,UNTIL,READ,WRITE,/* multicharacter tokens */ID,NUM,/* special symbols */ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI } TokenType; // 定义了关键字,运算符等内容的枚举值extern FILE* source; /* source code text file源代码地址*/extern FILE* listing; /* listing output text file 显示分析过程的文件的地址*/extern FILE* code; /* code text file for TM simulator 目标汇编代码文件的地址*/ extern int lineno; /* source line number for listing *//**************************************************//*********** Syntax tree for parsing ************//**************************************************/typedef enum {StmtK,ExpK} NodeKind;//定义了语句类型的枚举值,这个决定树的节点typedef enum {IfK,RepeatK,AssignK,ReadK,WriteK} StmtKind;typedef enum {OpK,ConstK,IdK} ExpKind;/* ExpType is used for type checking */typedef enum {Void,Integer,Boolean} ExpType;//定义了变量类型#define MAXCHILDREN 3 //定义了最大子节点typedef struct treeNode//定义了树的节点{ struct treeNode * child[MAXCHILDREN];struct treeNode * sibling;int lineno;NodeKind nodekind;union { StmtKind stmt; ExpKind exp;} kind;union { TokenType op;int val;char * name; } attr;ExpType type; /* for type checking of exps */} TreeNode;/**************************************************//*********** Flags for tracing ************//**************************************************//* EchoSource = TRUE causes the source program to* be echoed to the listing file with line numbers* during parsing*/extern int EchoSource;/* TraceScan = TRUE causes token information to be* printed to the listing file as each token is* recognized by the scanner*/extern int TraceScan;/* TraceParse = TRUE causes the syntax tree to be* printed to the listing file in linearized form* (using indents for children)*/extern int TraceParse;/* TraceAnalyze = TRUE causes symbol table inserts* and lookups to be reported to the listing file*/extern int TraceAnalyze;/* TraceCode = TRUE causes comments to be written* to the TM code file as code is generated*/extern int TraceCode;/* Error = TRUE prevents further passes if an error occurs */extern int Error;#endifSCAN.C/* 词法扫描程序*/#include "globals.h"#include "util.h"#include "scan.h"/*定义的状态*/typedef enum{START, /*初始状态*/INASSIGN, /*进入到赋值状态*/INCOMMENT, /*进入到注释状态*/INNUM, /*进入到数字状态*/INID, /*进入到标志符状态*/DONE /*状态结束*/}StateType;/*每当语法分析程序需要一个单词时,就调用该子程序,得到(类别码,单词的值)*/ /* 语义标识符和保留字*/char tokenString[MAXTOKENLEN+1];/* BUFLEN = 源代码的输入缓冲长度*/#define BUFLEN 256static char lineBuf[BUFLEN]; /* 当前行*/static int linepos = 0; /* 在linebuf中的当前位置*/static int bufsize = 0; /* 缓冲区的字符串当前大小*/static int EOF_flag = FALSE; /* 如果读入下一个字符出错,设置EOF_flag为假。