编译原理词法分析器(项目报告)

目录

一、需求分析(三号,宋体,粗体) 2

二、系统设计(三号,宋体,粗体) 4

(一)系统中的数据定义(四号,黑体,粗体) 4

(二)系统的概要设计 4

(三)系统的详细设计 8

(四)系统的核心算法 9

三、系统编码及运行(三号,宋体,粗体) 11

(一)系统开发涉及的软件 11

(二)系统运行界面及结果 11

四、系统测试(三号,宋体,粗体) 13

五、总结 16

附录(源代码) 20

(注:这部分可以点击右键更新生成,重新设置字体为四号)

 

 

 

 

 

  • 需求分析

当今时代是飞速发展的信息时代,随着计算机技术的普及与网络的广泛应用,计算机语言更显得至关重要。计算机语言是人与计算机之间传递信息的媒介。计算机系统最大特征是指令通过一种语言传达给机器。为了使电子计算机进行各种工作,就需要有一套用以编写计算机程序的数字、字符和语法规划,由这些字符和语法规则组成计算机各种指令(或各种语句)。这些就是计算机能接受的语言。一个高级语言程序的实现,必须依赖于相应的编译系统。编译程序的基本任务是将源语言程序翻译成等价的目标语言程序。

词法分析阶段是编译过程的第一个阶段,是编译的基础。词法分析结果的好坏将直接影响中文信息处理上层应用的效果。理解词法分析在编译程序中的作用,加深对有穷自动机模型的理解,掌握词法分析程序的实现方法和技术,加深对编译原理的理解,掌握编译程序的实现方法和技术至关重要。

本次项目则为简单的词法分析器,通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。具体方法为:编制一个读单词的程序,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符和分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示)。

词法分析器相关知识:

1.词法分析器的功能和输出格式

词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。在本实验中,采用的是一类符号一种别码的方式。

标识符的BNF表示:

<标识符>-> <字母><字母数字串>

<字母数字串>-><字母><字母数字串>|<数字><字母数字串>|ε

无符号整数的BNF表示:

<无符号整数>-> <数字><数字串>

<数字串>-> <数字><数字串> |ε

运算符的BNF表示:

<加法运算符>-> +

<减法运算符>-> -

<大于关系运算符>-> >

<大于等于关系运算符>-> >=

2.超前搜索

词法分析时,常常会用到超前搜索方法。如当前待分析字符串为“a>i”,当前字符为’>’,此时,分析器到底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。于是分析器读入下一个字符’+’,这时可知应将’>’解释为大于运算符。但此时,超前读了一个字符’i’,所以要回退一个字符,词法分析器才能正常运行。在分析标识符,无符号整数等时也有类似情况。

 

简单流程如图1.1

                           图1.1程序简单流程图

 

系统设计(三号,宋体,粗体)

系统中的数据定义四号黑体,粗体)

定义:词法分析器的功能输入源程序,按照构词规则分解成一系列单词符号。单词是语言中具有独立意义的最小单位,包括关键字、标识符、运算符、界符和常数等。

  1. 识别保留字:if、int、for、while、do、return、break、continue等
  2. 运算符包括:+、-、*、/、=、>、<、>=、<=、!=
  3. 分隔符包括:,、;、{、}、(、)
  4. 常数为无符号整形数;
  5. 其它的都识别为标识符;

输出:词法分析器所输出单词符号常常表示成如下的二元式:(单词,单词符号的属性值)

    标识符一般统归为一种。常数包括整数和浮点数两种。

    关键字、运算符、界符可将其全体视为一种。

    单词符号的属性是指单词符号的特性或特征。

 

  • 系统的概要设计

功能流程图如图:

 

    

 实现词法分析的函数为

/**词法分析**/

