编译原理 lex yacc 的联合使用 实验报告
编译原理 利用lex生成c语言的词法分析程序 实验报告

《编译原理》课程实验报告题目利用lex生成c语言的词法分析程序专业班级学号姓名一. 实验题目利用lex生成c语言的词法分析程序二. 实验日期三. 实验环境(操作系统,开发语言)操作系统是Windows开发语言是C语言四. 实验内容(实验要求)利用flex,仿教材p227的pascal语言的词法分析程序,经过适当修改后,遵照教材p48-图4.1和p50-表4.1编写自己的类别码。
要求:1.生成的词法分析程序要求能够对给定的任意c程序进行词法分析,并生成文档输出。
2.词法分析程序能够识别关键字、运算符、分界符、标识符、常量(至少是整形常量,可以自己扩充识别其它常量)等,并能处理注释、部分复合运算符(如>=等)。
3.交 .l 文件,c源文件、输出分析结果文件及实验报告。
五. 实验步骤(1)遵照教材p48-图4.1和p50-表4.1,自己编写自己的类别编码。
(2)仿教材p227,pascal语言的词法分析程序,经过适当的修改后输入记事本中,保存格式为.l文件。
(3)在DOS环境下,利用flex运行.l文件,生成lex.yy.c文件。
(4)用c-free打开lex.yy.c文件,检查是否有错误并运行,生成lex.yy.exe 文件。
(5)可利用此程序运行任意的c程序进行词法分析。
六. 实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)1.此次实验让我进一步熟悉了词法分析程序lex的运用,熟悉了模式的运用方法及其格式的运用。
2.要使词法分析程序能够识别c程序中任意的关键字、运算符、分界符、标识符、常量,必须对这五类单词符号非常熟悉,因此还需要加强巩固c语言这方面的知识。
3.由于对pascal语言的陌生,在将代码修改为c语言的过程中,更多的只是跟着老师说的改,至于为什么这么改并不是很清楚,这其中一个原因是对各种模式的运用和理解的欠缺。
因此需要不断进行总结。
七. 实验结果(关键源代码)单词符号输出形式(表格)如下:。
编译原理-实验二-FLEX词法分析器

编译原理-实验⼆-FLEX词法分析器FLEX词法分析器⼀、Lex和Yacc介绍Lex 是⼀种⽣成扫描器的⼯具。
扫描器是⼀种识别⽂本中的词汇模式的程序。
⼀种匹配的常规表达式可能会包含相关的动作。
这⼀动作可能还包括返回⼀个标记。
当 Lex 接收到⽂件或⽂本形式的输⼊时,它试图将⽂本与常规表达式进⾏匹配。
它⼀次读⼊⼀个输⼊字符,直到找到⼀个匹配的模式。
如果能够找到⼀个匹配的模式,Lex 就执⾏相关的动作(可能包括返回⼀个标记)。
另⼀⽅⾯,如果没有可以匹配的常规表达式,将会停⽌进⼀步的处理,Lex 将显⽰⼀个错误消息。
Yacc代表 Yet Another Compiler Compiler 。
Yacc 的 GNU 版叫做 Bison。
它是⼀种⼯具,将任何⼀种编程语⾔的所有语法翻译成针对此种语⾔的 Yacc 语法解析器。
(下载下载flex和bison。
⽹址分别是/packages/flex.htm和/packages/bison.htm。
)⼆、配置环境(win7)①下载flex和bison并安装到D:\GnuWin32(尽量是根⽬录)②由于我们使⽤的flex和bison都是GNU的⼯具,所以为了⽅便,采⽤的C/C++编译器也采⽤GNU的编译器GCC,当然我们需要的也是Windows版本的GCC了。
所以提前准备好VC 6.0③检验是否可以进⾏lex⽂件编译1.新建⽂本⽂件,更改名称为lex.l,敲⼊下⾯代码%{int yywrap(void);%}%%%%int yywrap(void){return 1;}2.新建⽂本⽂件,更改名称为yacc.y,敲⼊下⾯代码%{void yyerror(const char *s);%}%%program:;%%void yyerror(const char *s){}int main(){yyparse();}我们暂且不讨论上⾯代码的意思。
打开控制台,进⼊到刚才所建⽴⽂件(lex.l,yacc.y)所在的⽂件夹。
编译原理lexyacc的联合使用实验报告

