编译原理 - 实验二 - FLEX词法分析器

FLEX词法分析器

一、Lex和Yacc介绍

Lex 是一种生成扫描器的工具。扫描器是一种识别文本中的词汇模式的程序。 一种匹配的常规表达式可能会包含相关的动作。这一动作可能还包括返回一个标记。 当 Lex 接收到文件或文本形式的输入时,它试图将文本与常规表达式进行匹配。 它一次读入一个输入字符,直到找到一个匹配的模式。 如果能够找到一个匹配的模式,Lex 就执行相关的动作(可能包括返回一个标记)。 另一方面,如果没有可以匹配的常规表达式,将会停止进一步的处理,Lex 将显示一个错误消息。

Yacc代表 Yet Another Compiler Compiler 。 Yacc 的 GNU 版叫做 Bison。它是一种工具,将任何一种编程语言的所有语法翻译成针对此种语言的 Yacc 语 法解析器。

(下载下载flex和bison。网址分别是http://gnuwin32.sourceforge.net/packages/flex.htm和http://gnuwin32.sourceforge.net/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();

return 0;

}

我们暂且不讨论上面代码的意思。

打开控制台,进入到刚才所建立文件(lex.l,yacc.y)所在的文件夹。

1.输入 flex lex.l

2.输入 bison yacc.y

如果我们看到当前文件夹上多了两个文件(yacc.tab.c,lex.yy.c),那么说明lex&&yacc已经安装配置成功,接下来就可以进行实验了。

 三、课本实例

1.  按课本p58 3.7.3代码,保存testscan.lex文件,然后放到与flex相同的文件夹下,然后进入DOS下,输入flex testscan.lex 并回车,即可生成lex.yy.c文件

2.  用C编译器(VC 6.0)编译并产生lexyy.exe

3.  建好aaa.txt输入文件,进入DOS下,进入到lexyy.exe所在目录,输入lexyy.exe aaa.txt bbb.txt即可。

{
int a;
a=10;
}

通过分析后:

{, {

int, int
NUM, a
;, ;

NUM, a
=, =
ID, 10
;, ;

}, }

4.  课本p61 7

按题目要求适当修改代码,然后在进入DOS下,进入到lexyy.exe所在目录,输入lexyy.exe abc.txt abcdef.txt,再打开abcdef.txt即可看到结果

int i=10;
do{
printf(i);
i++;
}while(i!>10)
if(1<2&&2<4)
else(1||2)

分析后:

int, int
NUM, i
=, =
ID, 10
;, ;

NUM, do
{, {

NUM, printf
(, (
NUM, i
), )
;, ;

NUM, i
+, +
+, +
;, ;

}, }
while, while
(, (
NUM, i
!, !
>, >
ID, 10
), )

if, if
(, (
ID, 1
<, <
ID, 2
&&ID, 2
<, <
ID, 4
), )

else, else
(, (
ID, 1
||ID, 2
), )

五、代码

%{
#include<stdio.h>
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
%}