void analyse(FILE * fpin){

    char ch=' ';

    string arr="";

    while((ch=fgetc(fpin))!=EOF){

        arr="";

        if(IsFilter(ch)){}              //判断是否为过滤符

        else if(IsLowLetter(ch)){       //判断是否为关键字

            while(IsLowLetter(ch)){

                arr += ch;

                ch=fgetc(fpin);

            }

            //fseek(fpin,-1L,SEEK_CUR);

            if(IsKeyword(arr)){

 

                cout<<arr<<"  <关键字>"<<endl;

            }

            else

            {

                cout<<arr<<"  <标识符>"<<endl;

            }

        }

        else if(IsDigit(ch)){           //判断是否为数字

            while(IsDigit(ch)||(ch=='.'&&IsDigit(fgetc(fpin)))){

                arr += ch;

                ch=fgetc(fpin);

            }

            fseek(fpin,-1L,SEEK_CUR);

            cout<<arr<<"  <无符号整形数>"<<endl;

        }

        else if(IsUpLetter(ch)||IsLowLetter(ch)||ch=='_'){

            while(IsUpLetter(ch)||IsLowLetter(ch)||ch=='_'||IsDigit(ch)){

                arr += ch;

                ch=fgetc(fpin);

            }

            fseek(fpin,-1L,SEEK_CUR);

            cout<<arr<<"  <标识符>"<<endl;

        }

        else switch(ch){

        case '+':

        case '-':

        case '*':

        case '/':

        case '>':

        case '<':

        case '=':

        case '!':

            {

                arr += ch;

                cout<<arr<<"  <运算符>"<<endl;

                break;

            }

        case ';':

        case ',':

        case '(':

        case ')':

        case '[':

        case ']':

        case '{':

        case '}':

            {

              arr += ch;

              cout<<arr<<"  <分隔符>"<<endl;

              break;

            }

        default :cout<<"\""<<ch<<"\":无法识别的字符!"<<endl;

        }

    }

 

}

  • 系统的详细设计

1.词法分析程序打开源文件,读取文件内容,直至遇上’$’文件结束符,然后读取结束。

2.对读取的文件进行预处理,从头到尾进行扫描,去除//和/*  */的内容,以及一些无用的、影响程序执行的符号如换行符、回车符、制表符等。但是千万注意不要在这个时候去除空格,因为空格在词法分析中有用,比如说int i=3;这个语句,如果去除空格就变成了“inti=3”,这样就失去了程序的本意,因此不能在这个时候去除空格。

3.接下来就要对源文件从头到尾进行扫描了,从头开始扫描,主控程序主要负责系统建立一个文件保存四个表,这四个表分别存储关键字、运算符、界符、过滤符。而标识符和常数则用正则表达式判断。建立了多个布尔类,当系统读取代码时,用空格或制表符作为切词标志符,当遇到空格就输出之前检索的字符串进行判断(规定每个单词符号之间都有空格),判断字符串时,系统会通过顺序查找依次调用布尔类与之匹配来判断其属性并输出,如没有匹配成功,则说明所检索的字符进步串不合法,系统则会输出非法字符串。直到最后一个字符串匹配完毕之后系统结束

 

 

 

 

 

 (四)系统的核心算法

(一)/**判断是否为关键字**/

bool IsKeyword(string word){

    for(int i=0;i<15;i++){

        if(KEYWORD[i]==word){

            return true;

        }

    }

    return false;

}

(二)/**判断是否为分隔符**/

bool IsSeparater(char ch){

    for(int i=0;i<8;i++){

        if(SEPARATER[i]==ch){

            return true;

        }

    }

    return false;

}

 

(三)/**判断是否为运算符**/

bool IsOperator(char ch){

    for(int i=0;i<8;i++){

        if(OPERATOR[i]==ch){

            return true;

        }

    }

    return false;

}

(四)/**判断是否为过滤符**/

bool IsFilter(char ch){

    for(int i=0;i<4;i++){

        if(FILTER[i]==ch){

            return true;

        }

    }

    return false;

}

 

(五)/**判断是否为大写字母**/

bool IsUpLetter(char ch){

    if(ch>='A' && ch<='Z') return true;

    return false;

}

(六)/**判断是否为小写字母**/

bool IsLowLetter(char ch){

    if(ch>='a' && ch<='z') return true;

    return false;

}

(七)/**判断是否为数字**/

bool IsDigit(char ch){

    if(ch>='0' && ch<='9') return true;

    return false;

}

 

 

 

系统编码及运行(三号,宋体,粗体)