编译原理lexyacc的联合使用实验报告《编译原理》课程实验报告题目lex yacc 的联合使用专业班级学号姓名一. 实验题目lex yacc 的联合使用二. 实验日期三. 实验环境(操作系统,开发语言)操作系统是Windows开发语言是C语言四. 实验内容(实验要求)目的:熟悉lex和yacc的接口要求:(1)能对整数、实数进行带变量的四则运算(2)词法分析用lex实现(3)语法分析用yacc实现(4)交源代码和实验报告五. 实验步骤1.在实验二的基础上修改代码,并添加上以下的代码:double { return DOUBLE;}EOF { return 0;}{ID} { return ID;}2.在DOS环境下按照之前的步骤利用flex运行myleb.l,修改其中的错误之后,生成lex.yy.c文件。
3.参照书中第14章第7节和myparser-fifth.y文件中的代码,和老师说的思路修改myparser-sixth.y文件,按照实验要求修改代码。
4.在DOS环境下利用yacc运行myparser-sixth.y文件,会有出错提示,按照出错的地方指示,修改代码,使其最终能通过运行,生成y.tab.c文件。
(此步骤还未完成)5.打开c-free5.0,新建工程,在Source files文件夹中添加之前生成的lex.yy.c文件和y.tab.c文件,然后找到已给的calc.h文件,将其添加到新建工程中的Header files文件夹中,这时就能将三个文件组成一个类似于.exe文件类型的文件,最后运行。
6.运行并调试成功。
六. 实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)这是最后一次实验了,但这次的难度是有史以来最难的一次实验,因为要结合之前我们学到的所有东西。
首先要修改.l文件的代码,再把此文件用lex运行,即词法分析部分用lex 完成;然后是修改myparser-sixth.y文件,尽管有参照的代码,但是要自己实现能对整数和实数进行带变量的四则运算,对于还没有完全掌握.y文件编写的我还是太有难度了,自己先是完成了只对实数的运算,也能运行,但只要添加上实数就会出错,研究了很久,还是没有找出来哪里还有错误;有时候也会出现用yacc运行没错误,但用c-free运行就会出错,提示说.h文件有错误,找了半天,也修改了很多。
实验报告程序说明

“程序语言设计与实现”实习题
一、编译程序构造实验
1.题目:利用Lex与Yacc实现一个小语言的编译。
2.目的:通过Lex与Yacc(或Flex与Bison)的实习,熟悉和掌握最常用的编译程序自动产生工具的原理、方法与应用。
3.要求:
(1)设计一个小语言,并对你要实现的小语言进行语法等描述;
(2)在UNIX环境或WINDOWS环境安装Lex与Yacc(或Flex与Bison)工具;
(3)利用Lex与Yacc(或Flex与Bison)工具实现该小语言的编译程序;
(4)、提交实验报告。
二、函数式程序语言实验
1.题目:函数式程序语言实验。
2.目的:通过实验理解函数式程序语言的基本概念和特征。
3.要求:
(1)在网上下载开源的ML(或Scheme)软件,并安装运行;
(2)用ML(或Scheme)编写2~3道程序并上机验证通过;
(3)提交实验报告,写出使用该语言的体会。
三、逻辑式程序语言实验
1.题目:逻辑式程序语言实验。
2.目的:通过实验理解逻辑式程序语言的基本概念和特征。
3.要求:
(1)在网上下载开源的PROLOG软件,并安装运行;
(2)用PROLOG编写2~3道程序并上机验证通过;
(3)提交实验报告,写出使用该语言的体会。
编译原理实验报告5

