《编译原理》课程设计报告--词法分析器
- 格式:pdf
- 大小:325.00 KB
- 文档页数:15
编译原理词法分析实验报告实验名称:词法分析器的设计与实现一、实验目的:1.熟悉编译原理中词法分析的基本概念和原理;2.掌握正则表达式的使用方法;3.实现一个简单的词法分析器。
二、实验内容:1.设计一个简单的编程语言,包含如下几种类型的词法单元:关键字、标识符、常量、运算符和界符。
2.使用正则表达式定义每种词法单元的模式。
3.设计一个词法分析器,将源代码中的每个词法单元识别出来并输出。
三、实验步骤:1. 确定编程语言的词法单元类型和正则表达式模式,定义相应的单词类型(如 TokenType)和模式(如 regex)。
2. 实现一个词法分析器的类 Lexer,包含以下方法:(1)一个构造方法,用于初始化词法分析器的输入源代码。
(2) 一个getNextToken方法,用于获取源代码中的下一个词法单元。
3. 在getNextToken方法中,使用正则表达式逐个识别源代码中的词法单元,并返回相应的Token对象。
4. 设计一个Token类,包含以下属性:词法单元类型、词法单元的值和位置信息等。
5.在主程序中使用词法分析器,将源代码中的每个词法单元识别出来并输出。
四、实验结果:1.设计一个简单的编程语言,包含如下词法单元类型(示例):(1) 关键字:if、else、while、for等;(2)标识符:变量名等;(3)常量:整数、浮点数、字符串等;(4)运算符:+、-、*、/、=等;(5)界符:(、)、{、}、;等。
2. 实现一个词法分析器,识别出源代码中的每个词法单元,并输出相应的Token对象。
五、实验总结:通过本次实验,我熟悉了编译原理中词法分析的基本概念和原理,并掌握了正则表达式的使用方法。
我成功完成了一个简单的词法分析器的设计与实现,实现了源代码中每个词法单元的识别与输出。
这次实验对我深化了对编译原理中词法分析的理解,并提高了我的编程能力。
编译原理实验词法分析实验报告一、实验目的词法分析是编译过程的第一个阶段,其主要任务是从左到右逐个字符地对源程序进行扫描,产生一个个单词符号。
本次实验的目的在于通过实践,深入理解词法分析的原理和方法,掌握如何使用程序设计语言实现词法分析器,提高对编译原理的综合应用能力。
二、实验环境本次实验使用的编程语言为_____,开发工具为_____。
三、实验原理词法分析的基本原理是根据编程语言的词法规则,将输入的字符流转换为单词符号序列。
单词符号通常包括关键字、标识符、常量、运算符和界符等。
词法分析器的实现方法有多种,常见的有状态转换图法和正则表达式法。
在本次实验中,我们采用了状态转换图法。
状态转换图是一种有向图,其中节点表示状态,有向边表示在当前状态下输入字符的可能转移。
通过定义不同的状态和转移规则,可以实现对各种单词符号的识别。
四、实验步骤1、定义单词符号的类别和编码首先,确定实验中要识别的单词符号种类,如关键字(if、else、while 等)、标识符、整数常量、浮点数常量、运算符(+、、、/等)和界符(括号、逗号等)。
为每个单词符号类别分配一个唯一的编码,以便后续处理。
2、设计状态转换图根据单词符号的词法规则,绘制状态转换图。
例如,对于标识符的识别,起始状态为“起始状态”,当输入为字母时进入“标识符中间状态”,在“标识符中间状态”中,若输入为字母或数字则继续保持该状态,直到遇到非字母数字字符时结束识别,确定为一个标识符。
3、编写词法分析程序根据状态转换图,使用所选编程语言实现词法分析器。
在程序中,通过不断读取输入字符,根据当前状态进行转移,并在适当的时候输出识别到的单词符号。
4、测试词法分析程序准备一组包含各种单词符号的测试用例。
将测试用例输入到词法分析程序中,检查输出的单词符号是否正确。
五、实验代码以下是本次实验中实现词法分析器的核心代码部分:```include <stdioh>include <ctypeh>//单词符号类别定义typedef enum {KEYWORD,IDENTIFIER,INTEGER_CONSTANT,FLOAT_CONSTANT,OPERATOR,DELIMITER} TokenType;//关键字列表char keywords ={"if","else","while","for","int","float","void"};//状态定义typedef enum {START,IN_IDENTIFIER,IN_INTEGER,IN_FLOAT,IN_OPERATOR} State;//词法分析函数TokenType getToken(char token, int tokenLength) {State state = START;int i = 0;while (1) {char c = getchar();switch (state) {case START:if (isalpha(c)){state = IN_IDENTIFIER;tokeni++= c;} else if (isdigit(c)){state = IN_INTEGER;tokeni++= c;} else if (c =='+'|| c ==''|| c ==''|| c =='/'|| c =='('|| c ==')'|| c ==';'|| c ==','){state = IN_OPERATOR;tokeni++= c;} else if (c ==''){state = IN_FLOAT;tokeni++= c;} else if (c == EOF) {tokeni ='\0';tokenLength = i;return -1;} else {tokeni ='\0';tokenLength = i;return -2;}break;case IN_IDENTIFIER:if (isalpha(c) || isdigit(c)){tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;//检查是否为关键字for (int j = 0; j < sizeof(keywords) / sizeof(keywords0); j++){if (strcmp(token, keywordsj) == 0) {return KEYWORD;}}return IDENTIFIER;}break;case IN_INTEGER:if (isdigit(c)){tokeni++= c;} else if (c ==''){state = IN_FLOAT;tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;return INTEGER_CONSTANT;}break;case IN_FLOAT:if (isdigit(c)){tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;return FLOAT_CONSTANT;}break;case IN_OPERATOR: tokeni ='\0';tokenLength = i;return OPERATOR; break;}}}int main(){char token100;int tokenLength;TokenType tokenType;while ((tokenType = getToken(token, &tokenLength))!=-1) {switch (tokenType) {case KEYWORD:printf("Keyword: %s\n", token);break;case IDENTIFIER:printf("Identifier: %s\n", token);break;case INTEGER_CONSTANT:printf("Integer Constant: %s\n", token);break;case FLOAT_CONSTANT:printf("Float Constant: %s\n", token);break;case OPERATOR:printf("Operator: %s\n", token);break;case DELIMITER:printf("Delimiter: %s\n", token);break;}}return 0;}```六、实验结果对准备的测试用例进行输入,得到的词法分析结果如下:测试用例 1:```int main(){int num = 10;float pi = 314;if (num > 5) {printf("Hello, World!\n");}}```词法分析结果:```Keyword: int Identifier: main Delimiter: (Delimiter: ){Identifier: num Operator: =Integer Constant: 10;Identifier: float Identifier: pi Operator: =Float Constant: 314;Keyword: ifDelimiter: (Identifier: numOperator: >Integer Constant: 5){Identifier: printfDelimiter: (String: "Hello, World!\n" Delimiter: );}```测试用例 2:```for (int i = 0; i < 10; i++){double result = i 25;```词法分析结果:```Keyword: for Delimiter: (Keyword: int Identifier: i Operator: =Integer Constant: 0;Identifier: i Operator: <Integer Constant: 10;Identifier: i Operator: ++)Identifier: doubleIdentifier: resultOperator: =Identifier: iOperator:Float Constant: 25;}```通过对多个测试用例的分析,词法分析器能够正确识别出各种单词符号,实验结果符合预期。
编译方法课程设计词法分析器设计学院:计算机与信息工程学院专业:软件工程学号:姓名:指导教师:职称:设计报告日期:二О一二年十二月目录1设计概述 (2)1.1设计题目 (2)1.2 设计目的 (3)1.3 设计任务内容: (3)1.4 设计时间 (3)2 设计环境与工具 (3)3设计要求 (3)4分析与概要设计 (4)5算法描述与框图 (4)6 源程序清单 (6)7 软件测试 (10)7.1 设计的测试题目 (10)7.2测试结果截图 (10)8 总结 (10)8 参考文献 (11)1设计概述1.1设计题目词法分析器的设计与实现。
1.2 设计目的词法分析是编译程序第一个阶段的工作,它的任务是对输入的字符串形式的源程序进行扫描,在扫描的同时,根据源语言的词法规则识别具有独立意义的单词。
本设计是C++高级程序语言,数据结构和变异原理中词法分析原理等知识的综合运用。
掌握生成词法分析器的方法,加深对词法分析原理的理解,掌握设计,编制并调试词法分析程序的思想和方法。
1.3 设计任务内容:1、格式输入:将C++语言的源代码从文本文档中读入。
处理:对输入框中的代码进行词法分析,分离出关键字、标示符、数值、运算符和界符。
输出:在文本文档中输出每个单词对应的编码和值。
2、编译对象声明和其他标记赋值语句分支结构语句循环语句1.4 设计时间2012年12月23日至2012年12月28日2 设计环境与工具Windows7环境下使用 C++语言。
3设计要求1、使用任何一种编程语言编制一个词法分析程序。
2、该程序能够识别的单词有5类:(1)关键字:"long", "float", "static", "char", "short", "switch", "int", "const", "if", "then", "else", "for", "while", "break"。
编译原理课程设计1一、题目:词法分析器二、运行环境:JAVA jdk1.6.0_21三、设计思路:编译程序的工作过程一般划分为五个阶段:词法分析、语法分析、语义分析与中间代码产生、优化、目标代码生成。
作为本次课程设计的词法分析器的主要任务是,对输入的源程序字符串进行扫描和分解,识别出一个个的单词,如基本字(include、if、while、for等),标识符、常数、算符和界符。
本次课程设计词法分析我选取的目标语言为C语言。
关于种别码的分配,我对关键字采用一字一种,对运算符采用一符一种,对界符采用一符一种,整型常量为一种,浮点常量为一种,字符常量为一种,字符串常量为一种。
(详情参加附录1)本次词法分析器工作的第一步是输入源程序文本。
通过调用预处理子程序去除程序两端多余的空格、注释,再将处理得到的串存放在一个缓冲区中。
第二步是对关键字、标示符、数字以及算符和界符的识别过程,并返回识别出的单词的种别码和内容(单词值,种别码),在过程中进行必要的出错处理。
第三步即将所识别出来的单词及种别码输出到文件保存。
四、基本工具UML及JAVA语言五、状态转换图:六、程序源码:import java.util.ArrayList;import java.io.*;//记法分析器类class Lex{char ch[] = new char[300];String token;int flag;ArrayList<String> buffer = new ArrayList<String>();ArrayList<String> errorqueue = new ArrayList<String>();ArrayList<String> queue = new ArrayList<String>();int buffer_current,buffer_advance,index_queue,index_error,line,buffersize;public Lex(){buffer_current=buffer_advance=index_queue=index_error = buffersize = 0;line = 1;flag = 0;}//判断是否为字母public boolean isletter(char cc){if ((cc>='a'&&cc<='z')||(cc>='A'&&cc<='Z')){return true;}else{return false;}}//判断是否为数字public boolean isdigit(char cc){if (cc>='0'&&cc<='9'){return true;}else{return false;}}//预处理子程序,读入源程序,并装入bufferpublic void prepare(){int k ;String sub;try{FileReader filein = new FileReader("in.txt");filein.read(ch);String str = new String(ch);k = 0;while(k<300){buffer.add(sub);buffersize++;k++;filein.close();}}catch (Exception e){String err = e.toString();System.out.println(err);}}//result_out函数将所有识别了的单词输出到文件out.txt public void result_out(){int k;if (index_queue == 0){System.out.println("The queue is empty!");return;}try{FileWriter fileout = new FileWriter("out.txt");fileout.write("\t符号(值)\t种别码\n");for (k =0; k<index_queue ; k++ ){fileout.write(queue.get(k));}fileout.close();}catch (Exception e){String err = e.toString();System.out.println(err);}}//error_out函数将所有识别了的错误情形输出到文件error.txtpublic void error_out(){int k;if (index_error == 0){System.out.println("The errorqueue is empty!");return;}try{FileWriter errorout = new FileWriter("error.txt");for (k =0; k<index_error ; k++ ){errorout.write(queue.get(k));}errorout.close();}catch (Exception e){String err = e.toString();System.out.println(err);}}//判断是否为保留字public int isreserve(String s){String str[] = {"define","include","char","double","enum","float","int","long","short","signed","struct","union","unsigned","void","for","do","while","break","continue","if", "else","goto","switch","case","default","return","auto","extern","register","static","const","sizeof","typedef","volatile"};int k;for ( k =0 ; k < 34 ; k++ ){if (str[k].equals(s)){return (k+4);}}return 0;}//往queue队列添加一个新识别的单词public void insert_queue(String s){queue.add(s);index_queue++;}//往errorqueue队列添加一个新发现的错误public void insert_error(String s){errorqueue.add(s);index_error++;}//读掉空格public void space(){String s;do{s = queue.get(buffer_advance);if (s.equals(" ")){if (buffer_advance+1 == buffersize){flag = 1;return;}buffer_advance++;}else{break;}}while(true);buffer_current = buffer_advance;}// 读掉形如的//.... \n 注释public void comment1(){String s;do{s = queue.get(buffer_advance);if (s.equals("\n")){line++;break;}{if (buffer_advance+1 == buffersize){flag = 1;return;}buffer_advance++;}}while(true);buffer_current = buffer_advance;}// 读掉形如的/*.... */ 注释public void comment2(){String s1,s2;do{s1 = queue.get(buffer_advance);s2 = queue.get(buffer_advance+1);if (s1.equals("\n")){buffer_advance++;line++;}else if (s1.equals("*")&&s2.equals("/")){buffer_advance = buffer_advance + 2;break;}else{if (buffer_advance+1 == buffersize){flag = 1;return;}buffer_advance++;}}while(true);buffer_current = buffer_advance;}//实现单词识别public void dfa(){int flag2;String s1,s2;prepare();while ( flag == 0 ){flag2 = 0;token = "";//存放识别出来的单词space();do{s1 = queue.get(buffer_advance);s2 = queue.get(buffer_advance+1);if (s1.equals("/")&&s2.equals("/")){if (buffer_advance+2 == buffersize){flag = 1;break;}buffer_advance = buffer_advance+2;comment1();}else if (s1.equals("/")&&s2.equals("*")){if (buffer_advance+2 == buffersize){flag = 1;break;}buffer_advance = buffer_advance+2;comment2();}else if (s1.equals("\n")){if (buffer_advance+1 == buffersize){flag = 1;break;}buffer_advance++;line++;}else{break;}space();}while (true);//下面是数值常量识别主要是实数和整数的识别if (isdigit(s1.charAt(0))){flag2 = 2;token = token + s1;buffer_advance++;s1 = buffer.get(buffer_advance);while (isdigit(s1.charAt(0))){token = token + s1;if (buffer_advance+1 != buffersize){buffer_advance++;s1 = buffer.get(buffer_advance);}else{insert_queue("\t"+token+"\t2\n");break;}}/*如果数字后碰到小数点,小数点后不是数字,则要捕捉错误异常;如果还是数字,则和上面的方法一样,将一串数字连为一个实数*/if(s1.equals(".")){flag = 3;token = token + s1;buffer_advance++;s1 = buffer.get(buffer_advance);if (!isdigit(s1.charAt(0))){insert_error("\n程序第("+line+")行有错误错误单词为:"+token+"\n");continue;}while (isdigit(s1.charAt(0))){token = token + s1;if (buffer_advance+1 != buffersize){buffer_advance++;s1 = buffer.get(buffer_advance);}else{insert_queue("\t"+token+"\t3\n");break;}}}//如果碰到科学计数法中的e,要取出它面的符号,然后再取出数值部分if (s1.equalsIgnoreCase("e")){token = token + s1;buffer_advance++;if (buffer_advance!= buffersize){s1 = buffer.get(buffer_advance);}else{insert_queue("\t"+token+"\t3\n");break;}if (s1.equals("-")){token = token + s1;buffer_advance++;if (buffer_advance != buffersize){s1 = buffer.get(buffer_advance);}else{insert_error("\n程序第("+line+")行有错误错误单词为:"+token+"\n");break;}}else if (s1.equals("+")){token = token + s1;buffer_advance++;if (buffer_advance != buffersize){s1 = buffer.get(buffer_advance);}else{insert_error("\n程序第("+line+")行有错误错误单词为:"+token+"\n");break;}}if (!isdigit(s1.charAt(0))){insert_error("\n程序第("+line+")行有错误错误单词为:"+token+"\n");continue;}while (isdigit(s1.charAt(0))){flag = 3;token = token + s1;buffer_advance++;if (buffer_advance != buffersize){s1 = buffer.get(buffer_advance);}else{insert_queue("\t"+token+"\t3\n");continue;}}}//科学eif(flag == 2){insert_queue("\t"+token+"\t2\n");continue;}if(flag == 3){insert_queue("\t"+token+"\t3\n");continue;}}//数字识别//下面是标志符及保留字识别if (isletter(s1.charAt(0))||s1.charAt(0)=='_'){token = token +s1;int t;do{buffer_advance++;if (buffer_advance!=buffersize){s1 = buffer.get(buffer_advance);}else{break;}if (isletter(s1.charAt(0))||s1.charAt(0)=='_'||isdigit(s1.charAt(0))){token = token +s1;}else{break;}}while (true);if ((t = isreserve(token))!=0){insert_queue("\t"+token+"\t"+t+"\n");}else{insert_queue("\t"+token+"\t71\n");}continue;}// if (isletter(s1.charAt(0))||s1.charAt(0)=='_')//下面是识别字符常量如'a'if (s1.charAt(0) == '\''){token = token + s1;if (buffer_advance +2>=buffersize){insert_error("\n程序第("+line+")行有错误错误单词为:"+token+"\n");continue;}else{buffer_advance++;s1 = buffer.get(buffer_advance);token = token + s1;}s2 = buffer.get(buffer_advance);if (s2.charAt(0)== '\''){token = s1;buffer_advance++;insert_queue("\t"+token+"\t0\n");}else{insert_error("\n程序第("+line+")行有错误错误单词为:"+token+"\n");}continue;}// 下面是识别字符串常量if (s1.charAt(0) == '\"'){do{buffer_advance++;s1 = queue.get(buffer_advance);if (s1.equals("\"")){insert_queue("\t"+token+"\t1\n");buffer_advance++;break;}else{if (buffer_advance+1 == buffersize){insert_error("\n程序第("+line+")行有错误错误单词为:"+token+"\n");flag = 1;break;}token = token + s1;}}while(true);continue;}//下面是识别运算符+ 或++if (s1.charAt(0)=='+'){token =token + s1;buffer_advance++;{insert_queue("\t+"+"\t38\n");break;}else{s1 = buffer.get(buffer_advance);if (s1.equals("+")){buffer_advance++;insert_queue("\t++"+"\t46\n");}else{insert_queue("\t+"+"\t38\n");}}continue;}//下面是识别运算符- 或-- 或->if (s1.charAt(0)=='-'){token =token + s1;buffer_advance++;if (buffer_advance == buffersize){insert_queue("\t-"+"\t39\n");break;}else{s1 = buffer.get(buffer_advance);if (s1.equals("-")){buffer_advance++;insert_queue("\t--"+"\t47\n");}else if (s1.equals(">")){buffer_advance++;insert_queue("\t->"+"\t68\n");}else{}}continue;}//下面是识别运算符* 或者**if (s1.charAt(0)=='*'){token =token + s1;buffer_advance++;if (buffer_advance == buffersize){insert_queue("\t*"+"\t40\n");break;}else{s1 = buffer.get(buffer_advance);if (s1.equals("*")){buffer_advance++;insert_queue("\t**"+"\t50\n");}else{insert_queue("\t*"+"\t40\n");}}continue;}//下面是识别运算符/if (s1.charAt(0)=='/'){insert_queue("\t/"+"\t41\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别运算符& 或者&&if (s1.charAt(0)=='&'){token =token + s1;if (buffer_advance == buffersize){insert_queue("\t&"+"\t42\n");break;}else{s1 = buffer.get(buffer_advance);if (s1.equals("&")){buffer_advance++;insert_queue("\t&&"+"\t48\n");}else{insert_queue("\t&"+"\t42\n");}}continue;}//下面是识别运算符| 或者||if (s1.charAt(0)=='|'){token =token + s1;buffer_advance++;if (buffer_advance == buffersize){insert_queue("\t|"+"\t43\n");break;}else{s1 = buffer.get(buffer_advance);if (s1.equals("|")){buffer_advance++;insert_queue("\t||"+"\t49\n");}else{insert_queue("\t|"+"\t43\n");}}continue;//下面是识别运算符! 或者!=if (s1.charAt(0)=='!'){token =token + s1;buffer_advance++;if (buffer_advance == buffersize){insert_queue("\t!"+"\t44\n");break;}else{s1 = buffer.get(buffer_advance);if (s1.equals("=")){buffer_advance++;insert_queue("\t!="+"\t54\n");}else{insert_queue("\t!"+"\t44\n");}}continue;}//下面是识别运算符%if (s1.charAt(0)=='%'){insert_queue("\t%"+"\t45\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别运算符> 或者>=if (s1.charAt(0)=='>'){token =token + s1;buffer_advance++;if (buffer_advance == buffersize){insert_queue("\t>"+"\t51\n");}else{s1 = buffer.get(buffer_advance);if (s1.equals("=")){buffer_advance++;insert_queue("\t>="+"\t56\n");}else{insert_queue("\t>"+"\t51\n");}}continue;}//下面是识别运算符< 或者<=if (s1.charAt(0)=='<'){token =token + s1;buffer_advance++;if (buffer_advance == buffersize){insert_queue("\t<"+"\t52\n");break;}else{s1 = buffer.get(buffer_advance);if (s1.equals("=")){buffer_advance++;insert_queue("\t<="+"\t57\n");}else{insert_queue("\t<"+"\t52\n");}}continue;}//下面是识别运算符= 或者==if (s1.charAt(0)=='='){buffer_advance++;if (buffer_advance == buffersize){insert_queue("\t="+"\t53\n");break;}else{s1 = buffer.get(buffer_advance);if (s1.equals("=")){buffer_advance++;insert_queue("\t=="+"\t55\n");}else{insert_queue("\t="+"\t53\n");}}continue;}//下面是识别界符(if (s1.charAt(0)=='('){insert_queue("\t("+"\t58\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符)if (s1.charAt(0)==')'){insert_queue("\t)"+"\t59\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符#insert_queue("\t#"+"\t60\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符;if (s1.charAt(0)==';'){insert_queue("\t;"+"\t61\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符,if (s1.charAt(0)==','){insert_queue("\t,"+"\t62\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符:if (s1.charAt(0)==':'){insert_queue("\t:"+"\t63\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符{insert_queue("\t{"+"\t64\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符}if (s1.charAt(0)=='}'){insert_queue("\t}"+"\t65\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符[if (s1.charAt(0)=='['){insert_queue("\t["+"\t66\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符]if (s1.charAt(0)==']'){insert_queue("\t]"+"\t67\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}//下面是识别界符.if (s1.charAt(0)=='.')insert_queue("\t."+"\t69\n");buffer_advance++;if (buffer_advance == buffersize){break;}continue;}}//while(flag == 1)if (index_queue>0){result_out();}if (index_error>0){error_out();}}}public class startLex{public static void main ( String args[] ){Lex l = new Lex();l.dfa();}}七、运行结果:运行前源程序存放在in.txt中,如图(1)所示,运行后得到的识别单词结果存放在out.txt中,如图(2)所示,识别过程中发现的错误存放在error.txt中,如图(3)所示。
词法分析器的作用词法分析是编译的第一阶段。
词法分析器的主要任务是读入源程序的输入字符,将它们组成词素,生成并输出一个词法单元序列,这个词法单元序列被输出到语法分析器进行语法分析。
另外,由于词法分析器在编译器中负责读取源程序,因此除了识别词素之外,它还会完成一些其他任务,比如过滤掉源程序中的注释和空白,将编译器生成的错误消息与源程序的位置关联起来等。
总而言之,词法分析器的作用如下:1.读入源程序的输入字符,将它们组成词素,生成并输出一个词法单元序列;2.过滤掉源程序中的注释和空白;3.将编译器生成的错误消息与源程序的位置关联起来;4.其它。
词法分析过程首先,对某个正则语言L,构造能够描述其的正则表达式r;然后,需要将r 转换成一个有穷自动机。
这里有三种方法,一是直接转换成NFA,而是直接转换成DFA,三是先转换成NFA,再把NFA 转换成DFA;最后,如果将r 转换成了一个DFA,需要将此DFA 的状态数最小化。
正则表达式正则表达式可以用来描述词素的模式,一个正则表达式可以由较小的正则表达式递归的构建。
对于符号集合∑={a,b},有:-正则表达式a 表示语言{a};-正则表达式a|b 表示语言{a,b};-正则表达式(a|b)(a|b)表示语言{aa,ab,ba,bb};-正则表达式a*表示语言{ε,a,aa,aaa,…};-正则表达式(a|b)*表示语言{ε,a,b,aa,ab,ba,bb,aaa,…};-正则表达式a|a*b 表示语言{a,b,ab,aab,aaab,…}。
上面通过基本的并、连接和闭包运算递归定义了正则表达式有穷自动机一个有穷自动机可以把一个描述词素的模式变成一个词法分析器,从本质上来讲,有穷自动机是与状态转换图相类似的图,它有以下特点:有穷自动机是一个识别器,它只能对每个输入符号串简单的输出“yes”或“no”,表示是否能够识别此符号串;有穷自动机和状态转换图类似,它具有有限个数的结点,每个结点表示一个状态,并且这些状态中有一个初始状态和若干个终止状态。
编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。
该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。
二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。
四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。
int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。
void GetChar(char *ch); //将下一个输入字符读到ch中。
void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。
void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。
int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。
void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。
编译原理课程设计报告题目:学院:教师::学号:班级:评分:签字:编译原理课程设计一:设计c语言的词法分析器一、实验目的了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程,加深对词法原理的理解。
二、实验要求了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。
三、实验设计3.1.单词分类及表示3.1.1 C语言的子集分类(1)标识符:以字母开头的字母数字串(2)整数或浮点型。
(3)保留字:for,while,do,else,if,static,int,sizeof,break,continue(4)运算符:+,-,*,/,%,>,<,=,!=,==,<=,>=,!,&,&&,||;(5)界符:"(",")",",",":",";","{","}"3.1.2单词二元组(单词分类号、单词自身值)3.2 词法分析器的设计3.2.1算法设计3.2.1.1概要设计从文件中逐个读取字符,只要这五大类的状态序列则继续读取,否则回退字符,在对应类别进行查找,输出单元二次组至另一文件夹。
3.2.1.2状态图设计开始打开txt文件读取c语言代码扫描是否读取到相应字符常数?标识符保留字运算符记录标号结束界符?YY Y3.2.2输入输出设计输入:通过文件指针从文件中一个一个读取字符输出:输出单词二元组至文件。
格式为(种别码,值)3.2.3主要函数void Getchar(FILE *fp ) //读入一个字符void GetBC(FILE *fp)//读入一个非空字符void contacat()//连接字符int letter()//判断是否为字母int digit()//判断是否为字母void retract(FILE *fp,char *c)//回退int reserve (char **k)//处理保留字int sysmbol(identifier *id)//处理标识符,查找符号表并存放位置若没有则添加int constant(constnumber *con)//存入常数表,并返回它在常数表中的位置void Tofile(int num, int val, identifier *id, constnumber *con, FILE *fw)//写到文件void WordAnalyze(char **k,char *c, char **CODE, identifier *id, constnumber *con, FILE *fp, FILE *fw)//词法分析函数四、结果测试文件输入int main(){int a=1,b=3;if(a>1)b=b-2;}输出结果:结论:程序输出结果与期望输出结果相符。
词法分析器实验报告实验目的:设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。
功能描述:该程序要实现的是一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error!”,然后跳过错误部分继续进行)设计思想:设计该词法分析器的过程中虽然没有实际将所有的状态转移表建立出来,但是所用的思想是根据状态转移表实现对单词的识别。
首先构造一个保留字表,然后,每输入一个字符就检测应该进入什么状态,并将该字符连接到d串后继续输入,如此循环,最后根据所在的接受状态以及保留字表识别单词。
符号表:记号类别属性值ws - -const 保留字 1var 保留字 1call 保留字 1begin 保留字 1if 保留字 1while 保留字 1do 保留字 1odd 保留字 1end 保留字 1then 保留字 1procedure 保留字 1= 运算符 2< 运算符 2<= 运算符 2<> 运算符 2> 运算符 2>= 运算符 2* 运算符 2+ 运算符 2- 运算符 2/ 运算符 2:= 运算符 2ident 标识符 3number 常数 4 ( 分隔符 5) 分隔符 5; 分隔符 5, 分隔符 5. 分隔符 5状态转换图:①标识符及保留字:letter or digittStart letter②number:③关系操作符:0 21 435startdigit.digit E+ | -digitdigitdigitdigitEdigit otherother④分隔符:start< other =(<=, 2) >= other>=* * (<>, 2)(<,2)(=, 2)(>=, 2)(>, 2):=(:=,2)⑤算术运算符:使用环境:Windows xp 下的visual c++6.0程序测试: input1 : int a,b;start;( ),.( ; ,5)( (,5)( ),5) ( , ,5)( . ,5)start+- * /( + ,2) ( -,2)( *,2) ( / ,2). a=b+2;input2:while(a>=0)do7x=x+6.7E+23;end;input3:begin:x:=9if x>0 then x:=x+1;while a:=0 dob:=2*x/3,c:=a;end;output1: 3,int 3,a 5,,3,b 5,;3,a2,=3,b2,+4,2 5,; output2:output2:1,while5,(3,a2,>=4,05,)1,doerror line 32,=3,x2,+4,6.7E+235,;1,end5,;output3:output3:1,beginerror line 13,x2,:=4,91,if3,x2,>4,01,then3,x2,:=3,x2,+4,15,;1,while3,a2,:=4,01,do 3,b 2,:= 4,2 2,* 3,x 2,/4,35,,3,c2,:=3,a5,;1,end5,;测试结果与预期结果一致源程序代码:#include<stdio.h>#include<string.h>void main(){int i=0,j,k=0,state=1,f=0,linenum=1;chara[11][10]={"const","var","call","begin","if","while","do","odd","end","then","proc edure"};char b,d[40]={"\0"};freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);b=getchar();while(b!=EOF)/*判断所输入字符是否为结束符*/{if(b==' '||b=='\n'||b=='\t')/*滤过空格、换行等分隔符号*/{ if(b='\n') linenum++;b=getchar();}else if((b>='a'&&b<='z')||(b>='A'&&b<='Z'))/*识别标识符以及保留字*/{d[i++]=b;b=getchar();while((b>='a'&&b<='z')||(b>='A'&&b<='Z')||(b>='0'&&b<='9')){d[i++]=b;b=getchar();}for(j=0;j<11;j++)/*查询保留字表确定该单词是否是保留字*/{ if(strcmp(d,a[j])==0){ printf("1,%s\n",d);k=1;break;}}if(k==0)/*在保留字表中没有查到该单词,是标识符*/printf("3,%s\n",d);for(j=0;j<=i;j++)d[j]='\0';i=0;k=0;}else if(b>='0'&&b<='9')/*识别常数*/{ d[i++]=b;b=getchar();while(f!=1){switch (state) {case 1:if(b>='0'&&b<='9') {state=1;d[i++]=b;b=getchar();}else if(b=='.') { state=2;d[i++]=b;b=getchar();}else if(b=='E') { state=4;d[i++]=b;b=getchar();}else state=7;break;case 2:if(b>='0'&&b<='9') {state=3;d[i++]=b;b=getchar();}else state=8;break;case 3:if(b>='0'&&b<='9') {state=3;d[i++]=b;b=getchar();}else if(b=='E') { state=4;d[i++]=b;b=getchar();}else state=7;break;case 4:if(b=='+'||b=='-') { state=5;d[i++]=b;b=getchar();}else if(b>='0'&&b<='9'){ state=6;d[i++]=b;b=getchar();} else state=8;break;case 5:if(b>='0'&&b<='9'){ state=6;d[i++]=b;b=getchar();}else state=8;break;case 6:if(b>='0'&&b<='9'){ state=6;d[i++]=b;b=getchar();}else state=7;break;case 7: f=1;break;case 8: f=1;break;}}if(state==7&&(b<'a'||b>'z')&&(b<'A'||b>'Z'))printf("4,%s\n",d);else if(state==7&&(b>='a'&&b<='z')||(b>='A'&&b<='Z'))/*数字后接字母的出错控制*/{while((b>='a'&&b<='z')||(b>='A'&&b<='Z')){ d[i++]=b;b=getchar();}printf("error line %d\n",linenum);}else printf("error line %d\n",linenum);for(j=0;j<=i;j++)d[j]='\0';i=0;f=0;state=1;}else if(b=='<')/*识别'<'、'<='和'<>'*/{ d[i++]=b;b=getchar();if(b=='='||b=='>'){ d[i++]=b;b=getchar();printf("2,%s\n",d);for(j=0;j<=i;j++)d[j]='\0';i=0;}else{ printf("2,%s\n",d);for(j=0;j<=i;j++)d[j]='\0';i=0;}}else if(b=='>')/*识别'>'和'>='*/{ d[i++]=b;b=getchar();if(b=='='){ d[i++]=b;b=getchar();printf("2,%s\n",d);for(j=0;j<=i;j++)d[j]='\0';i=0;}else{ printf("2,%s\n",d);for(j=0;j<=i;j++)d[j]='\0';i=0;}}else if(b==':')/*识别':='*/{ d[i++]=b;b=getchar();if(b=='='){ d[i++]=b;b=getchar();printf("2,%s\n",d);}else printf("error line %d\n",linenum);for(j=0;j<=i;j++)d[j]='\0';i=0;}else if(b=='*'||b=='+'||b=='-'||b=='/'||b=='=')/*识别运算符*/{ printf("2,%c\n",b);b=getchar();}else if(b=='('||b==')'||b==','||b==';'||b=='.')/*识别分隔符*/{ printf("5,%c\n",b);b=getchar();}else{ printf("error line %d\n",linenum);b=getchar();}}}实验心得:此次实验让我了解了如何设计、编制并调试词法分析程序,并加深了我对词法分析器原理的理解;熟悉了直接构造词法分析器的方法和相关原理,并学会使用c语言直接编写词法分析器;同时更熟练的掌握用c语言编写程序,实现一定的实际功能。
编译原理实验—词法分析器一、实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
二、实验内容及要求对某特定语言A ,构造其词法规则。
该语言的单词符号包括:保留字(见左下表)、标识符(字母大小写不敏感)、整型常数、界符及运算符(见右下表) 。
功能要求如下所示:·按单词符号出现的顺序,返回二元组序列,并输出。
·出现的标识符存放在标识符表,整型常数存放在常数表,并输出这两个表格。
·如果出现词法错误,报出:错误类型,位置(行,列)。
·处理段注释(/* */),行注释(//)。
·有段注释时仍可以正确指出词法错误位置(行,列)。
三、实验过程1、词法形式化描述使用正则文法进行描述,则可以得到如下的正规式:其中ID表示标识符,NUM表示整型常量,RES表示保留字,DEL表示界符,OPR表示运算符。
A→(ID | NUM | RES | DEL | OPR) *ID→letter(letter | didit)*NUM→digit digit*letter→a | … | z | A | … | Zdigit→ 0 | … | 9RES→ program | begin | end | var | int | and | or | not | if | then | else | while | doDEL→( | ) | . | ; | ,OPR→+ | * | := | > | < | = | >= | <= | <>如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一个空格作间隔。
空格由空白、制表符和换行符组成。
2、单词种别定义;A语言中的单词符号及其对应的种别编码如下表所示:单词符号种别编码单词符号种别编码3、状态转换图;语言A的词法分析的状态转换图如下所示:空格符,制表符或回车符字母或数字4、java旗舰版5、关键算法的流程图及文字解释;程序中用到的函数列表:A类定义各种类函数以及包含主函数public static void main()变量ch储存当前最新读进的字符的地址strToken存放当前字符串main() //主函数Analysis()//分析函数,每次读入一行文件,进行识别处理;char GetChar(); //取得当前位置的字符的内容放入ch,并提前指向下一个字符;char GetNextChar();//取得当前位置的下一位置的字符,String ConCat(); //将ch指向的字符连接到strToken后面isLetter(); //判断ch指向的字符是否字母isDigit(); //判断ch指向的字符是否数字add(p,str); //向p表中插入当前strToken的字符串Boolean findKeyWord(str); //检测当前strToken中的字符串是否保留字,若是,则执行getKeyWordKey(str),返回保留字的id,否则,判别其是否是已存在的标示符,若是,返回标示符的id以及该标示符在表中的位置;findPunctuation()//判断是否是一个保留的符号;getindex() //返回已经识别的标示符或者是数字的位置下标;Boolean exist(); //检测当前strToken中的字符串是否在标识符表中已存在,若是,则返回true,否则返回falsevoid callError(); //出错处理过程,将错误的位置报告出来(1)main()函数的流程图如下:)具体分析流程图:开始类初始化,变量的初始化,准备执行main()函数调用Analyse()函数分析输出结果表结束Analyse(str)函数读取第一个字符赋给变量Ch继续判读IndexoutofBound6、测试报告(测试用例,测试结果);首先输入一个不含错误的程序(两种注释)进行检测:运行后在控制台上得到的结果如下所示:得到的二元组序列如下:经检验,输出的是正确的二元组序列。
一.课程设计题目:词法分析器的实现二.课程设计成员三.课程设计内容和要求设计一个程序,调试、编译,实现词法分析的功能,识别各单词或字符所属类别,并显示在屏幕上。
词法分析器:逐个读入源程序字符并按照构词规则切分成一系列单词。
单词是语言中具有独立意义的最小单位,包括保留字、标识符、运算符、标点符号和常量等。
词法分析是编译过程中的一个阶段,在语法分析前进行。
也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
要求:通过词法分析器能够实现以下五种类型如单词等的识别。
(1)关键字"begin","end","if","then","else","while","write","read"等,"do", "call","const","char","until","procedure","repeat"等(2)运算符:"+","-","*","/","="等(3)界符:"{","}","[","]",";",",",".","(",")",":"等(4)标识符(5)常量四.操作要求首先建立一个或多个文档,此处新建了两个文档,例:07196133.txt文本文档和zhaoxiaodong.txt文本文档,以供选择,各文本文档中都输入有不同的内容,运行程序,出现提示,输入文本文档的名称,即可对文本文档中的内容进行分析,并把分析结果输出显示在屏幕上。
编译原理词法分析器实验报告1. 引言编译原理是计算机科学中的重要概念,它涉及将高级语言程序转换为计算机可执行的低级指令。
词法分析是编译过程中的第一个阶段,它负责将源代码分解为词法单元,为后续的语法分析做准备。
本实验旨在设计和实现一个基本的词法分析器,以了解词法分析的原理和实际应用。
2. 实验目标本实验的主要目标是实现一个基本的词法分析器,能够识别并提取源代码中的各种词法单元。
具体而言,我们将设计一个针对某种编程语言的词法分析器,能够识别关键字、标识符、算术运算符、括号、常量等。
3. 实验环境为了完成本实验,我们需要使用以下工具和环境:•一种编程语言,例如Python、Java或C++•一个文本编辑器,例如Visual Studio Code或Sublime Text•一个命令行终端4. 实验步骤4.1 定义词法规则首先,我们需要定义词法分析器的词法规则。
这些规则描述了编程语言中各种词法单元的模式。
例如,关键字可以被定义为由特定字符组成的字符串,标识符可以被定义为以字母开头并由字母和数字组成的字符串。
4.2 实现词法分析器接下来,我们将根据定义的词法规则,使用编程语言实现一个词法分析器。
在实现过程中,我们可以使用正则表达式来匹配和提取各种词法单元。
4.3 编写测试用例完成词法分析器的实现后,我们需要编写一些测试用例来验证其正确性。
测试用例应该包含各种可能的输入情况,以确保词法分析器能够正确地识别和提取词法单元。
4.4 运行测试用例最后,我们将使用编写的测试用例来运行词法分析器,并检查输出是否符合预期。
如果测试通过,说明词法分析器能够正常工作;否则,我们需要检查代码并进行调试。
5. 实验结果经过实验,我们成功地设计并实现了一个基本的词法分析器。
该词法分析器能够按照预定义的词法规则,正确地识别和提取源代码中的各种词法单元。
在运行测试用例时,词法分析器能够产生符合预期的输出,表明其具有良好的准确性和可靠性。
编译原理实验词法分析实验报告一、实验目的词法分析是编译过程中的第一个阶段,其主要任务是从输入的源程序中识别出具有独立意义的单词符号,并将其转换为内部编码形式。
本次实验的目的是通过设计和实现一个简单的词法分析程序,深入理解词法分析的基本原理和方法,提高对编程语言语法结构的认识和编程能力。
二、实验原理词法分析的基本原理是根据编程语言的词法规则,使用有限自动机或正则表达式等技术来识别单词符号。
在本次实验中,我们采用了状态转换图的方法来设计词法分析器。
状态转换图是一种用于描述有限自动机的图形表示方法,它由状态节点和有向边组成。
每个状态节点表示自动机的一个状态,有向边表示状态之间的转换条件。
当输入字符与当前状态的转换条件匹配时,自动机将从当前状态转换到下一个状态。
当到达一个终态时,表示识别出了一个单词符号。
三、实验环境本次实验使用了 Python 编程语言,并在 PyCharm 集成开发环境中进行开发和调试。
四、实验内容1、定义单词符号的种类和编码关键字:如`if`、`else`、`while` 等标识符:由字母、数字和下划线组成,且以字母或下划线开头常数:包括整数和浮点数运算符:如`+`、``、``、`/`等分隔符:如`(){},;`等2、设计状态转换图根据单词符号的定义,设计了相应的状态转换图,用于识别不同类型的单词符号。
例如,对于标识符的识别,从起始状态开始,当输入字符为字母或下划线时,进入标识符状态,继续输入字母、数字或下划线,直到遇到非标识符字符为止,此时到达终态,识别出一个标识符。
3、实现词法分析程序使用 Python 语言实现了基于状态转换图的词法分析程序。
程序首先读取输入的源程序文本,然后逐个字符进行处理,根据当前状态和输入字符进行状态转换,当到达终态时,输出识别出的单词符号及其编码。
4、进行测试编写了一些测试用例,包括包含各种单词符号的源程序代码。
运行词法分析程序对测试用例进行分析,检查输出结果是否正确。
一.课程设计题目:词法分析器的实现二.课程设计成员三.课程设计内容和要求设计一个程序,调试、编译,实现词法分析的功能,识别各单词或字符所属类别,并显示在屏幕上。
词法分析器:逐个读入源程序字符并按照构词规则切分成一系列单词。
单词是语言中具有独立意义的最小单位,包括保留字、标识符、运算符、标点符号和常量等。
词法分析是编译过程中的一个阶段,在语法分析前进行。
也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
要求:通过词法分析器能够实现以下五种类型如单词等的识别。
(1)关键字"begin","end","if","then","else","while","write","r ead"等,"do", "call","const","char","until","procedure","repeat"等(2)运算符:"+","-","*","/","="等(3)界符:"{","}","[","]",";",",",".","(",")",":"等(4)标识符(5)常量四.操作要求首先建立一个或多个文档,此处新建了两个文档,例:07196133.txt文本文档和zhaoxiaodong.txt文本文档,以供选择,各文本文档中都输入有不同的内容,运行程序,出现提示,输入文本文档的名称,即可对文本文档中的内容进行分析,并把分析结果输出显示在屏幕上。
编译原理实验报告姓名:关海超学号:200807010209专业:计算机科学与技术班级:08—02班一、实验目的通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;加深对课堂教学的理解;提高词法分析方法的实践能力。
二、词法分析器的实现1、词法分析过程的考虑词法分析器的任务是将程序源代码看做一个字符串,只需从中分离出一个个具有独立意义的单词(包括标识符,符号和常量)即可,而无需考虑其在上下文环境中的正确性。
基于此认识,词法分析的过程可如下描述:本程序中用户源程序存储在文件“E:\prog.txt”文件中,程序首先调用readFromFile()函数将源程序代码从文件中读出,放到数组中暂存,然后主函数调用scaner()函数对其进行逐个扫描,分离出的每个独立单词进行分类判断,构成二元组形式,再将其输出的文件“E:\result.txt”中进行保存。
2、各种单词符号对应的种别码0 标识符21 ret 42 ++ 63 ||1 整型常量22 sho 43 -- 64 ?:2 auto 23 sig 44 - 65 =3 brea 24 siz 45 * 66 +=4 case 25 sta 46 & 67 -=5 char 26 str 47 / 68 *=6 cons 27 swi 48 % 69 /=7 cont 28 typ 49 + 70 %=8 defa 29 uni 50 - 71 >>=9 do 30 uns 51 << 72 <<=10 dou 31 voi 52 >> 73 &=11 els 32 vol 53 < 74 ^=12 enu 33 whi 54 <= 75 |=13 ext 34 ( 55 > 76 ,14 flo 35 ) 56 >= 77 '15 for 36 [ 57 == 78 ;16 got 37 ] 58 != 79 :17 if 38 -> 59 & 80 \{18 int 39 . 60 ^ 81 }19 lon 40 ! 61 | 82 //20 reg 41 ~ 62 &&3、关键数据结构的描述计数器count:将二元组写入文件时通过count判断是否是首次写入,若是则清空文件,否则追加写入;字符串常量endStr:其值为“end”,在分析判断每一单词的种类时,该字符串作为rwtab表的结束标志;数组prog[200]:暂存从文件中读取的源程序代码,该词法分析器约定源代码长度不超过199;数组token[20]:暂存每次分离出的单个具有独立意义的单词,该词法分析器约定每个单词的长度不超过19;结构体result:存放一个单词的种别码和单词本身的值,在写入文件时以结构体中的元素为单位依次写入;4、程序结构的描述本程序采用结构化设计方法,共有两个文件,六个模块,分别介绍如下:rwtab.h文件包含一个模块,即各种单词符号对应的种别码,作为外部文件被main.cpp文件引用。
编译原理实验报告班级:软件0501班学号:**********姓名:***词法分析器与语法分析器I. 问题描述设计、编制并调试一个词法分析子程序,完成识别语言单词的任务;设计、编制、调试一个语法分析程序,并用它对词法分析程序所提供的单词序列进行语法检查和结构分析。
ii. 设计简要描述界面需求:为了更加形象的模拟过程,此实验使用图形界面。
要求从图形界面上输入输入串,点击词法分析,可以将词法分析后识别的单词符号显示,点击语法分析,可以将语法分析的堆栈过程显示,并且显示结果(是否是符合文法的句子),清空则可以将所有置空。
功能分析:1、由用户输入输入串;2、用户点击“词法分析”,可以将词法分析后识别的单词符号显示。
3、用户点击语法分析,可以将语法分析的堆栈过程显示,并且显示结果(是否是符合文法的句子)4、用户点击清空,则将界面所有组件置为空思路描述:一、设计构想:本实验决定编写一个简易C语言的词法分析器和语法分析器。
使其能够识别while,if等关键字,可以判断赋值语句、条件语句、循环语句。
二、文法分析1、需要识别的关键字及其识别码有:关键字识别码关键字识别码关键字识别码main 0 - 11 ;22int 1 * 12 > 23char 2 / 13 < 24if 3 ( 14 >= 25else 4 ) 15 <= 26for 5 [ 16 == 27while 6 ] 17 != 28ID 7 { 18 ERROR -1NUM 8 } 19= 9 , 20+ 10 : 212、文法〈程序〉→ mai n()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉;〈语句串〉|〈语句〉;〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|=|!>转化为符号表示:S→ main() K|空K→ { C }C→Y;C |空Y→F | T | XF→ ID = BT→ if J KX→ while J KJ→( B G B )B→ B Z B |( B )| ID | NUMZ→ + | - | * | /G→< | <= | > | >= | == | !>表示含义:S:程序 K:语句块 C:语句串 Y:语句 F :赋值语句T:条件语句 X:循环语句 J:条件 B:表达式 I:项 Z :运算符G:关系符3、LL(1)分析表(1),求出first集及follow集:FIRST(S)={mian}FIRST(K)={{}FIRST(C)= FIRST(Y)= {ID,if,while,空};FIRST(Y)= FIRST(F)+ FIRST(T)+ FIRST(X)={ID,if,while};FIRST(F)={ID};FIRST(T)={if};FIRST(X)={while};FIRST(J)= FIRST(B)={};FIRST(B)={(,ID,NUM };FIRST(Z)={+,-,*,/}FIRST(G)={<,<= ,>,>=,==,!= };FOLLO W(S)={#};FOLLO W(K)={;};FOLLO W(C)={}};FOLLO W(Y)={;}FOLLO W(F)={;};FOLLO W(T)={;};FOLLO W(X)={;};FOLLO W(J)={{,;};FOLLO W(B)={+,-,*,/,),<,<= ,>,>=,==,!=,;};FOLLO W(B’)={+,-,*,/,),<,<= ,>,>=,==,!=,;};FOLLO W(Z)={(,ID,NUM };FOLLO W(G)={(,ID,NUM };(2)消除左递归,拆分文法关系并编号0、S→ 空1、S→ main() K2、K→ { C }3、C→Y;C4、C→空5、Y→ F6、Y→ T7、Y→ X8、F→ ID = B9、T→ if J K10、X→ while J K11、J→( B G B )12、 B→( B )B'13、B→ ID B'14、B→ NUM B'15、B'→ BZB B'16、B'→空17、Z→ +18、Z→ -19、Z→ *20、Z→ /21、 G→ <22、 G→ <=23、 G→ >24、 G→ >=25、 G→ ==26、 G→ !=(3)构造LL (1)分析表(注:在表中用上一步的编号表示所需要的产生式)iii. 详细设计描述 项目构架:各函数功能介绍:main 空 () { } ; = if while ID num + - * / < <= > >= == != # S 10 K 2 C 4 4 3 3 3 Y 6 7 5 F 8 T 9 X10 J11 B1213 14B '16 15 16 16 15 15 16 16 16 16 16 16 16 16 16 16 Z 17 18 19 20G21 22 232425261、word.wordList包(存储了关键字):word:此类是定义了存储关键字的结构:包括String型的关键字,和int型的识别符。
编译原理词法分析器实验报告篇一:编译原理词法分析器实验报告曲阜师范大学实验报告计算机系2008年级软件工程一班组日期2010年10月17日星期日姓名陈金金同组者姓名课程编译原理成绩实验名称:教师签章词法分析器一、实验目的:1·掌握词法分析的原理。
2·熟悉保留字表等相关的数据结构与单词的分类方法。
3·掌握词法分析器的设计与调试。
二、实验内容:根据编译中的分词原理,编写一个词法分析程序:1. 输入:任意一个C 语言程序的源代码。
2. 处理:对输入进行分析,分离出保留字、标识符、常量、算符和界符。
3. 输出:对应的二元式(种别编码自定,可暂编为一类对应一个编码)。
三、实验要求:1. 任选C/C++/Java 中的一种高级程序语言编程完成词法分析器。
2. 词法分析器应以教材所述分词原理为依据,使用恰当的数据结构和方法,结构清晰、高效。
四、实验环境:WindowsXp操作系统,J2SE,Eclipse 集成开发环境五、实验分析:将源代码作为长字符串进行读入,之后通过switch语句,及状态转换图进行词素识别,并对识别的词素进行分类整理以二元式的形式输出。
六、实验过程:1、建立词法分析器界面,很简单:输入框,输出框,执行分析按钮,清空按钮,退出程序按钮。
主要的地方是,考虑mvc开发模式,为model及controller 提供接口。
实现界面如下所示:2、核心代码的编写,考虑到需要进行词素的匹配,创建符号表类SymTable。
提供两个变量,分别存放如下内容:并提供方法insert,lookUp,分别负责标志符的插入和查找。
3.、根据语法规则书写状态转换图,并用switch语句实现:需要注意的地方是,begin和forward 两个指针的移动:通过swith语句识别词素,并在符号表中进行匹配,匹配成功,则返回相应的记号,否则返回id。
七、实验结论:实验过程还算顺利,遇到的一系列问题都得到比较好的解决,当然分析器还有很大的改进空间,这里只是简单的实现了词素的识别及简单的判断。
编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的:1,词法分析器能够识别简单语言的单词符号2,识别出并输出简单语言的基本字。
标示符。
无符号整数.运算符.和界符。
三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号.2、程序流程图(1)主程序(2)扫描子程序3、各种单词符号对应的种别码五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符.字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。
2 实验词法分析器源程序:#include 〈stdio.h〉#include <math.h>#include <string。
h>int i,j,k;char c,s,a[20],token[20]={’0’};int letter(char s){if((s〉=97)&&(s〈=122)) return(1);else return(0);}int digit(char s){if((s〉=48)&&(s<=57)) return(1);else return(0);}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(char token[20]){if(strcmp(token,"while")==0) return(1);else if(strcmp(token,"if")==0) return(2);else if(strcmp(token,"else”)==0) return(3);else if(strcmp(token,"switch”)==0) return(4);else if(strcmp(token,"case")==0) return(5);else return(0);}void main(){printf(”please input string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);switch(s){case 'a':case ’b':case ’c':case ’d':case ’e’:case ’f’:case 'g’:case ’h':case 'i':case ’j':case 'k’:case ’l':case 'm’:case 'n':case ’o':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)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。