系统开发涉及的软件

     代码编写工具:CodeBlocks

      画图工具:Microsoft Office Word

     文档撰写:Microsoft Office Word,记事本

 

(二)系统运行界面及结果

(一):系统开始界面(如图1)

图1 系统登录界面

 

 

 

 

 

 

 

(二)系统开始运行界面

第一步:输入源文件名(包含路径和后缀)(如图2)

2 系统输入源文件界面

(三)运行结果显示界面(如图3)

3 系统运行结果显示界面

系统测试(三号,宋体,粗体)

     系统测试数据1:C:\Users\24125\Desktop\a.txt

文本文档内容:

main()

 

{

 

int  a,b;

 

a = 10;

 

b = a + 20;

 

}

运行结果如下:

系统测试数据2:C:\Users\24125\Desktop\b.txt

文本文档内容:

FILE* fp = NULL;

int ifind = 0;

 

unsigned char* ptr = NULL;

int datalong = 0;

 

int g_iLogonID = -1;

unsigned int g_uConnID = -1;

 

 

int main()

{

do

{

Sleep(20 * 1000);

} while (0);

 

return 0;

}

 

 

 

 

 

 

 

 

系统运行结果如下图:

系统测试数据3:如果输入了不正确的文件路径

系统测试数据4:如果文本文档中的内容不在词法分析的范围内

 

 

这一部分的系统测试,我首先分析了短文本文档内容的C语言程序代码的词法分析器,据结果显示,系统将会按照规定好的关键字,标识符,分界符,无符号型整数等正确显示出词法分析的结果,然后我设置了C语言程序代码较长的文本文档作为词法分析的内容,据结果显示,可得出结论,不论代码的长短,此词法分析器均可以显示正确词法分析结果,然后我例举了可能由于输入错误源文件路径或者名字的情况,据结果显示,如果发生此类情况,词法分析器会出现提示文字,告知用户,重新输入源文件的路径和名字,体现此词法分析器项目的人文关怀,同样,如果待分析文本文档出现不合规字符,此词法分析器同样会给与提示与警告。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

五、总结

该系统为简单的词法分析器,可以对输入的字符串进行分析,判断是关键字、标识符、运算符、界符和常数,然后输出。整个系统项目开发的过程中,提高了我对编译原理这门学科的实践能力,加深了我对其的理解,一学期的学习只是限于书本层次和实验层次,只有亲手自己动手动脑,制作出词法分析器,才从根本上理解词法分析的原理,这也让我深深地体会到学习,就应该是书本知识结合实践过程,实践出真知,才能真正将所学的知识融会贯通,把印在纸页上的文字变成自己脑中的能量。而且一定要深知一个大的程序是由许多小的程序组成的,总的程序就是对这些小的程序的调用,来实现各项功能。只要处理好这些小的程序,做出一个大的程序并不是很困难。而且要认真的把自己所学的知识结合起来,比如编译原理和C++,根据C++课程所学的概念、理论和方法,按照C++程序设计的基本步骤,设计出一个适当规模的程序;进一步加深对C++语言和编译原理的理解和掌握。理论联系实际,加深和巩固所学的理论知识,进而提高实践能力和计算机的综合运用能力。

我们编写程序的过程是辛苦与快乐的,程序的编写原则很重要,只要我们在编程,就必须不断改进,才能更好提高编程能力。在这过程中,我也遇到了各种各样的编译错误,或者代码想不通,不知道如果继续下去,我积极的问了自己的同学老师,让我体会到团队的力量,有时候一个人走入一个思想盲点会不断撞墙而无法走出,而与志同道合者交流,则可以让问题迎刃而解,共同努力和进步的感觉让成功变得不是那么遥远。这个程序也是通过多次调试和改进最终才得以完善序,而我自己也在调试的过程中学习的知识得到了完善和补充,不仅是对词法分析器的理解更进一步。也让我重新熟悉了计算机语言的相关内容,加深了知识的深化和用途的理解。未来可能会接触更加复杂和难以理解的知识,所以我会更加努力学习,一面增加提高自己的基础能力,一面提高自身应对困难的能力,力求不断进步。

 

 

 

附录(源代码,注意代码格式)

#include <iostream>

#include <stdlib.h>