编译原理实验报告五年月日姓名学号姓名学号系年级 2012级专业计算机科目编译原理题目验证Yacc的使用实验目的熟悉语法分析器生成工具Yacc的使用,并学会在cygwin下使用bison工具编译Yacc文法说明文件。
学习如何使用lex和yacc合作进行语法分析。
实验内容根据给出的calculator例子(calculator0,calculator1,calculator2,calculator3)完成下面题目:用lex 和yacc写一个计算布尔表达式真值的计算器。
实验要求输入为一个布尔表达式,以换行结束。
输出为这个布尔表达式的真值(true 或false)。
尝试二义文法和非二义文法两种不同的实现方式。
布尔表达式二义文法为:S –> S or S | S and S | not S | (S) | true | false,其中优先级or < and < not,or 和 and 左结合,not 右结合。
非二义文法请参照表达式非二义文法自己写出来。
cygwin下用flex,bison和gcc工具将实验调试通过,并写出测试例测试正确性。
实验参考:calculator0-3这四个例子。
请认真阅读例子,发现错误及时提出。
代码编写或修改实验结果非二义:二义(版本1,未去掉对于运算结合性的定义):以上的内容按照我们的计算顺序都是对的,一开始无法相通为什么二义与非二义的结果相同,后来明白了,于是有了下面的一个版本的结果。
二义(版本2,去掉了运算结合性的定义)这两项本来应该的结果与其相反,说明了二义文法如果不进行运算符优先性、结合性的定义,则会造成预料不到的结果。
实验心得1.要深刻理解二义与非二义文法的内涵与区别,才能更好地完成这个实验;2.由于对yacc了解的不够好,导致用了一段时间才能看懂给的例子以及各部分的写法,这就告诉我们,不能够忽视老师对于这些工具的用法的讲解,每一部分都要学的认真仔细;3.一开始是写的非二义的文法,然后做出来后直接修改成二义的,没有去掉对于运算结合性的定义,导致了两者运行结果不管怎么尝试都没有差别,后来才考虑到这是因为我们定义了优先级与结合性,所以结果是一样的,于是特意为了尝试如果没有这些定义会如何,产生了二义版本2。
(完整版)基于LEX的词法分析器实验报告