digit [0-9]
number {digit}+
letter [a-zA-Z]
identifier {letter}({letter}|{digit})*
newline [\n]
whitespace [\t]+
%%
"if" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"else" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"for" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"while" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"int" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"=" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"+" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"-" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"*" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"/" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"<" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
">" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"(" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
")" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"{" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"}" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
";" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
":" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"‘" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"," {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"!" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"==" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
">=" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"<=" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"!=" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
{number} {fprintf(yyout,"%s, %s\n", "ID",yytext);}
{identifier} {fprintf(yyout,"%s, %s\n", "NUM",yytext);}
{whitespace} {/*跳过空白*/}
"/*" {char c ;
int done=FALSE;
do{
while((c=input())!=‘*‘);
while((c=input())==‘*‘);
if(c==‘/‘) done=TRUE;
}while(!done);
}
{fprintf(yyout,"%d, %s\n", 0,yytext);}
%%

main(argc,argv)
int argc;
char **argv;
{
++argv,--argc;
if(argc>0)
yyin=fopen(argv[0],"r");
else
yyin=stdin;
++argv,--argc;
if(argc>0)
yyout=fopen(argv[0],"w");
else
yyout=stdout;
yylex();
}
int yywrap()
{
return 1;
}

时间: 2024-10-14 03:37:18

编译原理 - 实验二 - FLEX词法分析器的相关文章

编译原理实验二:LL(1)语法分析器

一.实验要求 不得不想吐槽一下编译原理的实验代码量实在是太大了,是编译原理撑起了我大学四年的代码量... 这次实验比上次要复杂得多,涵盖的功能也更多了,我觉得这次实验主要的难点有两个(其实都是难点...): 1. 提取左公因子或消除左递归(实现了消除左递归) 2. 递归求First集和Follow集 其它的只要按照课本上的步骤顺序写下来就好(但是代码量超多...),下面我贴出实验的一些关键代码和算法思想. 二.基于预测分析表法的语法分析 2.1 代码结构 2.1.1  Grammar类    功

CSUFT 编译原理实验二LL(1)文法分析

1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <stack> 5 #include <queue> 6 #include <map> 7 #include <algorithm> 8 #include <vector> 9 10 using namespace std; 11 12 char A[20];/*分

哈工大软件学院编译原理实验1——词法分析

这次实验被"过来人"们定位非常easy,实验内容例如以下: ----------------------------------------------------------------------------------- 对例如以下工作进行展开描写叙述 (1) 给出语言的词法规则描写叙述 · 标识符.keyword.整常数.字符常数.浮点常数 · 单界符:+,-,×,;,- · 双界符:/*,:=,>=,<=,!=,- · 凝视 (2) 针对这样的单词的状态转换图和程

编译原理(简单自动词法分析器LEX)

编译原理(简单自动词法分析器LEX)源程序下载地址:  http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7%90%86%E7%AE%80%E5%8D%95LEX%EF%BC%88%E8%AF%8D%E6%B3%95%E8%87%AA%E5%8A%A8%E5%88%86%E6%9E%90%E5%99%A8%EF%BC%89.zip

编译原理实验代码(词法分析,语法分析,中间代码生成)

花了一天写出的程序没有顾及很多层面,但对于理解基本的实验道理和交上实验还是有点帮助的.代码实现了基于有限自动机的词法分析,采用递归下降分析法和EBNF文法实现语法分析并生成中间代码. lexAnalysis.h /* * lexAnalysis.h * * Created on: 2014-12-2 * Author: liuqiushan */ #ifndef LEXANALYSIS_H_ #define LEXANALYSIS_H_ #include <stdio.h> #include

[Vue源码]一起来学Vue模板编译原理(二)-AST生成Render字符串

本文我们一起通过学习Vue模板编译原理(二)-AST生成Render字符串来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫持和发布订阅 一起来学Vue模板编译原理(一)-Template生成AST 一起来学Vue模板编译原理(二)-AST生成Render字符串 一起来学Vue虚拟DOM解析-Virtual Dom实现和Dom-diff算法 这些文章统一放在我的git仓库:https://github.com/yzsunlei/javascri

编译原理 实验3 语法分析

语法分析 一. 实验目的 算术表达式的文法可以是(你可以根据需要适当改变): E→E+E|E-E|E*E|E/E|(E)|i 根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确. 二. 实验环境 操作系统:window xp 编写环境:visual c++ 编写语言:c语言 三. 实验内容 程序输入/输出示例: 如参考C语言的运算符.输入如下表达式(以分号为结束)和输出结果: (1)10; 输出:正确 (2)1+2; 输出:正确 (3)(1+2)/3+4-(5+6/7); 输出:正

吉首大学_编译原理实验题_基于预測方法的语法分析程序的设计【通过代码】

一.实验要求 实验二 基于预測方法的语法分析程序的设计 一.实验目的 了解预測分析器的基本构成及用自顶向下的预測法对表达式进行语法分析的方法,掌握预測语法分析程序的手工构造方法. 二.实验内容 1.了解编译程序的基于预測方法的语法分析过程. 2.依据预測分析原理设计一个基于预測方法的语法分析程序. 三.实验要求 对给定文法G[S]: S->AT       A->BU     T->+AT|$      U->*BU|$    B->(S)|m 当中,$表示空串. 1.推断上

编译原理-如何使用flex和yacc工具构造一个高级计算器

Flex工具的使用方法 Lex 是一种生成扫描器的工具. Lex是Unix环境下非常著名的工具,主要功能是生成一个扫描器(Scanner)的C源码. 扫描器是一种识别文本中的词汇模式的程序. 这些词汇模式(或者常规表达式)在一种特殊的句子结构中定义.一种匹配的常规表达式可能会包含相关的动作.这一动作可能还包括返回一个标记. 当 Lex 接收到文件或文本形式的输入时,它试图将文本与常规表达式进行匹配. 它一次读入一个输入字符,直到找到一个匹配的模式. 如果能够找到一个匹配的模式,Lex 就执行相关