#include <stdio.h>

using namespace std;

string KEYWORD[15]={"if","else","void","return","while","then","for","main",  "int","char","double","float","case","cin","cout"};

char SEPARATER[8]={';',',','{','}','[',']','(',')'};    //界符

char OPERATOR[8]={'+','-','*','/','>','<','=','!'};     //运算符

char FILTER[4]={' ','\t','\r','\n'};                    //过滤符

 

/**判断是否为关键字**/

bool IsKeyword(string word){

    for(int i=0;i<15;i++){

        if(KEYWORD[i]==word){

            return true;

        }

    }

    return false;

}

/**判断是否为分隔符**/

bool IsSeparater(char ch){

    for(int i=0;i<8;i++){

        if(SEPARATER[i]==ch){

            return true;

        }

    }

    return false;

}

 

/**判断是否为运算符**/

bool IsOperator(char ch){

    for(int i=0;i<8;i++){

        if(OPERATOR[i]==ch){

            return true;

        }

    }

    return false;

}

/**判断是否为过滤符**/

bool IsFilter(char ch){

    for(int i=0;i<4;i++){

        if(FILTER[i]==ch){

            return true;

        }

    }

    return false;

}

/**判断是否为大写字母**/

bool IsUpLetter(char ch){

    if(ch>='A' && ch<='Z') return true;

    return false;

}

/**判断是否为小写字母**/

bool IsLowLetter(char ch){

    if(ch>='a' && ch<='z') return true;

    return false;

}

/**判断是否为数字**/

bool IsDigit(char ch){

    if(ch>='0' && ch<='9') return true;

    return false;

}

 

/**词法分析**/

void analyse(FILE * fpin){

    char ch=' ';

    string arr="";

    while((ch=fgetc(fpin))!=EOF){

        arr="";

        if(IsFilter(ch)){}              //判断是否为过滤符

        else if(IsLowLetter(ch)){       //判断是否为关键字

            while(IsLowLetter(ch)){

                arr += ch;

                ch=fgetc(fpin);

            }

            //fseek(fpin,-1L,SEEK_CUR);

            if(IsKeyword(arr)){

 

                cout<<arr<<"  <关键字>"<<endl;

            }

            else

            {

                cout<<arr<<"  <标识符>"<<endl;

            }

        }

        else if(IsDigit(ch)){           //判断是否为数字

            while(IsDigit(ch)||(ch=='.'&&IsDigit(fgetc(fpin)))){

                arr += ch;

                ch=fgetc(fpin);

            }

            fseek(fpin,-1L,SEEK_CUR);

            cout<<arr<<"  <无符号整形数>"<<endl;

        }

        else if(IsUpLetter(ch)||IsLowLetter(ch)||ch=='_'){

            while(IsUpLetter(ch)||IsLowLetter(ch)||ch=='_'||IsDigit(ch)){

                arr += ch;

                ch=fgetc(fpin);

            }

            fseek(fpin,-1L,SEEK_CUR);

            cout<<arr<<"  <标识符>"<<endl;

        }

        else switch(ch){

        case '+':

        case '-':

        case '*':

        case '/':

        case '>':

        case '<':

        case '=':

        case '!':

            {

                arr += ch;

                cout<<arr<<"  <运算符>"<<endl;

                break;

            }

        case ';':

        case ',':

        case '(':

        case ')':

        case '[':

        case ']':

        case '{':

        case '}':

            {

              arr += ch;

              cout<<arr<<"  <分隔符>"<<endl;

              break;

            }

        default :cout<<"\""<<ch<<"\":无法识别的字符!"<<endl;

        }

    }

 

}

int main()

{

    char inFile[40];

    FILE *fpin;

    cout<<"********************************************************"<<endl;

    cout<<"***********************词法分析器***********************"<<endl;

    cout<<"**********************Code Analyse**********************"<<endl;

cout<<"*********************小仙女:赵琳娜**********************"<<endl;

cout<<"***********************软件16-1班***********************"<<endl;

cout<<"********************************************************"<<endl;

cout<<"                                                        "<<endl;

cout<<"                                                        "<<endl;

    cout<<"请输入源文件名(包括路径和后缀):";

    while(true){

        cin>>inFile;

        if((fpin=fopen(inFile,"r"))!=NULL)

            break;

        else{

            cout<<"文件名错误!"<<endl;

            cout<<"请输入源文件名(包括路径和后缀):";

        }

 

    }

    cout<<"------词法分析如下------"<<endl;

    analyse(fpin);

    return 0;

}