定义识别标识符规则
{id}
{printf("%d行",lineno);
printf("%s ID\n",yytext);}//
定义识别错误的字符串规则当开头为数字的后面为字母的字符串时,是错误的标识符。{error_id}
yylex();/*start the analysis*/
printf("ok2\n");
printf(" No of words: %d\n number: %d\n", wordCount, numcount);
return0;
}
int yywrap()
{
return1;
}
2、新建文本文件,更名为b.c,敲入下面代码此为输入源代码
{printf("error:%s\n",yytext);}//以数字开头的字符自动报错定义忽略空格规则
{whitespace}{/*skip whitespace*/}//忽略空格定义忽略回车规则
{enter}
{lineno++;}//遇到回车自动加行号忽略辅助程序集中包括
主函数main()和辅助函数toupper()。程序代码实现
二、实验原理及方法
Lex输入文件由3个部分组成:定义集(definition),规则集(rule)和辅助程序集(auxiliary routine)或用户程序集(user routine)。这三个部分由位于新一行第一列 的双百分号分开,因此,Lex输入文件的格式如下
{definitions}
编译器的自动生成工具LEX和YACC的使用方法
编译器的自动生成工具LEX和YACC的使用方法一、词法分析程序产生器LEX的用法1.1 Lex概述Lex是一个词法分析器(扫描器)的自动产生系统,它的示意图如图1.1。
Lex源程序是用一种面向问题的语言写成的。
这个语言的核心是正规表达式,用它描述输入串的词法结构。
在这个语言中用户还可以描述当某一个词形被识别出来时要完成的动作,例如在高级语言的词法分析器中,当识别出一个关键字时,它应该向语法分析器返回该关键字的内部编码。
Lex并不是一个完整的语言,它只是某种高级语言(称为lex的宿主语言)的扩充,因此lex 没有为描述动作设计新的语言,而是借助其宿主语言来描述动作。
我们只介绍C作为lex的宿主语言时的使用方法,在Unix系统中,FORTRAN语言的一种改进形式Ratfor也可以做lex的宿主语言。
图1.1 Lex示意图Lex自动地表示把输入串词法结构的正规式及相应的动作转换成一个宿主语言的程序,即词法分析程序,它有一个固定的名字yylex,在这里yylex是一个C语言的程序。
yylex将识别出输入串中的词形,并且在识别出某词形时完成指定的动作。
看一个简单的例子:写一个lex源程序,将输入串中的小写字母转换成相应的大写字母。
程序如下:%%[a-z] printf(“%c”,yytext[0]+'A'-'a');上述程序中的第一行%%是一个分界符,表示识别规则的开始。
第二行就是识别规则。
左边是识别小写字母的正规式。
右边就是识别出小写字母时采取的动作:将小写字母转换成相应的大写字母。
Lex的工作原理是将源程序中的正规式转换成相应的确定有限自动机,而相应的动作则插入到yylex中适当的地方,控制流由该确定有限自动机的解释器掌握,对于不同的源程序,这个解释器是相同的。
1.2 lex源程序的格式lex源程序的一般格式是:{辅助定义的部分}%%{识别规则部分}%%{用户子程序部分}其中用花括号起来的各部分都不是必须有的。
编译原理实验报告
编译原理实验报告一、引言编译原理是计算机科学中的重要课程,它研究了将高级语言翻译为机器语言的方法和技术。
编译器作为实现这一目标的关键工具,扮演着至关重要的角色。
本实验报告将介绍编译原理实验的相关内容,包括实验目的、实验环境、实验步骤和实验结果等。
二、实验目的编译原理实验的主要目的是通过设计和实现一个简单的编译器,来加深对编译原理相关概念和技术的理解。
具体目标包括: 1. 理解词法分析、语法分析、语义分析等编译器的基本原理和流程; 2. 掌握使用Lex和Yacc工具进行词法分析和语法分析的方法; 3. 学会使用C/C++等编程语言实现编译器的基本功能。
三、实验环境本实验使用的实验环境包括: 1. 操作系统:Windows 10; 2. 开发工具:Visual Studio Code; 3. 编程语言:C/C++; 4. 辅助工具:Lex、Yacc。
四、实验步骤本实验的主要步骤如下:4.1 设计语言文法在开始实验之前,我们首先需要设计我们要实现的编程语言的文法。
文法是描述编程语言语法结构的形式化规则,它指定了合法的语法结构和语句构造方法。
我们可以使用BNF(巴科斯范式)或EBNF(扩展巴科斯范式)来表示文法。
4.2 实现词法分析器词法分析器的主要任务是将输入的字符流转换为一个个的词法单元(token)。
词法单元是编程语言中的最小语法单位,例如关键字、标识符、常量等。
我们可以使用Lex工具来实现词法分析器,它可以根据我们定义的正则表达式规则来生成词法分析器的代码。
4.3 实现语法分析器语法分析器的主要任务是根据语言文法,将词法单元序列转换为语法树。
语法树是描述程序语法结构的一种树状数据结构,它可以帮助我们理解和处理程序的语义。
我们可以使用Yacc工具来实现语法分析器,它可以根据我们定义的文法规则来生成语法分析器的代码。
4.4 实现语义分析器语义分析器的主要任务是对语法树进行遍历和分析,检查程序中的语义错误并生成中间代码。
编译原理 lex和yacc的综合设计 python
编译原理lex和yacc的综合设计python
1、Lex和Yacc是一种强大的词法分析和语法分析技术,它们常用于编译器的开发和编写编译器前端。
它们分别可以分析和解释输入字符流,并产生相应的输出。
Lex是一个词法分析器,它可以将输入字符流分解为令牌(即识别的节点),这些令牌可以用于编写解释器或编译器的前端。
Yacc则是一种用来构建语法分析器的工具,它可以识别输入的令牌序列,并生成相应的程序。
2、编译原理是编译器的最小系统,它涉及源程序的分析和分解,目标程序的生成和优化,以及中间代码的翻译。
Lex和Yacc则是用来处理字符流和语法检查的两个有力工具,在处理中间代码生成和优化方面非常有用,是编译器的核心部分。
3、Lex和Yacc的综合设计一般需要借助某种语言将可执行模块链接起来,最常用的技术是使用C,C是一种高性能语言,可以让开发者实现快速迭代,也可以利用其标准库实现代码复用,因此是完成Lex和Yacc综合设计的最佳语言。
4、Python是一种脚本语言,不适合用于编写Lex和Yacc综合设计,因为Python 并不专业,不能满足低级程序设计的需求,处理过程中往往性能不佳。
编译原理课程设计报告
实验1:用Lex设计词法分析器1实验目的:学会用lex设计一个词法分析器。
实验内容:使用lex为下述文法语言写一个词法分析器。
实验要求:输入为用该语言所写的源程序文件;输出为记号序列,每个记号显示为二元组(记号名,记号属性值)的形式。
输出可以在屏幕上,也可以输出到文件中。
不要求建立符号表。
在cygwin下用flex和gcc工具将实验调试通过,并能通过例子parser0中testcases 目录下的测试例的测试。
实验参考:和。
语言文法:<程序> PROGRAM <标识符> ; <分程序><分程序> <变量说明> BEGIN <语句表> END.<变量说明> VAR <变量说明表>;<变量说明表><变量表>: <类型> | <变量表>: <类型>; <变量说明表><类型> INTEGER | REAL<变量表> <变量> | <变量>, <变量表><语句表> <语句> | <语句>; <语句表><语句> <赋值语句> | <条件语句> | <WHILE语句> | <复合语句><赋值语句><变量> := <算术表达式><条件语句> IF <关系表达式> THEN <语句> ELSE <语句><WHILE语句> WHILE <关系表达式> DO <语句><复合语句> BEGIN <语句表> END<算术表达式> <项> | <算术表达式> + <项> | <算术表达式> - <项><项> <因式> | <项> * <因式> | <项> / <因式><因式> <变量> | <常数> | (<算术表达式>)<关系表达式> <算术表达式> <关系符> <算术表达式><变量> <标识符><标识符> <标识符><字母> | <标识符><数字> | <字母><常数> <整数> | <浮点数><整数> <数字> | <数字> <整数><浮点数> .<整数> | <整数>.<整数><关系符> < | <= | = | > | >=| <><字母> A | B | …| X | Y | Z | a | b | …| x | y | z<数字>0|1|2|…|9程序代码:%{#include <>#define LT 1#define LE 2#define GT 3#define GE 4#define EQ 5#define NE 6#define PROGRAM 7#define END 13#define VAR 9#define IF 10#define THEN 11#define ELSE 12#define WHILE 18#define DO 19#define ID 20#define NUMBER 21#define RELOP 22#define NEWLINE 23#define ERRORCHAR 24%}delim [ \t \n]ws {delim}+letter [A-Za-z]digit [0-9]id _|{letter}({letter}|{digit})*number {digit}+(\.{digit}+)?(E[+-]?{digit}+)?int1 {digit}|{digit}{int1}*/%s COMMENT%%<INITIAL>"/*" {BEGIN COMMENT;ECHO;} <COMMENT>"*/" {BEGIN INITIAL;ECHO;} <COMMENT>.|\n {ECHO;}/* ECHO是一个宏,相当于 fprintf(yyout, "%s", yytext)*/ <INITIAL>{ws} {;}<INITIAL>while {return (WHILE);}<INITIAL>do {return (DO);}<INITIAL>PROGRAM {return (PROGRAM);}<INITIAL>end {return (END);}<INITIAL>VAR {return (VAR);}<INITIAL>if {return (IF);}<INITIAL>then {return (THEN);}<INITIAL>else {return (ELSE);}<INITIAL>{id} {return (ID);}<INITIAL>{number} {return (NUMBER);}<INITIAL>"<" {return (RELOP);}<INITIAL>"<=" {return (RELOP);}<INITIAL>"=" {return (RELOP);}<INITIAL>"<>" {return (RELOP);}<INITIAL>">" {return (RELOP);}<INITIAL>">=" {return (RELOP);}<INITIAL>"+" {return (RELOP);}<INITIAL>"-" {return (RELOP);}<INITIAL>"*" {return (RELOP);}<INITIAL>"/" {return (RELOP);}<INITIAL>":=" {return (RELOP);}<INITIAL>";" {return (RELOP);}<INITIAL>"." {return (RELOP);}<INITIAL>"," {return (RELOP);}<INITIAL>. {return ERRORCHAR;}%%int yywrap (){return 1;}void writeout(int c){switch(c){case ERRORCHAR: fprintf(yyout, "(ERRORCHAR, \"%s\") ", yytext);break;case RELOP: fprintf(yyout, "(RELOP, \"%s\") ", yytext);break;case WHILE: fprintf(yyout, "(WHILE, \"%s\") ", yytext);break;case DO: fprintf(yyout, "(DO, \"%s\") ", yytext);break;case NUMBER: fprintf(yyout, "(NUM, \"%s\") ", yytext);break;case ID: fprintf(yyout, "(ID, \"%s\") ", yytext);break;case NEWLINE: fprintf(yyout, "\n");break;case PROGRAM: fprintf(yyout, "(PROGRAM, \"%s\") ", yytext);break;case END: fprintf(yyout, "(END, \"%s\") ", yytext);break;case VAR: fprintf(yyout, "(VAR, \"%s\") ", yytext);break;case IF: fprintf(yyout, "(IF, \"%s\") ", yytext);break;case THEN: fprintf(yyout, "(THEN, \"%s\") ", yytext);break;case ELSE: fprintf(yyout, "(ELSE, \"%s\") ", yytext);break;default:break;}return;}int main (int argc, char ** argv){int c,j=0;if (argc>=2){if ((yyin = fopen(argv[1], "r")) == NULL){printf("Can't open file %s\n", argv[1]);return 1;}if (argc>=3){yyout=fopen(argv[2], "w");}}while (c = yylex()){writeout(c);j++;if (j%5 == 0) writeout(NEWLINE);}if(argc>=2){fclose(yyin);if (argc>=3) fclose(yyout);}return 0;}测试文件为:PROGRAM test;VAR i, j, k: INTEGER;f0: REAL;BEGINi := 1;j := 1;k := 0;f0 := ;WHILE k<=100 DOBEGINIF j <20 THENBEGINj := i;k := k+1;f0 := f0*ENDELSEBEGINj := k;k := k-2;f0 := f0/.2ENDENDEND.运行结果:实验2:用Lex设计词法分析器2实验目的:学会用lex设计一个词法分析器,并考虑其与后续语法分析器的链接问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《编译原理》课程实验报告题目lex yacc 的联合使用专业班级学号姓名一. 实验题目lex yacc 的联合使用二. 实验日期三. 实验环境(操作系统,开发语言)操作系统是Windows开发语言是C语言四. 实验内容(实验要求)目的:熟悉lex和yacc的接口要求:(1)能对整数、实数进行带变量的四则运算(2)词法分析用lex实现(3)语法分析用yacc实现(4)交源代码和实验报告五. 实验步骤1.在实验二的基础上修改代码,并添加上以下的代码:double { return DOUBLE;}EOF { return 0;}{ID} { return ID;}2.在DOS环境下按照之前的步骤利用flex运行myleb.l,修改其中的错误之后,生成lex.yy.c文件。
3.参照书中第14章第7节和myparser-fifth.y文件中的代码,和老师说的思路修改myparser-sixth.y文件,按照实验要求修改代码。
4.在DOS环境下利用yacc运行myparser-sixth.y文件,会有出错提示,按照出错的地方指示,修改代码,使其最终能通过运行,生成y.tab.c文件。
(此步骤还未完成)5.打开c-free5.0,新建工程,在Source files文件夹中添加之前生成的lex.yy.c文件和y.tab.c文件,然后找到已给的calc.h文件,将其添加到新建工程中的Header files文件夹中,这时就能将三个文件组成一个类似于.exe文件类型的文件,最后运行。
6.运行并调试成功。
六. 实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)这是最后一次实验了,但这次的难度是有史以来最难的一次实验,因为要结合之前我们学到的所有东西。
首先要修改.l文件的代码,再把此文件用lex运行,即词法分析部分用lex 完成;然后是修改myparser-sixth.y文件,尽管有参照的代码,但是要自己实现能对整数和实数进行带变量的四则运算,对于还没有完全掌握.y文件编写的我还是太有难度了,自己先是完成了只对实数的运算,也能运行,但只要添加上实数就会出错,研究了很久,还是没有找出来哪里还有错误;有时候也会出现用yacc运行没错误,但用c-free运行就会出错,提示说.h文件有错误,找了半天,也修改了很多。
却仍然不知道哪里有错。
总的来说,虽然没有完成最终的目的,但是我已经尽力了。
七. 实验结果(关键源代码)Myleb.l文件代码:%option noyywrapDIGIT[0-9]ID[a-zA-Z][a-zA-Z0-9]*%{#include<stdio.h>%}%%{DIGIT}+"."{DIGIT}* { return NUM;}"/*"[^}\n]*"*/" printf("33 \n");"^" printf("34 %s\n",yytext);"+" printf("35 %s\n",yytext);"-" printf("36 %s\n",yytext);"*" printf("37 %s\n",yytext);"/" printf("38 %s\n",yytext);"(" printf("39 %s\n",yytext);")" printf("40 %s\n",yytext);"[" printf("41 %s\n",yytext);"]" printf("42 %s\n",yytext);"{" printf("43 %s\n",yytext);"}" printf("44 %s\n",yytext);double { return DOUBLE;}EOF { return 0;}{ID} { return ID;}. printf("100 %s\n",yytext);%%main(void){yylex();}myparser-sixth.y文件代码:/*带整数 int 和实数 double 变量声明的加减乘除四则运算 */ %{#include <stdio.h>#include <math.h>#include <ctype.h>#include <string.h>#include "genMidCode.h"extern char yytext[20];extern SYMREC *sym_table;int id_type;SYMREC *sym;typedef struct{union inval{double do;int in;}int valType;} VALUE;%}//定义语义栈的数据类型有两种数据类型整数和实数仿照 p252 中间union部分%union {VALUE val;SYMREC *tptr;int type;}// 终结符和非终结符对应的符号类型,自己定义%token < val > NUMDOU%token < val > NUMINT%token < tptr> ID%token < type > DOUBLE%token < type > INTEGER%type < val > exp%start program%left '-' '+'%left '*' '/'%left UMINUS%%program : func '#' ;func:|func declaration_part|func assign_stmt;declaration_part: DOUBLE {id_type = DOUBLE ; } declaration_list ';' | INTEGER {id_type = INTEGER ; } declaration_list ';';declaration_list : declaration_list ',' declaration|declaration;declaration: ID { sym_table = putsym2(yytext,id_type); } | ID '=' NUMDOU { if (id_type == INTEGER)sym_table = putsym3(yytext,id_type,$3); /* 把整型值放入符号表 */| ID '=' NUMINT { if (id_type == DOUBLE)sym_table = putsym3(yytext,id_type,$3);} /* 把实型值放入符号表 */;assign_stmt: '\n'| ID '=' exp ';' { if((sym = getsym(yytext) != NULL ){if ($3.valType == 1) /* exp里是实数 */sym_table = putsym3(yytext,id_type,$3.inval.do);elsesym_table = putsym3(yytext,id_type,$3.inval.in);}};exp: NUMDOU { $$.valType =1; $$.inval.do= $1.inval.do;} /* valType =1代表实数 */| NUMINT { $$.valType =2; $$.inval.in= $2.inval.in;} /* valType =2代表整数 */| ID { if((sym = getsym(yytext)) != NULL )if (id_type == INTEGER){ $$.valType =2; $$.inval.in = sym->value;} /* valType =2代表整数 */else { $$.valType =1; $$.inval.do = sym->value;} /* valType =1代表实数 */else ("此变量没定义\n "); }| exp '+' exp { { if($1.valType ==1 && $3.valType ==1 ) { $$.valType =1 ;$$.inval.do= $1.inval.do + $3.inval.do ;}else }| exp '-' exp| exp '*' exp| exp '/' exp| '-' exp %prec UMINUS;%%int yyerror(char *s) {printf("%s\n", s);return 0;}int main(void) {yyparse();return 0;}int yylex() // 用lex实现如下的功能{int c;while ((c = getchar())==' ' || c=='\t');if (c == '.' || isdigit(c)){ungetc(c,stdin);scanf("%lf",&yylval.val);return NUMDOU;}if(isalpha(c)){char symbuf[20];int i=0;do{symbuf[i] = c;i++;c = getchar();}while(c != EOF && isalnum(c));ungetc(c,stdin);symbuf[i] = '\0'; // 还要能识别 int a 中的关键字int,如果遇见int 返回 INTEGERstrcpy(yytext,symbuf);if (strcmp("double",yytext) == 0) return DOUBLE ; //遇见 double 返回 DOUBLEreturn ID;}if (c==EOF) return 0;return c;}。