计算机编译原理实验报告

合集下载

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的和要求本次实验旨在对PL_0语言进行功能扩充,添加新的语法特性,进一步提高编译器的功能和实用性。

具体要求如下:1.扩展PL_0语言的语法规则,添加新的语法特性;2.实现对新语法的词法分析和语法分析功能;3.对扩展语法规则进行语义分析,并生成中间代码;4.验证扩展功能的正确性。

二、实验内容1.扩展语法规则本次实验选择扩展PL_0语言的语句部分,添加新的控制语句,switch语句。

其语法规则如下:<switch_stmt> -> SWITCH <expression> CASE <case_list><default_stmt> ENDSWITCH<case_list> -> <case_stmt> , <case_stmt> <case_list><case_stmt> -> CASE <constant> : <statement><default_stmt> -> DEFAULT : <statement> ,ε2.词法分析和语法分析根据扩展的语法规则,需要对新的关键字和符号进行词法分析,识别出符号类型和记号类型。

然后进行语法分析,建立语法树。

3.语义分析在语义分析阶段,首先对switch语句的表达式进行求值,判断其类型是否为整型。

然后对case语句和default语句中的常量进行求值,判断是否与表达式的值相等。

最后将语句部分生成中间代码。

4.中间代码生成根据语法树和语义分析的结果,生成对应的中间代码。

例如,生成switch语句的跳转表,根据表达式的值选择相应的跳转目标。

5.验证功能的正确性设计一些测试用例,验证新语法的正确性和扩展功能的实用性。

三、实验步骤与结果1.扩展语法规则,更新PL_0语法分析器的词法规则和语法规则。

编译原理实验报告(词法分析器语法分析器)

编译原理实验报告(词法分析器语法分析器)

函数 int f(char c) 和 int g(char c) , 判断运算符之间的优先关系 , 根据不同情况作各种不同操作 。 流程
图如下 :
word 完美格式
专业资料
输入算数表达式,以 #结束 初始化 loptr[1]= ’#’ 用 get()取一个待分析字符 s
Optr[1] 和 s 是否同时为 #

2 、而且对词法分析和语法分析在实践中的应用有了深入的掌握

3 、 更加熟悉了构造词法分析程序和语法分析程序的手工方式的相关原理
, 能够实现对词
法分析程序所提供的单词符号序列进行相应的语法检查和结构分析
,达到了学以致用的目的 。
word 完美格式
word 完美格式
专业资料
case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
while(letter(s)||digit(s)) {token[j]=s; j=j+1; get(); } retract();k=lookup(token); if(k==0)
-
9
*
10
<=
11
<
11
==
11
=
12
;
13
word 完美格式
助记符 while
if else switch case

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。

二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。

三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。

在本次实验中,我们使用有限自动机的理论来设计词法分析器。

首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。

然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。

在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。