()

  • 9
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
简单的语法、词法、语义分析器 简单的语法、词法、语义分析器项目是一个编程项目,旨在构建一个能够对源代码进行词法分析、语法分析和语义分析的程序。这个项目可以帮助开发者深入理解编译器的工作原理,以及编程语言的理论基础。 ### 项目介绍: **目标**:创建一个能够对源代码进行词法分析、语法分析和语义分析的程序。 **主要任务**: 1. **词法分析**: - 读取源代码,生成词法单元(tokens)。 - 忽略空白、换行符和注释。 - 识别关键字、标识符、常数、运算符和分隔符等。 2. **语法分析**: - 根据语言的语法规则,分析词法单元序列。 - 构建抽象语法树(AST)。 - 检测并报告语法错误。 3. **语义分析**: - 遍历抽象语法树,执行语义检查。 - 检查类型匹配、变量声明和使用等。 - 生成中间代码或目标代码(可选)。 **技术要求**: - 熟悉编程语言(如C/C++, Java, Python等)。 - 了解编译原理中的词法分析、语法分析和语义分析概念。 - 熟悉自动机理论、形式语言理论和抽象语法树。 **开发工具**: - 代码编辑器或IDE(如Visual Studio Code, Eclipse等)。 - 编程语言(C/C++, Java, Python等)。 ### 适合人员: - 计算机科学或相关领域的学生:此项目能够帮助他们实践编译原理和编程语言的基础知识。 - 软件开发者:特别是那些对编译器和解释器如何工作感兴趣的程序员。 - 语言处理领域的研究者:此项目可以作为自然语言处理和编译技术的一个研究起点。 ### 额外建议: - 从一个简单的编程语言子集开始,逐步增加支持的语法和语义特性。 - 使用单元测试和集成测试来验证分析器的正确性。 - 编写详细的文档,记录设计决策、实现细节和测试结果。 - 考虑使用版本控制系统(如Git)来管理项目代码。 通过这个项目,开发者不仅能够深入理解编译器的工作原理,还能够提高对程序语言的理解和编程技能。此外,这个项目对于希望进入编译器设计、程序分析和代码生成等领域的人来说,是一个很好的实践机会。
本科毕业设计 简单词法分析器生成工具的设计和实现 摘  要 本文描述一个简单的词法分析器生成工具的设计和实现过程。该词法分析器生成工具的功能是,它能根据给定的正则表达式构造出语言识别器。该语言识别器能够判断输入的句子是否是给定的正则表达式所描述的语言的句子,并在文件或标准输出中显示、保存所识别句子的信息。构造语言识别器的过程为:首先,从词法分析器生成工具读入正则表达式,将该正则表达式转换成等价的不确定的有限自动机,从而构造出确定的有限自动机,然后构造出确定的有限自动机的状态转换表,词法分析器生成工具利用该状态转换表生成语言识别器的C语言源文件,编译链接该C语言源文件即可生成语言识别器。在实现过程中,本文用语法分析器生成工具Bison来扫描正则表达式自动的来构造不确定的有限自动机 目 录 1 引言 1 2 基本概念 3 2.1 正则表达式 3 2.2 确定的有限自动机(DFA)和非确定的有限自动机(NFA) 3 2.3 产生式 5 3语言识别器生成工具的实现 6 3.1 实现的算法 7 3.1.1 由正则表达式构造NFA--Thompson构造法 8 3.1.2 LR语法分析法自动构造NFA 11 3.1.3 子集构造法 14 3.1.4 语言识别器的识别算法 16 3.2 数据结构 17 3.2.1 NFA的存储结构 17 3.2.2 DFA的存储结构 19 3.2.3 状态转换表的存储结构 20 3.3本章内容小结 20 4 编译运行及其性能 21 5 总结 24 参考文献 25 需要的联系请:QQ506425246

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值