编译原理课设报告词法分析
编译原理词法分析实验报告
编译原理词法分析实验报告实验名称:词法分析器的设计与实现一、实验目的: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对象。
五、实验总结:通过本次实验,我熟悉了编译原理中词法分析的基本概念和原理,并掌握了正则表达式的使用方法。
我成功完成了一个简单的词法分析器的设计与实现,实现了源代码中每个词法单元的识别与输出。
这次实验对我深化了对编译原理中词法分析的理解,并提高了我的编程能力。
编译原理实验报告(词法分析器语法分析器)
函数 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
编译原理实验报告-词法分析
词法分析实验报告一、实验目的1.编制一个词法分析程序。
2.加深对词法分析原理的理解。
二、实验要求1.待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符: = + - * / < <= <> > >= = ; ( ) .(3)其他单词是标识符(IDENT)和整型常数(NUMBER),通过以下正规式定义:IDENT = letter (letter | digit)*NUMBER = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔IDENT、NUMBER、运算符、界符和关键字,词法分析阶段通常被忽略。
2.各种单词符号对应的类别值:表各种单词符号对应的类别码3.词法分析程序的功能:输入:所给文法的源程序字符串,以“.”结束。
输出:二元组(sym,token或number)构成的序列。
其中:sym为单词种别码;token为存放的单词自身字符串;number为整型常数。
例如:对源程序begin x:=9;if x<10 then x:=(x+10)*2 end.的源文件,经过词法分析后输出如下序列:(17,begin)(1,x)(16,:=)(2,9)(15,;)……4.词法分析程序的设计词法分析采用状态转换图方法:三、实验设计方法从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
主程序示意图:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:图3-11.主要技术难点a)设计各种单词符号对应的符号表b)实现输入字符数字和单词符号及其对应单词种别码的正确输出。
编译原理词法分析,语法分析实验报告
char left[50];
/* 左部 */
char right[50][50];
/* 右部 */
char first[50][50],follow[50][50];
/* 各产生式右部的 FIRST 和左部的 FOLLOW 集合 */
char first1[50][50];
/* 所有单个符号的 FIRST 集合 */
int i,j,k,result=1,mark=0;
char temp[20];
temp[0]=c;
temp[1]='\0';
merge(empt,temp,1);
if(in(c,empty)==1)
return(1);
for(i=0;;i++)
{
if(i==count)
return(0);
if(left[i]==c)
}
/*******************************************
将单个符号或符号串并入另一符号串 ********************************************/
void merge(char *d,char *s,int type)
{
/*d 是目标符号串, s 是源串, type=1,源串中的‘ ^ ’一并并入目串;
int count=0;
/* 分解的产生式的个数 */
int number;
/* 所有终结符和非终结符的总数 */
char start;
/* 开始符号 */
char termin[50];
/* 终结符号 */
char non_ter[50];
编译原理词法分析器报告
编译原理课程设计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”,表示是否能够识别此符号串;有穷自动机和状态转换图类似,它具有有限个数的结点,每个结点表示一个状态,并且这些状态中有一个初始状态和若干个终止状态。
编译原理课程设计报告
编译原理课程设计报告软件学院05级时间:2007年7月25日一、词法分析1、实验目的编程实现词法分析程序,加深理解对词法分析原理。
2、实验要求a、识别出特殊符号(用顿号隔开),女口=、+、-、*、/、<、>、<=、>=、==、!=、;、:、,、{、}、卜卜(、)等b 识别出关键字,如if;the n;while;do;e nd;for 等c、识别其它标记ID和NUM,并通过以下正规式定义其他标记:ID -> letter (letter | digit)letter -> a | b ... | z | A |B ... | ZNUM -> digit digit*digit -> 0 | 1 ... | 93、算法思路:本程序每次判断均连续输入几个的词,不同的词之间用“空格”隔开,因为所输入的字符串中含有“空格”,故在输入的时候启用文本监视器,利用字符串解析器扫描所输入的字符串,以逗号,空格,分号分开,以java.util 包中的模式匹配生成文法和保留字对每个token进行分析,测试其匹配的模式,把它们区分开来4、程序流程图主程序流程图扫描程序流程图5.运行环境JDK6.0实验二:LL1语法判断、实验目要求:自定义一个文法集,输入文法产生式,计算文法的利用FIRST,FOLLOV和SELECT集合,SELECT集合构造预测分析表,接着用预测分析程序,栈和预测分析表对输入串进行分析,给出分析过程。
二、设计思想:设计算法实现:(1 )求FIRST集(用关系图法)(a)每个文法符号对应图中一个结点。
(b)如果文法中有产生式A、a X3 ,且a =>* £,则从对应A的结点到对应X的结点连一条箭弧。
(c)凡是从FIRST(A)的结点有路径可到达的终结符结点所标记的终结符都为FIRST(A的成员。
(d)判定£是否为某非终结符FIRST集的成员,若是则将加入该非终结符的FIRST集中。
编译原理词法分析报告
实验一:词法分析一、实验目的:1、通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
2、编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本关键字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。
词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。
本实验中,采用的是一类符号一种别码的方式。
2、单词的BNF表示<标识符>-> <字母><字母数字串><字母数字串>-><字母><字母数字串>|<数字><字母数字串>|<下划线><字母数字串>|ε<无符号整数>-> <数字><数字串><数字串>-> <数字><数字串> |ε<加法运算符>-> +<减法运算符>->-<大于关系运算符>->><大于等于关系运算符>-> >=3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。
如当前待分析字符串为“a>+”,当前字符为’>’,此时,分析器到底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。
于是分析器读入下一个字符’+’,这时可知应将’>’解释为大于运算符。
但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。
在分析标识符,无符号整数等时也有类似情况。
编译原理课程设计报告——词法分析器
精选课程设计任务书引言 (4)第一章概述 (5)1.1设计内容 (5)1.2设计要求 (5)第二章设计的基本原理 (6)2.1 (6)2.2 (6)第三章程序设计 (7)3.1 总体方案设计 (7)3.2 各模块设计 (8)第四章程序测试 (9)4.1一般测试4.2出错处理测试第五章结论 (10)参考文献 (10)附录程序清单 (11)引言《编译原理》是国内外各高等院校计算机科学技术类专业,特别是计算机软件专业的一门重要专业课程。
该课程系统地向学生介绍编译程序的结构、工作流程及编译程序各组成部分的设计原理和实现技术。
由于该课程理论性和实践性都比较强,内容较为抽象复杂,涉及到大量的软件设计算法,因此,一直是一门比较难学的课程。
为了使学生更好地理解和掌握编译技术的基本概念、基本原理和实现方法,实践环节非常重要,只有通过上机进行程序设计,才能使学生对比较抽象的教学内容产生具体的感性认识,增强学生综合分析问题、解决问题的能力,并对提高学生软件设计水平大有益处。
编译原理涉及词法分析,语法分析,语义分析及优化设计等各方面。
词法分析阶段是编译过程的第一个阶段,是编译的基础。
这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。
词法分析程序实现这个任务。
词法分析程序可以使用 Lex 等工具自动生成。
从左到右逐个字符对构成源程序的字符串进行扫描,依据词法规则,识别出一个一个的标记(token ),把源程序变为等价的标记串序列。
执行词法分析的程序称为词法分析器,也称为扫描器。
词法分析是所有分析优化的基础,涉及的知识较少,如状态转换图等,易于实现。
本次课程设计,我的选题是词法分析, C++ 代码实现。
第一章概述1.1 设计内容对 C 语言的一个子集设计并实现一个简单的词法分析器,掌握利用状态转换图设计词法分析器的基本方法。
1.2设计要求利用该词法分析器完成对源程序字符串的词法分析。
编译原理的词法分析与语法分析
编译原理的词法分析与语法分析编译原理是计算机科学中的一门重要课程,它研究如何将源代码转换为可执行的机器代码。
在编译过程中,词法分析和语法分析是其中两个基本的阶段。
本文将分别介绍词法分析和语法分析的基本概念、原理以及实现方法。
1. 词法分析词法分析是编译过程中的第一个阶段,主要任务是将输入的源代码分解成一个个的词法单元。
词法单元是指具有独立意义的最小语法单位,比如变量名、关键字、操作符等。
词法分析器通常使用有限自动机(finite automaton)来实现。
在词法分析的过程中,需要定义词法规则,即描述每个词法单元的模式。
常见的词法规则有正则表达式和有限自动机。
词法分析器会根据这些规则匹配输入的字符序列,并生成相应的词法单元。
2. 语法分析语法分析是编译过程中的第二个阶段,它的任务是将词法分析器生成的词法单元序列转换为语法树(syntax tree)或抽象语法树(abstract syntax tree)。
语法树是源代码的一种抽象表示方式,它反映了源代码中语法结构和运算优先级的关系。
语法分析器通常使用上下文无关文法(context-free grammar)来描述源代码的语法结构。
常见的语法分析算法有递归下降分析法、LR分析法和LL分析法等。
递归下降分析法是一种自顶向下的分析方法,它从源代码的起始符号开始,递归地展开产生式,直到匹配到输入的词法单元。
递归下降分析法的实现比较直观,但对于左递归的文法处理不方便。
LR分析法是一种自底向上的分析方法,它使用一个自动机来分析输入的词法单元,并根据文法规则进行规约操作,最终生成语法树。
常见的LR分析法有LR(0)、SLR、LR(1)和LALR等。
LL分析法是一种自顶向下的分析方法,它从源代码的起始符号开始,预测下一个要匹配的词法单元,并进行相应的推导规则。
LL分析法常用于编程语言中,如Java和Python。
3. 词法分析和语法分析的关系词法分析是语法分析的一个子阶段,它为语法分析器提供了一个符号序列,并根据语法规则进行分析和匹配。
编译原理课程设计报告-词法语法分析器
编译原理课程设计Course Design of Compiling(课程代码3273526)半期题目:词法和语法分析器实验学期:大三第二学期学生班级:2014级软件四班学生学号:18学生姓名:何华均任课教师:丁光耀信息科学与技术学院课程设计1-C语言词法分析器1.题目C语言词法分析2.内容选一个能正常运行的c语言程序,以该程序出现的字符作为单词符号集,不用处理c语言的所有单词符号。
将解析到的单词符号对应的二元组输出到文件中保存可以将扫描缓冲区与输入缓冲区合成一个缓冲区,一次性输入源程序后就可以进行预处理了3.设计目的掌握词法分析算法,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解4.设计环境(电脑语言环境)语言环境:C语言CPU:i7HQ6700内存:8G5.概要设计(单词符号表,状态转换图)词法分析器的结构词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
词法分析程序可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词.为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序:1) ch 存放最新读进的源程序字符2) strToken 存放构成单词符号的字符串3) Buffer 字符缓冲区4)struct keyType 存放保留字的符号和种别(1)保留字break、case、char、const、int、do、while…(2)运算符和界符= 、+、-、* 、/、%、,、;、(、)、、#各种单词符号对应的种别码状态转换图6.详细设计(数据结构,子程序)算法思想:首先设置3个变量:①strToken用来存放构成单词符号的字符串;②ch用来字符;③struct keyType用来存放单词符号的种别码。
扫描子程序主要部分流程如下图所示。
子程序结构:子程序名功能GETCHAR()读一个字符到ch 中GETBC()读一个非空白字符到ch 中CONCAT()把CHAR 中字符连接到strToken 之后LETTER()判断CHAR 中字符是否为字母7.程序清单eyname) == 0)return Key[i].value;return 0;}void Retract()alue;}else if (ch >= '0'&&ch <= '9') {ConCat();GetChar();while (Digit()) {ConCat();GetChar();}Retract();strcpy, strToken);= 1;}else {ConCat();strcpy, strToken);= Reserve();}return tempkey;}/*主函数*/int main() {行结果E:/作业/编译原理/运行结果九、 实验体会通过本次次法分析设计实验,我加深了对词法分析过程的理解。
《编译原理》课程实验报告(词法分析)完整版
《编译原理》课程实验报告题目词法分析专业计算机指导教师签名华东理工大学信息学院计算机系2013年4月10日一.实验序号:《编译原理》第一次实验二.实验题目:词法分析三.实验日期:2013.3.27-2013.4.10四.实验环境(操作系统,开发语言)操作系统:Windows开发语言:C五.实验要求●修改词法:1)将标识符的词法改为“以大写字母或小写字母开头,后面可以跟大写字母或小写字母或数字或下划线”。
把while ((isalpha(buffer))||(isdigit(buffer)))改成while ((isalpha(buffer))||(isdigit(buffer))||buffer==’_’)2)将<条件>中的表示相等关系的单词“=”改为“= =”char *relation[6]={"<","<=","=",">",">=","<>"};把其中的=改成==即可3)将原来无小数的数改为可以有小数的数把while (isdigit(buffer))改成while (isdigit(buffer)||buffer==’.’)●用C语言开发词法分析程序。
读入用PL/0语言编写的测试用例源程序,将识别出的一个个单词组成单词流依序同时输出到屏幕和文件中。
六.实验步骤1)根据修改词法后的PL/0语言编写测试用例源程序。
2)用C语言编写词法分析程序。
读入PL/0语言的测试用例源程序,进行词法分析,将识别出的一个个单词组成单词流依序同时输出到屏幕和文件中。
3)设立断点,单步运行词法分析程序,依次单个输出单词。
分析和理解词法分析程序,解释词法分析程序中的数据和变量变化的原因和输出结果。
七.实验结果(测试用例源程序,运行结果部分截图,词法分析函数主要部分源程序PL0程序:const a=6,b=81;var x,y;procEdure p;procedure q;x:=2;beginx:=1;write(x);end;begincall p;end.C程序:#include <stdio.h>#include <ctype.h>#include <malloc.h>#include <stdlib.h>#include <string.h>#define NULL 0FILE *fp;char cbuffer;char*key[19]={"auto","break","case","char","const","continue","default","do"," double","else","enum","extern","float","for","goto","if","int","long","register"};char *border[6]={",",";","{","}","(",")"};char *arithmetic[4]={"+","-","*","/"};char *relation[6]={"<","<=","=",">",">=","<>"};char *consts[11]={"0","1","2","3","4","5","6","7","8","9","."};char *label[20];int labelnum=0;int search(char searchchar[],int wordtype){ int i=0;switch (wordtype) {case 1:for (i=0;i<=18;i++){ if (strcmp(key[i],searchchar)==0){return(1);}}return(0);break;case 2:{for (i=0;i<=5;i++){ if (strcmp(border[i],searchchar)==0)return(i+1);} return(0);}break;case 3:{for (i=0;i<=3;i++){ if (strcmp(arithmetic[i],searchchar)==0){ return(1);}}return(0);}break;case 4:{for (i=0;i<=5;i++){ if (strcmp(relation[i],searchchar)==0){ return(1);}}return(0);}break;case 5:{for (i=0;i<=10;i++){ if (strcmp(consts[i],searchchar)==0){return;}}return(0);}break;}}char alphaprocess(char buffer){ int atype;int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer))){ alphatp[++i]=buffer;buffer=fgetc(fp);}alphatp[i+1]='\0';atype=search(alphatp,1);if(atype==1){printf("%s \t 保留字\n",alphatp);}//结束if(atype==0){printf("%s \t 标示符\n",alphatp);}return(buffer);}char digitprocess(char buffer){ int i=-1;char digittp[20];int dtype;while (isdigit(buffer)){ digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';dtype=search(digittp,5);if(dtype==1)printf("%s \t 数字\t %s\n",digittp,digittp);return(buffer);}char otherprocess(char buffer){ int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';otype=search(othertp,3);if (otype==1){ printf("%s \t 运算符\n",othertp);buffer=fgetc(fp);goto out;}otype=search(othertp,4);if (otype==1){ buffer=fgetc(fp);othertp[1]=buffer;othertp[2]='\0';otypetp=search(othertp,4);if (otypetp==1){ printf("%s \t 运算符\n",othertp);goto out;}elseothertp[1]='\0';printf("%s \t 运算符\n",othertp);goto out;}if (buffer==':'){ buffer=fgetc(fp);if (buffer=='=')printf(":= \t 运算符\n");buffer=fgetc(fp);goto out;}else{ if (otype=search(othertp,2)){ printf("%s \t 界符\n",othertp);buffer=fgetc(fp);goto out;}}if ((buffer!='\n')&&(buffer!=' '))printf("%c error,not a word\n",buffer);buffer=fgetc(fp);out: return(buffer);}void main(){if ((fp=fopen("example.txt","r"))==NULL)printf("error");else{cbuffer = fgetc(fp);while (cbuffer!=EOF){if (isalpha(cbuffer))cbuffer=alphaprocess(cbuffer);else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer);elsecbuffer=otherprocess(cbuffer);}printf("over\n");getchar();}}八.实验体会(词法分析程序修改的地方,解决问题的方法、心得体会等)通过本次试验,了解了词法分析的主要步骤,就是把标识符,保留字区分,并且能识别出空格,并把数据能从文件中读出来,主要识别标识符和保留字,主要通过比较参照一个事先建好的数组,里面包含了所有的保留字,不在其中的便是标识符。
《编译原理》课程实验报告(词法分析)
信息科学与工程学院__《编译原理》_实验报告系别计算机科学与工程专业计算机科学与应用班级_____计122_______学号_____10123544_____姓名_____ 陈柏君_________指导教师金登男2014学年第二学期1.实验题目:词法分析2.实验日期:2015.4.9-2015.4.163.实验环境(操作系统,开发语言)操作系统:Windows开发语言:C4.实验要求4.1.用C语言开发词法分析程序PL0Compiler。
4.2.修改PL/0词法,将其定义为一种新的语言,例如称其为PL/1语言,并完成PL/1语言的词法分析程序。
5.实验步骤5.1.用PL/0语言编写PL/0测试用例源程序,将其命名为Test0.pl。
5.2.用C语言开发PL/0词法分析程序PL0Compiler。
PL0Compiler读入Test0.pl,识别出一个个单词,并将这些单词流依序同时输出到屏幕和文件中。
被输出的每个单词应包括(1)单词序号(2)单词字符串(3)单词类型(4)单词值(如果是标识符,其值是字符串;如果是数,其值是数值;如果是符号,其值是ASCII代码…)在程序开发过程中,应设立断点,单步运行词法分析程序,依次输出一个个单词。
分析和理解词法分析程序,解释词法分析程序中的数据和变量变化的原因和输出结果。
5.3.研究其他程序设计语言,找出与PL/0词法不同的构词法则(例如C语言的标识符的组成规则与PL/0标识符的组成规则有所不同)。
据此修改PL/0的某些词法(例如,将PL/0标识符组成规则修改为C语言的标识符的组成规则),将其定义为一种新的语言,例如称其为PL/1语言。
5.4.用PL/1语言编写PL/1测试用例源程序,将其命名为Test1.pl。
5.5.开发PL/1词法分析程序PL1Compiler。
(可通过修改原PL0Compiler,实现PL/1语言的词法分析功能)。
5.6.PL1Compiler读入Test1.pl,识别出一个个单词,并将这些单词流依序同时输出到屏幕和文件中。
编译原理词法分析器实验报告
编译原理词法分析器实验报告1. 引言编译原理是计算机科学中的重要概念,它涉及将高级语言程序转换为计算机可执行的低级指令。
词法分析是编译过程中的第一个阶段,它负责将源代码分解为词法单元,为后续的语法分析做准备。
本实验旨在设计和实现一个基本的词法分析器,以了解词法分析的原理和实际应用。
2. 实验目标本实验的主要目标是实现一个基本的词法分析器,能够识别并提取源代码中的各种词法单元。
具体而言,我们将设计一个针对某种编程语言的词法分析器,能够识别关键字、标识符、算术运算符、括号、常量等。
3. 实验环境为了完成本实验,我们需要使用以下工具和环境:•一种编程语言,例如Python、Java或C++•一个文本编辑器,例如Visual Studio Code或Sublime Text•一个命令行终端4. 实验步骤4.1 定义词法规则首先,我们需要定义词法分析器的词法规则。
这些规则描述了编程语言中各种词法单元的模式。
例如,关键字可以被定义为由特定字符组成的字符串,标识符可以被定义为以字母开头并由字母和数字组成的字符串。
4.2 实现词法分析器接下来,我们将根据定义的词法规则,使用编程语言实现一个词法分析器。
在实现过程中,我们可以使用正则表达式来匹配和提取各种词法单元。
4.3 编写测试用例完成词法分析器的实现后,我们需要编写一些测试用例来验证其正确性。
测试用例应该包含各种可能的输入情况,以确保词法分析器能够正确地识别和提取词法单元。
4.4 运行测试用例最后,我们将使用编写的测试用例来运行词法分析器,并检查输出是否符合预期。
如果测试通过,说明词法分析器能够正常工作;否则,我们需要检查代码并进行调试。
5. 实验结果经过实验,我们成功地设计并实现了一个基本的词法分析器。
该词法分析器能够按照预定义的词法规则,正确地识别和提取源代码中的各种词法单元。
在运行测试用例时,词法分析器能够产生符合预期的输出,表明其具有良好的准确性和可靠性。
编译原理课程设计报告——词法分析器
int begin=0,end=0;
vector<string> array;
do
{
begin=DeleteNull(fileline,begin);
string nowString;
nowString=GetWord(fileline,begin,end);
单词符号
种别编码
单词符号
种别编码
main
1
[
28
int
2
]
29
char
3
{
30
if
4
}
31
else
5
,
32
for
6
:
33
while
7
;
34
标识符ID
10
>
35
整型常数NUM
20
<
36
=
21
>=
37
+
22
<=
38
-
23
==
39
*
24
!=
40
/
25
&
41
(
26
&&
42)27||43(2)关键字main int char if elseforwhile都是小写并都是保留字。
int DeleteNull(string str,int i);
/*判断i当前所指的字符是否为一个分界符,是的话返回真,反之假*/
bool IsBoundary(string str,int i);
/*判断i当前所指的字符是否为一个运算符,是的话返回真,反之假*/
编译原理课程设计报告-词法分析器
一.课程设计题目:词法分析器的实现二.课程设计成员三.课程设计内容和要求设计一个程序,调试、编译,实现词法分析的功能,识别各单词或字符所属类别,并显示在屏幕上。
词法分析器:逐个读入源程序字符并按照构词规则切分成一系列单词。
单词是语言中具有独立意义的最小单位,包括保留字、标识符、运算符、标点符号和常量等。
词法分析是编译过程中的一个阶段,在语法分析前进行。
也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
要求:通过词法分析器能够实现以下五种类型如单词等的识别。
(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文本文档,以供选择,各文本文档中都输入有不同的内容,运行程序,出现提示,输入文本文档的名称,即可对文本文档中的内容进行分析,并把分析结果输出显示在屏幕上。
编译原理实验报告 词法分析
编译原理实验一·词法分析一、实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
二、实验内容及要求对某特定语言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、单词种别定义;3、状态转换图;语言A的词法分析的状态转换图如下所示:空格符,制表符或回车符字母或数字4、运行环境介绍;本次实验采用win-tc进行代码的编写和编译及运行程序的运行环境为windows5、关键算法的流程图及文字解释;程序中用到的函数列表:变量ch储存当前最新读进的字符的地址strToken存放当前字符串voidmain() //主函数struct binary *lexicalAnalyze(); //词法分析的主函数,返回一个二元组的指针void GetBC(); //检查ch指向的字符是否为空格、制表或回车符,如果是则调用GetChar()直至不是上述字符void GetChar(); //ch前移一个地址单元int ConCat(); //将ch指向的字符连接到strToken之后int isLetter(); //判断ch指向的字符是否字母int isDigit(); //判断ch指向的字符是否数字int insertId(); //向标识符表中插入当前strToken的字符串int insertConst(); //将strToken的常数插入常数表中int Reserved(); //检测当前strToken中的字符串是否保留字,若是,则返回编码,否则返回0int isId(); //检测当前strToken中的字符串是否在标识符表中已存在,若是,则返回其编号,否则返回0int isConst(); //检测当前strToken中的字符串是否在常数表中已存在,若是,则返回其编号,否则返回0void errProc(int errType); //出错处理过程,errType是错误类型,将错误信息加入错误表中main()函数的流程图如下:lexicalAnalyze()函数的流程图如下所示:Reserved()、isId()和isConst()函数均采用了对链表的遍历算法,errProc()函数通过识别不同的错误编号,向错误链表中添加相应的错误信息。
编译原理课程实验报告(词法分析器及语法分析器)
编译原理实验报告班级:软件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型的识别符。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机与信息学院《编译原理综合设计》报告设计题目:简化的语言词法分析程序设计学生姓名:学号:********专业班级:计算机科学与技术班2015 年7月一、设计题目 (3)二、开发环境与工具 (3)三、任务及要求 (3)四、实现过程 (5)1.算法流程图 (5)2. 关键代码 (6)五、设计结果 (13)六、设计体会 (14)一、设计题目第2题:简化的FORTRAN语言词法分析程序设计将教材P.42上的表3.1的词法分析器构造出来,限制条件如教材所述。
保留字的识别按标识符一样识别,通过查找保留字表区分是保留字还是标识符。
程序能够从用户输入的源程序中,识别出的单词符号,并用二元式表示,显示输出或输出到文件中。
二、开发环境与工具开发环境:Windows开发工具:Eclipse开发语言:Java三、任务及要求1.基本要求:词法分析器产生下述小语言的单词序列这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表:对于这个小语言,有几点重要的限制:首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。
所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。
例如,下面的写法是绝对禁止的:IF(5)=x其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。
也就是说,对于关键字不专设对应的转换图。
但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。
当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。
再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。
例如,一个条件语句应写为IF i>0 i= 1;而绝对不要写成IFi>0 i=1;因为对于后者,我们的分析器将无条件地将IFI看成一个标识符。
这个小语言的单词符号的状态转换图,如下图:四、实现过程1.算法流程图1、词法分析器的流程图2.关键代码import java.util.HashMap;public class STDControl {private String[] keyTable = { "DIM", "IF", "DO", "STOP", "END" };private String[] charTable = { "=", "+", "*", "**" };//, "(", ")", ","private char[] DepartTable = {'(',')',','};private char[] charT = { '=', '+', '*'};private String tempString = "";// IF i = 0 DO i = i + 1private char ch;//存放最新读进的源程序字符private int index;private String[] store = new String[50];private int storeIndex = 0;private int num = 0;private HashMap<String,String> hashmap = new HashMap<String,String>(); private HashMap<String,Integer> hashmap1 = new HashMap<String,Integer>();public STDControl(){index = 0;hashmap.put( "DIM","$DIM" );hashmap.put( "IF","$IF" );hashmap.put( "STOP","$STOP" );hashmap.put( "END","$END" );hashmap.put( "标识符:","$ID" );hashmap.put( "数字:","$ASSIGN" );hashmap.put( "=","$ASSIGN" );hashmap.put( "+","$PLUS" );hashmap.put( "*","$STAR" );hashmap.put( "**","$POWER" );hashmap.put( ",","$COMMA" );hashmap.put( "(","$LPAR" );hashmap.put( ")","$RPAR" );hashmap.put( "DO","$DO" );hashmap1.put( "DIM",1 );hashmap1.put( "IF",2 );hashmap1.put( "STOP",3 );hashmap1.put( "END",4 );hashmap1.put( "标识符:",5 );hashmap1.put( "数字:",6 );hashmap1.put( "=",7 );hashmap1.put( "+",8 );hashmap1.put( "*",9 );hashmap1.put( "**",10 );hashmap1.put( ",",11 );hashmap1.put( "(",12 );hashmap1.put( ")",13 );hashmap1.put( "DO",14 );}public STDControl( String tString){tempString = tString;index = 0;hashmap.put( "DIM","$DIM" );hashmap.put( "IF","$IF" );hashmap.put( "DO","$DO" );hashmap.put( "STOP","$STOP" );hashmap.put( "END","$END" );hashmap.put( "标识符:","$ID" );hashmap.put( "数字:","$INT" );hashmap.put( "=","$ASSIGN" );hashmap.put( "+","$PLUS" );hashmap.put( "*","$STAR" );hashmap.put( "**","$POWER" );hashmap.put( ",","$COMMA" );hashmap.put( "(","$LPAR" );hashmap.put( ")","$RPAR" );hashmap1.put( "DIM",1 );hashmap1.put( "IF",2 );hashmap1.put( "STOP",3 );hashmap1.put( "END",4 );hashmap1.put( "标识符:",5 );hashmap1.put( "数字:",6 );hashmap1.put( "=",7 );hashmap1.put( "+",8 );hashmap1.put( "*",9 );hashmap1.put( "**",10 );hashmap1.put( ",",11 );hashmap1.put( "(",12 );hashmap1.put( ")",13 );hashmap1.put( "DO",14 );}public void setString( String s ){tempString = s;}private boolean IsLetter( char tChar ){if( tChar >= 'a' && tChar <='z' || tChar >= 'A' && tChar <= 'Z' ) return true;elsereturn false;}private boolean IsDigit( char tChar ){if( tChar >='0' && tChar <= '9')return true;elsereturn false;}private boolean IsSymbol( char tChar ){for( int i = 0; i < charT.length; i++ ){if( tChar == charT[i] )return true;}return false;}private boolean IsDepart( char tChar ){for( int i = 0; i < DepartTable.length; i++ ){if( tChar == DepartTable[i] )return true;}return false;}private int checkKey( String a ){for( int i = 0; i < keyTable.length; i++ )if( a.equals( keyTable[i] ) )return i;return -1;}public int getLength(){praseString();for( int i = 0; i < storeIndex; i++ ){if(store[0].equals(null)){System.out.println(store[i]);//System.out.println(store[i]);}elsenum++;}return num;}public void getStore( String[] a){for( int i = 0; i < num; i++){a[i] = store[i];}}private void praseString(){String temp = "";String storeTemp = "";while( index < tempString.length() ){ch = tempString.charAt(index);if( IsLetter( ch ) )//如果是a到Z{while( IsLetter(ch) || IsDigit(ch) ){temp = temp + ch;//继续读下一个index++;ch = tempString.charAt(index);}int keyNum = checkKey( temp );//查看标识符是不是关键字if( keyNum < 0 ){int a = (int)hashmap1.get("标识符:");String s = hashmap.get("标识符:");storeTemp = "标识符:"+temp+" "+s+" "+a;//store[storeIndex] = storeTemp;//是的话存起来storeIndex++;}else{System.out.println(temp);int a = (int)hashmap1.get(temp);String s = hashmap.get(temp);storeTemp = "关键字:"+temp+" "+s+" "+a;//否则是关键字store[storeIndex] = storeTemp;//存起来storeIndex++;temp = "";}}else if( IsDigit( ch ) )//如果是数字{boolean flag=true;while( IsDigit( ch ) )//是数字一直读{temp = temp + ch;index++;ch = tempString.charAt( index );// IF i = 0 DO i = i + 1if( IsLetter( ch ) ){temp = temp + ch;index++;System.out.println( temp + "错误标识符!!!" );temp = "";flag=false;}}if(flag){int a = (int)hashmap1.get("数字:");String s = hashmap.get("数字:");storeTemp = "数字:"+temp+" "+s+" "+a;//store[storeIndex] = storeTemp;storeIndex++;//System.out.println( "数字:" + temp );temp = "";}}else if( IsSymbol( ch ) ){index++;if( tempString.charAt( index ) == '*' ){temp = temp + ch;index++;}int a = (int)hashmap1.get(temp);String s = hashmap.get(temp);storeTemp = "运算符:"+temp+" "+s+" "+a;//store[storeIndex] = storeTemp;storeIndex++;temp = "";}else if( IsDepart( ch ) ){temp = temp + ch;index++;int a = (int)hashmap1.get(temp);String s = hashmap.get(temp);storeTemp = "分隔符:"+temp+" "+s+" "+a;//store[storeIndex] = storeTemp;storeIndex++;}else if( ch == ' '){index++;temp = "";}else{System.out.println( "ERROR " );temp = "";index++;}}}}五、设计结果图1 读入文件内容图2 启动界面图3 实验结果六、设计体会实验结果如上图所示,可以输出符号的种别码和标志,通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把理论知识应用于实验中,也让我重新熟悉了Java语言的相关内容,加深了对Java语言知识的深化和用途的理解。