(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。

在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。

首先,我们根据给定的语法规则,编写了相应的递归函数。

每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。

在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。

(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。

在本次实验中,我们使用了四元式作为中间代码的表示形式。

在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。

同时,根据语法树的结构,生成相应的四元式中间代码。

(四)代码优化代码优化的目的是提高生成代码的质量和效率。

在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。

通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。

中北编译原理实验报告

中北编译原理实验报告

一、实验目的1. 理解编译原理的基本概念,掌握编译程序的设计方法和流程。

2. 掌握编译过程中的词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等基本步骤。

3. 提高实际编程能力,培养严谨的编程思维。

二、实验环境1. 操作系统:Windows 102. 编译器:Visual Studio 20193. 编译原理实验平台:C++语言编写三、实验内容1. 词法分析器设计(1)词法分析器原理:词法分析器是编译程序中的第一个阶段,其作用是将源程序中的字符序列转换为一系列的单词符号。

本实验采用正则表达式来定义单词符号,并使用有限自动机实现词法分析。

(2)实验步骤:a. 定义单词符号:根据实验要求,设计正则表达式来定义单词符号。

b. 构建有限自动机:根据正则表达式,构建有限自动机的状态转移图。

c. 实现词法分析器:编写C++代码实现词法分析器,包括有限自动机的构建和状态转移过程。

2. 语法分析器设计(1)语法分析器原理:语法分析器是编译程序中的第二个阶段,其作用是检查源程序中的语法结构是否正确。

本实验采用递归下降分析法实现语法分析。

(2)实验步骤:a. 定义语法规则:根据实验要求,设计语法规则。

b. 构建语法分析树:根据语法规则,构建语法分析树。

c. 实现语法分析器:编写C++代码实现语法分析器,包括递归下降分析法和语法分析树的构建。

3. 语义分析器设计(1)语义分析器原理:语义分析器是编译程序中的第三个阶段,其作用是检查源程序中的语义是否正确。

本实验采用符号表来实现语义分析。

(2)实验步骤:a. 设计符号表:根据实验要求,设计符号表结构。

b. 实现语义分析器:编写C++代码实现语义分析器,包括符号表的构建和语义检查过程。

4. 中间代码生成(1)中间代码生成原理:中间代码生成是编译程序中的第四个阶段,其作用是将源程序转换为中间代码。

本实验采用三地址码作为中间代码。

(2)实验步骤:a. 设计三地址码:根据实验要求,设计三地址码格式。

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验概述本次实验旨在设计并实现一个简单的词法分析器,即实现编译器的第一个阶段,词法分析。

词法分析器将一段源程序代码作为输入,将其划分为一个个的词法单元,并将其作为输出。

二、实验过程1.设计词法规则根据编程语言的规范和所需实现的功能,设计词法规则,以明确规定如何将源程序代码分解为一系列的词法单元。

2.实现词法分析器采用合适的编程语言,根据所设计的词法规则,实现词法分析器。

词法分析器的主要任务是读入源程序代码,并将其根据词法规则进行分解,生成对应的词法单元。

3.测试词法分析器设计测试用例,用于检验词法分析器的正确性和性能。

测试用例应包含各种情况下的源程序代码。

4.分析和修正错误根据测试过程中发现的问题,分析产生错误的原因,并进行修正。

重复测试和修正的过程,直到词法分析器能够正确处理所有测试用例。

三、实验结果我们设计了一个简单的词法分析器,并进行了测试。

测试用例涵盖了各种情况下的源程序代码,包括正确的代码和错误的代码。

经过测试,词法分析器能够正确处理所有的测试用例。

词法分析器将源程序代码分解为一系列的词法单元,每个词法单元包含了单词的种类和对应的值。

通过对词法单元的分析,可以进一步进行语法分析和语义分析,从而完成编译过程。

四、实验总结通过本次实验,我深入了解了编译原理的词法分析阶段。

词法分析是编译器的第一个重要阶段,它将源程序代码分解为一个个的词法单元,为后续的语法分析和语义分析提供基础。

在实现词法分析器的过程中,我学会了如何根据词法规则设计词法分析器的算法,并使用编程语言实现词法分析器。

通过测试和修正,我掌握了调试和错误修复的技巧。

本次实验的经验对我今后的编程工作有很大帮助。

编译原理是计算机科学与技术专业的核心课程之一,通过实践能够更好地理解和掌握其中的概念和技术。

我相信通过进一步的学习和实践,我能够在编译原理领域取得更大的成果。

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。

本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。

二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。

此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。

三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。

在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。

首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。

然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。

在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。

对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。

(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。

在本次实验中,我们使用了递归下降的语法分析方法。

首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。

在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。

为了处理语法错误,在分析过程中添加了错误检测和处理机制。

当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。

(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。

在本次实验中,我们使用了三地址码作为中间代码的表示形式。

在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。

对于符合语义规则的语法结构,生成相应的三地址码指令。

四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。

编译原理 实验三 实验报告

编译原理 实验三 实验报告

实验报告第 1 页专业____软件工程________ 班级____2_____ 姓名_71李飞强77欧艺欣81吴文浩89张泰鑫__ 组别:第四组实验日期:2014年 3 月26 日报告退发(订正、重做)课程编译原理实验名称递归下降的预测分析一、实验目的1. 学会用语法图来形式化地描述一门简单的语言;2. 掌握递归下降的预测分析;3. 掌握词法分析。

二、实验环境Visual Studio 或 GCC 或Eclipse三、实验内容、步骤和结果分析实验内容:请基于递归下降的分析方法(教材P55页),编写一个“语法图.doc”所对应语言的语法分析器。

该语法分析器能读入一个源代码文件(如“test.c”文件所示),并判断其中的源代码是否符合“语法图.doc”的规定。

如果符合,打印出Yes;如果不符合,打印出No。

(所用编程语言不限)C语言版:#include<stdio.h>#include<string.h>#include<stdlib.h>#define MaxIdLen 20 //标志符的最大长度#define KeyWordsCount 5 //该语言拥有的关键字个数#define BoolValueCount 2 //bool类型可能取值的个数#define SymTypeCount 17 //symType个数enum SymType//枚举{OR , //或AND, //与LP, //左括号RP, //右括号ID, //标志符ASSIGN, //赋值LB, //左大括号RB, //右大括号COMMA, //逗号SEMICOLON, //分号UNDEFINED, //未定义BOOLVALUE, //bool类型的值IF, //ifELSE, //elseWHILE, //whilePRINTF, //printfBOOL, //bool};enum boolValue{TRUE,FALSE,};//关键字static char * keywords[KeyWordsCount] = { "if","else","while","printf","bool",};//关键字对应类别static int keyType[KeyWordsCount] = { IF,ELSE,WHILE,PRINTF,BOOL,};static char * boolvalue[BoolValueCount]={"true","false",};static int boolValueType[BoolValueCount]={TRUE,FALSE,};char ch=' '; //当前字符char id[MaxIdLen+1]; //当前符号串int token; //当前记号(的类型)int value; //当前记号的值FILE * fp; //用来打开要识别的源代码文件int lineNum=1; //要识别的代码行数bool isPass = false ; //判断识别的代码是否全部合法void getToken();void program();void program();void statement();void definition();void term();void factor();void expression();void match(int t);void main(){fopen_s(&fp,"D:\\test.c","r");getToken();program();if(isPass)printf("Y\n");else printf("N\n");fclose(fp);}/****************************************lexical*****************************************/int getKeyWord(char * str){for(int i=0;i<KeyWordsCount;i++)if(strcmp(str,keywords[i])==0)return keyType[i];return UNDEFINED;}int getBoolValue(char* str){for(int i=0;i<BoolValueCount;i++)if(strcmp(str,boolvalue[i])==0){value = boolValueType[i];return BOOLVALUE;}return UNDEFINED;}bool isLetter(char ch){return (ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'); }bool isDigit(char ch){return ch>='0'&&ch<='9';}void nextChar(){ch = fgetc(fp);}void getToken(){while(ch==' '||ch=='\t'||ch=='\r'||ch=='\n'){if(ch == '\n')lineNum++;nextChar();}if(isLetter(ch)){int index=0;id[index++] = ch;nextChar();while(isLetter(ch) || isDigit(ch)){if(index<MaxIdLen){id[index++] = ch;nextChar();}else{//cout<<"identifier is too long."<<endl;//exit(1);}}id[index]='\0';token = getKeyWord(id);if(token == UNDEFINED)token = getBoolValue(id);if(token == UNDEFINED){token = ID;}}else if(ch == '='){token = ASSIGN;nextChar();}else if(ch=='|'){nextChar();if(ch=='|'){token=OR;nextChar();}elseexit(1);}else if(ch=='&'){nextChar();if(ch=='&'){token=AND;nextChar();}elseexit(1);}else if(ch == ';'){token = SEMICOLON;nextChar();}else if(ch == '('){token = LP;nextChar();}else if(ch == ')'){token = RP;nextChar();}else if(ch == ','){token = COMMA;nextChar();}else if(ch == '{'){token = LB;nextChar();}else if(ch == '}'){token = RB;nextChar();}else if(ch == EOF){printf(" EOF!\n");isPass = true;}else{printf("第%d行不能识别的符号!\n",lineNum );exit(1);}}/****************************************grammar*****************************************/void match(int t){if(t == token){getToken();}else{printf("大概在第%d行错误\n",lineNum);exit(1);}}void expression(){term();while(token == OR){match(OR);term();}}void factor(){if(token == BOOLVALUE && value == TRUE)match(BOOLVALUE);else if(token == BOOLVALUE && value == FALSE) match(BOOLVALUE);else if(token == LP){match(LP);expression();match(RP);}else if(token == ID)match(ID);}void term(){factor();while(token == AND){match(AND);factor();}}void definition(){do{match(BOOL);match(ID);match(ASSIGN);expression();match(SEMICOLON);}while(token == BOOL);}void statement(){if(token == IF){match(IF);match(LP);expression();match(RP);statement();if(token == ELSE){match(ELSE);statement();}}else if(token == PRINTF){match(PRINTF);match(LP);expression();while(token == COMMA){match(COMMA);expression();}match(RP);match(SEMICOLON);}else if(token == WHILE){match(WHILE);match(LP);expression();match(RP);statement();}else if(token == LB){match(LB);do{statement();}while(token != RB);match(RB);}else if(token == ID){match(ID);match(ASSIGN);expression();match(SEMICOLON);}else if(token == SEMICOLON){match(SEMICOLON);}}void program(){definition();statement();}Java版:(吴文浩)Java版的关键代码:// 由语法分析带动翻译public void parse(String src) {this.lexer = new GrammarLexer(src);lookahead = lexer.getToken();program();}private void match(TokenType type) {// 如果记号lookahead的类型是type,则取下一个记号System.out.println("------------>" + type);if (lookahead.tokenType.equals(type)) {lookahead = lexer.getToken();} else {error("NO");// 否则报错}}private void error(String str) {// out.println(str);System.out.println(str);System.exit(-1);}/*** program:程序 definition----->statement-------->*/public void program() {definition();//定义statement();// 声明}// definition:定义/*** bool-->id-->=-->expression-->;*/public void definition() {do {match(TokenType.BOOLEAN);match(TokenType.ID);match(TokenType.EQUAL);expression();match(TokenType.SEMICOLON);// 匹配分号} while (lookahead.isBoolean());}// statement:声明public void statement() {if(lookahead.isIf()) {// -->if-->(-->expression-->)-->statement--->match(TokenType.IF);match(TokenType.LeftP);expression();match(TokenType.RightP);statement();if(lookahead.isElse()) {//缺陷:如果用全部代码测试时,程序走到这里停止了,while循环后的语句将不能执行!match(TokenType.ELSE);statement();} else {}} else if (lookahead.isWhile()) {match(TokenType.WHILE);match(TokenType.LeftP);expression();match(TokenType.RightP);statement();} else if (lookahead.isPrint()) {match(TokenType.PRINT);match(TokenType.LeftP);expression();while (lookahead.isComma()) {match(MA);expression();}match(TokenType.RightP);match(TokenType.SEMICOLON);} else if (lookahead.isSemicolon()) {// ;match(TokenType.SEMICOLON);} else if (lookahead.isLeftBrace()) {match(TokenType.LeftBrace);statement();while(!lookahead.isRightBrace() || lookahead.isId() ){//必须加入lookahead.isId()否则a = false;运行不出来(语法图缺陷吧!)statement();}match(TokenType.RightBrace);} else if (lookahead.isId()) {// id = expression;// System.out.println("++++++++++++++++++++");match(TokenType.ID);match(TokenType.EQUAL);expression();match(TokenType.SEMICOLON);} else {}}/***expression:式子-------->term()----(---->||------->term()---->);*/private void expression() {term();while (lookahead.isOr()) {// 如果是||就继续循环处理match(TokenType.OR);term();}}/***term:项 Factor(); While(match(‘&&’)){ Factor(); }*/private void term() {factor();while (lookahead.isAnd()) {// 判断是&&就继续进行match(TokenType.AND);factor();}}/*** --->(------>expression--------->)--------->* ---->true---->* ---->false---->* ---->id------>*/private void factor() {if (lookahead.isTrue()) {match(TokenType.TRUE);} else if (lookahead.isLeftP()) {match(TokenType.LeftP);expression();match(TokenType.RightP);} else if (lookahead.isFalse()) {match(TokenType.FALSE);} else if (lookahead.isId()) {match(TokenType.ID);} else{}}/*** 获取下一个Token*/public Token getToken() {int value = 0;char cur;while (true) {if (index >= src.length())return Token.EOF;else {// 取下一字符cur = next();// 如果下一个字符是空白,继续读取字符if (this.isBlank(cur))continue;else if (this.isAlpha(cur)) {// 字符缓冲区StringBuilder buffer = new StringBuilder();buffer.append(cur);while (isAlpha((char) peek())) {buffer.append(next());}if(buffer.toString().equals(KeyWord.BOOLEAN)) {return new Token(TokenType.BOOLEAN, buffer.toString());} else if (buffer.toString().equals(KeyWord.FALSE)) {return new Token(TokenType.FALSE, buffer.toString());} else if (buffer.toString().equals(KeyWord.TRUE)) {return new Token(TokenType.TRUE, buffer.toString());} else if(buffer.toString().equals(KeyWord.IF)) {return new Token(TokenType.IF, buffer.toString());} else if (buffer.toString().equals(KeyWord.WHILE)) {return new Token(TokenType.WHILE, buffer.toString());} else if (buffer.toString().equals(KeyWord.PRINT)) {return new Token(TokenType.PRINT, buffer.toString());} else {return new Token(TokenType.ID, buffer.toString());}} else if (cur == ',') {return MA;} else if (cur == '(') {return Token.LeftP;} else if (cur == ')') {return Token.RightP;} else if (cur == '|' && next() == '|') {return Token.OR;// 或者} else if (cur == '&' && next() == '&') {return Token.AND;// 且} else if (cur == '=') {return Token.EQUAL;} else if (cur == ';') {return Token.SEMICOLON;// 分号} else if (cur == '{') {// 左大括号return Token.LeftBrace;} else if (cur == '}') {return Token.RightBrace;} else if (cur == '\n') {line++;} else {this.error();}}}}运行这个测试代码的截图:String src = "boolean a = true;boolean b = false;boolean c = (a && b);if( a || b) print(a,b);else print(c);";运行这个测试代码的截图:String src = "boolean a = true; while(a && (b||c)){print(a,b,c);a = false;}";四、讨论(说明实验过程中遇到的问题及解决办法;未解决/需进一步研讨的问题或建议新实验方法等)在text.c中先是声明bool类型,然后是if语句,最后是while语句。

计算机编译原理实验报告

计算机编译原理实验报告

编译原理实验报告实验一词法分析设计一、实验功能:1、对输入的txt文件内的内容进行词法分析:2、由文件流输入test.txt中的内容,对文件中的各类字符进行词法分析3、打印出分析后的结果;二、程序结构描述:(源代码见附录)1、分别利用k[],s1[],s2[],s3[]构造关键字表,分界符表,算术运算符表和关系运算符表。

2、bool isletter(){} 用来判断其是否为字母,是则返回true,否则返回false;bool isdigit(){} 用来判断其是否为数字,是则返回true,否则返回false;bool iscalcu(){} 用来判断是否为算术运算符,是则返回true,否则返回false;bool reserve(string a[]){} 用来判断某字符是否在上述四个表中,是则返回true,否则返回false;void concat(){} 用来连接字符串;void getn(){} 用来读取字符;void getb(){} 用来对空格进行处理;void retract(){}某些必要的退格处理;int analysis(){} 对一个单词的单词种别进行具体判断;在主函数中用switch决定输出。

三、实验结果四、实验总结词法分析器一眼看上去很复杂,但深入的去做就会发现并没有一开始想象的那么困难。

对于一个字符的种别和类型可以用bool函数来判断,对于关键字和标示符的识别(尤其是3b)则费了一番功夫,最后对于常数的小数点问题处理更是麻烦。

另外,这个实验要设定好时候退格,否则将会导致字符漏读甚至造成字符重复读取。

我认为,这个实验在程序实现上大体不算困难,但在细节的处理上则需要好好地下功夫去想,否则最后的程序很可能会出现看上去没有问题,但实际上漏洞百出的状况。

将学过的知识应用到实际中并不简单,只有自己不断尝试将知识转化成程序才能避免眼高手低,对于知识的理解也必将更加深刻。

实验二LL(1)分析法一、实验原理:1、写出LL(1)分析法的思想:当一个文法满足LL(1)条件时,我们就可以为它构造一个不带回溯的自上而下的分析程序,这个分析程序是有一组递归过程组成的,每个过程对应文法的一个非终结符。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

编译原理实验报告实验一词法分析设计一、实验功能:1、对输入的IXt文件内的内容进行词法分析:2、由文件流输入IesiJxi中的内容,对文件中的各类字符进行词法分析3、打印出分析后的结果;二、程序结构描述:(源代码见附录)1、分别利用k[],siu,s2[],s3[]构造关键字表,分界符表,算术运算符表和关系运算符表。

2、bool isletter(){}用来判断其是否为字母,是则返回IrUe,否则返回false;bool isdigit(){)用来判断其是否为数字,是则返回IrUe,否则返回false;bool iscalcu(){)用来判断是否为算术运算符,是则返回IrUe,否则返回false;bool reserve(string a∣∣){)用来判断某字符是否在上述四个表中,是则返向InIe,否则返回false;void concat(){)用来连接字符串;void getn(){)用来读取字符;void getb(){)用来对空格进行处理;void retract(){}某些必要的退格处理;int analysis(){}对一个单词的单词种别进行具体判断;在主函数中用switch决定输出。

3| file.txt -记事本文件(F)编辑⑹格式(O)查看(V) W(H)if i = O then i ++; a <= 3b%); 富F:\cpp\词法分析器.exeProcess exited after 2.503 seconds with return信按任意键继续∙.∙四、实验总结词法分析器一眼看上去很复杂,但深入的去做就会发现并没有一开始想象的那么困难。

对于一个字符的种别和类型可以用b∞l 函数来判断,对于关键字和标示符的识别(尤其是 3b)则费了一番功夫,最后对于常数的小数点问题处理更是麻烦。

另外,这个实验要设定好 时候退格,否则将会导致字符漏读甚至造成字符重复读取。

我认为,这个实验在程序实现上大体不算困难,但在细节的处理上则需要好好地下功夫 去想,否则最后的程序很可能会出现看上去没有问题,但实际上漏洞百出的状况。

将学过的知识应用到实际中并不简单,只有自己不断尝试将知识转化成程序才能避免眼 高手低,对于知识的理解也必将更加深刻。

单词*******分析结果如下美 二元序列 类型then+ +3b<l,if > <6,i> <4,=> 〈5.0) <l,then> <6,i> <3,++> <6,a> <4,<=> Error Error <2,>> <2,;>关标天常关OW ⅛:天ErEr 八芬键识系匿识术识系rorr 字符运字符运符运r O B-Tnvp1%E,E--? 符符算算位置<1,1> <1,2> <1,3〉 <1,4〉 <1,5> <1,6〉 <1,7〉 <2,1> <2,2〉《2,3》<2,4) <2,5〉 value 0实验二LL(I)分析法一、实验原理:1、写出LL(I)分析法的思想:当一个文法满足LL(I)条件时,我们就可以为它构造一个不带回溯的自上而下的分析程序,这个分析程序是有一组递归过程组成的,每个过程对应文法的一个非终结符。

实现LL(I)分析的一种有效的方法是使用一张分析表和一个站进行联合控制。

预测分析表是一个M[A,a]形式的矩阵,存储着分析规则;栈STACK用于存放文法符号。

从栈顶取符号,按照分析表给出的规则进行有步骤的分析。

2.实验要求实现的文法:(1)E->TG(2)G->+TG∣-TG(3)G->ε(4)T->FS(5)S->*FS∣∕FS(6)S->ε(7)F->(E)(8)F->i二、程序结构:SlringM⑸⑻用来定义分析表:CharinPUl[50]用来存放输入的句子;vector<char> analysis用来存放分析栈;bool flag = true用来判断是否成功的标志;reference(char a,char i){)查询分析表,其中a为分析栈顶符号,i为输入串符号;pro(char a,char in){)用以做出具体的分析;LL(I)依测分析程序流程三、实验结果:运行程序,输入需要分析的语句,结果如下:四、实验总结:本次试验用代码实现了LL(I)文法,在过程中对于非终结符向终结符转换的过程中出现了一些问题,之后通过向同学请教得已解决。

本代码中的分析表写在了主函数中,可以说本程序只对这一个文法有效,这也是这个程序的局限性。

实验三LR(I)分析法一、实验原理LR (1)分析法实验设计思想及算法(1)总控程序,也可以称为驱动程序。

对所有的LR分析器总控程序都是相同的。

(2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTlON)和状态转换(GoTo) 表两个部分,它们都可用二维数组表示。

(3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。

分析器的动作就是由栈顶状态和当前输入符号所决定。

二、程序结构action[12][6]定义动作表;go[12][3]定义转换表:input[50]存放输入串;referaction(int s,char i){)查询action表,a为分析栈顶的状态,i为输入串的符号;refergo(int s,char i){}查询go 表;reduce(int n){ J 就近规约:analysis(int st,char in)( J 具体分析:LR分析器结构:♦其中:SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。

状态转换表用GOTO[i, X]=j表示,规定当栈顶状态为i,遇到当前文法符号为X时应转向状态j, X为终结符或非终结符。

♦ ACTION[i, a]规定了栈顶状态为i时遇到输入符号a应执行。

动作有四种可能:(1)移进:action[i, a]= Sj:状态j移入到状态栈,把a移入到文法符号栈,其中i,j表示状态号。

(2)归约:action[i, a]=rk:当在栈顶形成句柄时,则归约为相应的非终结符A,即文法中有A- B 的产生式,若B 的长度为R(即IBI=R),则从状态栈和文法符号栈中自顶向下去掉R 个符号,即栈指针SP 减去R,并把A 移入文法符号栈内, j=GOTO[i,A]移进状态栈,其中i 为修改指针后的栈顶状态。

(3)接受 acc:当归约到文法符号栈中只剩文法的开始符号S 时,并且输入符号串已结束即 当前输入符是'#',则为分析成功。

(4)报错:当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输 入端不是该文法能接受的符号串。

用IP 指向W#的第一个得号a 是ip 所搐向的桁号分别从桂BW 出W 个 符号,令s'是当前桂Bi 状轰 JRa 和先讯T 入桂中.S 出产 生或A>0.出幡处”三、实验结果:输入需要规约的字符串,结果如下:“的心止Ss'圮Nfs'分别■人 箝号枝和状态枝: 使桢蔺济TrF 一个Process exited after 8.325 seconds with return ualue 0 请按任意键继续...四、实验总结1、与算符优先分析方法比较,用LR 分析时,设计特定出错处理子程序比较容易,因为不 会发生不正确的归约。

在分析表的每一个空项内,可以填入一个指示器,指向特定的出错处 理子程序,第一类错误的处理一般采用插入、删除或修改的办法,但要注意,不能从栈内移 去任何那种状态,它代表已成功地分析了程序中的某一部分。

2、LR 分析法的归约过程是规范推导的逆过程,所以LR 分析过程是一种规范归约过程。

LR 分析法正是给出一种能根据当前分析栈中的符号串(通常以状态表示)和向右顺序查看输入 串的K 个(KeO)符号就可唯一地确定分析器的动作是移进还是归约和用哪个产生式归约, 因而也就能唯一地确定句柄。

其中LR(O)分析器是在分析过程中不需向右查看输入符号,因 而它对文法的限制较大,然而,它是构造其它LR 类分析器的基础。

因此,首先应学好LR(O) 项目集规范族构造的基本原理和方法。

当K=I 时,已能满足当前绝大多数高级语言编译程 序实现的需要。

SLR(I)分析是为学习LR(I)分析做准备,LR(I)项目集族的构造是LALR(I) 分析器的构造原理和基础。

LALR(I)分析器是当前大多数高级程序设计语言编译程序所采 用的语法分析技术,也是编译程序语法分析器自动构造工具YACC 的实现基本原理。

由此, LR(0)、SLR(1 )> LALR(I). LR(I)四种分析器的构造方法都必须深入理解和掌握。

3、经过以上三个实验的锤炼,不得不说自己编译原理这门课的认识又提高了一个阶层,对 编译原理的知识运用更加深入,编写过程中遇到不少的问题,结合课本及强大的网络资源, 在完成的过程中得到很多收获,不仅来自于对知识点的了解更加深入,更是对自己编程能力 的一次很好的锻炼,希望有更多这样实验的机会。

4、本人很希望在完成实验后,老师可以根据自己讲的课本,将自己所写的程序花一段时间 来讲解,我想这样会对不会编写的是一种教学,对会了的同学是一种榜样效应,可以让我们 有个目标追求,这样我们收获了的也会更加准确与丰富。

辄i 入哈句,L)述箔束:i+i*it ∣ 符号栈0 05 n Hi 03 #F 02 #T 01 ItE 016 #E+ 0165 ttE*i 0163 «E*F 0169 #E+T 01697 ttE*T* 016975 ttE*T*i 0169710 ttE+T*F 0169 #E*T 01 ttE剩余输入串i÷i*itt +i∙∙itt +i*i# +i*i» ÷i*itt i*i# *itt *itt*itt itt tt tt It tt力5 642656475 ⅛s PrrSSrrSSr6r3rlACM 约约约归卷 5Λ归归归6Λ5Λ归归7Λ5Λ归*F 蒜>i>F>τ态态X>F态态>ix>E 丽 P-T-』奈F-T-菜F-T-E-汤¾ F:\cpp\LR(l).exeG0T0<6,F>=3 GOTO<6,T>=9GOTO<7,F>=10 ,GOTO<6,T>=9 ,G OTO<0,E>-1GOTO<0,F>-3 GOTO<0,T>=2 GOTO<0,E>=1附录:实验一源代码:#include <iostream>#include <string>#include <fstream>using namespace std;string k∣] = {“do",“end","for","if n,"fTscanfTthen∖”While”};//关键字string sl[]= ")",T,T};〃分界符string s2∣]= “*”「7",”++”,”」};〃算术运算符string s3[]= {y丁J!=");〃关系运算符string id[IOO];string ci[100];ifstream in;char ch;int row =l,col = 0;〃行数与列数int idcount = 0,cicount = 0;string strtoken;bool isletter(){∕/用来判断其是否为字母if(ch >= 'A, && ch <= 'z,)return true;elsereturn false;)bool isdigil(){∕/用来判断其是否为数字if(ch >= '0' && ch <= '9')return true;elsereturn false;)bo。

相关文档
最新文档