语言词法分析器和C语言语法分析器上编译原理课程设计_第1页
语言词法分析器和C语言语法分析器上编译原理课程设计_第2页
语言词法分析器和C语言语法分析器上编译原理课程设计_第3页
语言词法分析器和C语言语法分析器上编译原理课程设计_第4页
语言词法分析器和C语言语法分析器上编译原理课程设计_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、四川大学编译原理课程设计 学号2012141461017编译原理课程设计课程报告题目 c语言词法分析器和c-语言语法分析器 学生姓名 学生学号 指导教师 提交报告时间 2019 年 6 月 8 日c语言词法分析器1 实验目的及意义1. 熟悉c语言词法2. 掌握构造dfa的过程3. 掌握利用dfa实现c语言的词法分析器4. 理解编译器词法分析的工作原理2 词法特点及正则表达式2.1词法特点2.1.1 保留字auto, break , case , char , const , continue , default , do , double , else, enum , extern , flo

2、at , for , goto, if , int , long , register , return, short , signed , sizeof , static , struct , switch , typedef , union , unsigned , void, volatile , while,2.1.2 符号 + - * / + - += -= *= = = != = ; , ( ) /* */ : 2.2 正则表达式 whitespace = (newline|blank|tab|comment)+ digit=0|.|9 nat=digit+ signednat=(

3、+|-)?nat num=signednat(“.”nat)? letter = a|.|z|a|.|z id = letter(letter|digit|“_”)+ char = other+ string = “other+”3 token定义3.1 token类型保留字auto break case char const continue default do double elseenum extern float for gotoif int long redisterreturnshort signed sizeof static struct switch typedef uni

4、on unsignedvoid volatile while特殊符号+ - * / + - += -= *= = = != = ; , ( ) /* */ :文件结束、错误eof error其它tokennum id character stringtypedef enum /错误、结束 endfile,error, /保留字 auto,break,case,char,const,continue ,default , do ,double, else, enum, extern , float ,for , goto,if, int, long,register , return, shor

5、t, signed ,sizeof ,static, struct ,switch, typedef ,union, unsigned , void,volatile , while, /其他token id,num,character,string,/特殊符号 /+、-、*、/、+、-、+=、-=、*=、=、=、!=、=、;、,、(、)、/、/*、*/、:plus,minus,times,over,selfplus,selfminus,plusassign,minusassign,timesassign,lt,leq,gt,geq,eq,neq,assign,semi,comma,lpare

6、n, minusassign,timesassign,lt,leq,gt,geq,eq,neq,assign,semi,comma,lparen, rparen,lbracket,rbracket, lcbracket,rcbracket,lcomment,rcomment,colon tokentype;3.2 tokentype类型代码4 dfa设计4.1 注释的dfa设计注释的dfa如下所示,一共分为5个状态,在开始状态1时,如果输入的字符为/,则进入状态2,此时有可能进入注释状态,如果在状态2时,输入的字符为*,则进入注释状态,状态将转到3,如果在状态3时,输入的字符为*,则有可能结束

7、注释状态,此时状态将转到状态4,如果在状态4时输入的字符为/,则注释状态结束,状态转移到结束状态。4.2 词法分析的dfa设计词法分析的dfa如下所示,一共分为10个状态:start、innum、innum1、innum2、inid、incompare、inoperate、instring、inchar、done。状态start表示开始状态,状态innum,innum1,innum2表示数字类型(num)token的状态,状态inid表示标示符(id)类型token的状态,状态inoperate表示算数运算符型token的状态,状态inocompare表示比较运算符型token的状态,inst

8、ring表示字符串(string)类型token的状态,inchar表示字符(character)类型token的状态,状态done表示接收状态。l 在开始状态start时 如果输入的字符为空白符,如空格换行等,则仍在start状态 如果输入的字符为digit,则进入状态innum,即可能是数字类型(num)token的状态 如果输入的字符为letter,则进入状态inid,即可能是标识符类型token的状态 如果输入的字符为、=2) b+=0.1 a+; 6.2 测试结果6.3结果分析test.c文件中包括注释,保留字,整数和小数,标识符,特殊符号,字符串以及错误输入。本程序成功对test.

9、c文件进行了词法分析,对注释进行了忽略,输出了相应的行号、类型、取值,对于错误的输入显示error。7 小结通过编写c语言词法分析器,我对编译器的基本原理有了更深的认识,同时掌握了dfa的设计与实现。在最开始的编写过程中,我总是把词法和语法分析混淆,比如一些错误应该在语法分析中判断,我却写进了词法分析中,后来我逐步认识到词法分析的作用就是提取源代码中的token。在dfa的实现过程中,我主要参考了书后tiny语言dfa的实现方法,将它扩展到c语言。另外c语言词法比较复杂,因为时间关系我省略了一些,比如位运算符,转义字符等等,希望今后能完善。c-语言语法分析器1 实验目的及意义用c语言编制tin

10、y/c-语言的语法分析程序,实现对词法分析程序所提供的token序列的语法检查和结构分析。 2 文法规则(ebnf)programdeclaration-listdeclaration_list declaration declaration declarationvar-declaration|fun-declarationvar_declaration type-specifier id; | type-specifier id num;type - specifier int | voidfun-declatationtype-specifier id (params) | compou

11、nd-stmtparamsparam_list | voidparam_listparam, paramparam type-specifier id compound-stmt local-declaration statement-listlocal-declarations empty var- declarationstatement-liststatementstatementexpression-stmt | compound-stmt | selection-stmt | iteration-stmt | return-stmtexpression-stmt expression

12、;selection-stmtif (expression) statement else statementiteration-stmtwhile (expression)statementreturn-stmtreturn expression;expression var = expression | simple-expressionrelop = | | = | = = | ! =varid | id expressionsimple-expressionadditive-expression relop additive-expression additive-expression

13、termaddop term addop + | -termfactormulop factor mulop * | /factor(expression) | var | call | numcallid( args )argsarg-list | emptyarg-list expression, expression3 节点类型及定义3.1节点类型节点类型描述子节点intkint型变量或返回值无voidkvoid型变量或返回值无idk标示符id无constk数值无var_declk变量声明变量类型+变量名var_declk数组声明数组名+数组大小funk函数声明返回类型+函数名+参数列表

14、+函数体paramskfunk的参数列表参数(如果有多个参数,则之间为兄弟节点)paramkfunk的参数参数类型+参数名compk复合语句体变量声明列表+语句列表selection_stmtkif条件表达式+if体+else体iteration_stmtkwhile条件表达式+循环体return_stmtkreturn表达式assignk赋值被赋值变量+赋值变量opk运算运算符左值+运算符右值arry_elemk数组元素数组名+下标callk函数调用函数名+参数列表argskcallk的参数列表表达式unkownk未知节点无3.2节点定义typedef struct treenodestru

15、ct treenode * child4;struct treenode * sibling;int lineno;nodekind nodekind;union tokentype op; int val; const char * name; attr; exptype type; treenode;4 代码结构分析文法programdeclaration-list分析函数treenode * parse(void)说明c-程序由一个声明序列组成,parse(void)函数首先执行gettoken()然后直接调用declaration_list()返回树节点代码treenode * par

16、se(void)treenode * t;token = gettoken();t = declaration_list();if(token!=endfile) syntaxerror(endfile error);return t;文法declaration_list declaration declaration 分析函数treenode * declaration_list(void)说明声明序列是由若干声明构成,declaration_list(void)函数中直接调用declaration()函数返回树节点,当前token为int或void时,调用declaration()返回之前

17、树节点的兄弟节点。代码treenode * declaration_list(void)treenode * t = declaration();treenode * p =t;/程序以变量声明开始 while(token!=int)&(token!=void)&(token!=endfile) syntaxerror(开始不是类型声明); token = gettoken(); if(token=endfile) break; while(token=int|token=void)treenode * q;q = declaration();if (q!=null)if (t=null)t=

18、p=q;elsep-sibling=q;p=q;match(endfile);return t;文法declarationvar-declaration|fun-declarationvar_declaration type-specifier id; | type-specifier id num;fun-declatationtype-specifier id (params) | compound-stmt type-specifier int | void分析函数 treenode * declaration(void)说明首先判断类型,执行match函数, 匹配类型和id,向前探测1

19、个token的值确定是函数声明还是变量声明,如果token为,则是数组变量声明,返回节点array_declk, token为(,则是函数声明,返回节点funk, token为;则是普通变量声明,返回节点var_declk代码treenode * declaration(void)treenode * t = null;treenode * p = null;treenode * q = null;treenode * s = null;treenode * a = null;if (token=int)p=newnode(intk);match(int);else if (token=voi

20、d)p=newnode(voidk);match(void);else syntaxerror(type error);if(p!=null&token=id)q = newnode(idk); = copystring(tokenstring); match(id);if (token=lparen)t = newnode(funk);t-child0 = p; /p是t子节点t-child1 = q;match(lparen);t-child2 = params();match(rparen);t-child3 = compound_stmt();else if (t

21、oken=lbracket)t = newnode(var_declk);a = newnode(arry_declk);t-child0 = p; /p是t子节点t-child1 = a;match(lbracket);s = newnode(constk);s-attr.val = atoi(tokenstring);match(num);a-child0=q;a-child1=s;match(rbracket);match(semi);else if (token=semi)t = newnode(var_declk);t-child0 = p;t-child1 = q;match(se

22、mi);elsesyntaxerror();elsesyntaxerror();return t;文法paramsparam_list | void分析函数treenode * params(void)说明参数列表,根节点paramsk,首先判断token是否是void,如果是void则匹配,判断下一个token,如果是右括号,则参数列表中只有子节点voidk,如果是id,则子节点是param_list,如果开始时token是int,则参数列表子节点是param_list代码treenode * params(void)treenode * t = newnode(paramsk);treen

23、ode * p = null;if (token=void)p = newnode(voidk);match(void);if (token=rparen)if(t!=null)t-child0 = p;else/参数列表为(void id,) t-child0 = param_list(p);else if (token=int)t-child0 = param_list(p);else syntaxerror();return t;文法param_listparam, param分析函数treenode * param_list(treenode * k)说明说明参数列表由param序列组

24、成,并由逗号隔开。param_list(treenode * k)函数使用递归向下分析方法直接调用param(treenode * k)函数,并返回树节点代码treenode * param_list(treenode * k)treenode * t = param(k);treenode * p = t; k = null;/没有要传给param的voidk,所以将k设为nullwhile (token=comma)treenode * q = null;match(comma);q = param(k);if (q!=null)if (t=null)t=p=q;elsep-sibling

25、 = q;p = q;return t;文法param type-specifier id 分析函数treenode * param(treenode * k)说明探测token是int还是void,决定子节点类型是intk还是voidk,idk作为第二个子节点,向前探测一个token,如果是左中括号,则产生第三个子节点代码treenode * param(treenode * k)treenode * t = newnode(paramk);treenode * p = null;treenode * q = null;if(k=null&token=void)p = newnode(voi

26、dk);match(void);else if(k=null&token=int)p = newnode(intk);match(int);else if (k!=null)p = k;if(p!=null)t-child0 = p;if (token=id)q = newnode(idk); = copystring(tokenstring);t-child1 = q;match(id);elsesyntaxerror();if (token=lbracket&(t-child1!=null)/match(lbracket);t-child2 = newnode(idk

27、);match(rbracket);else return t; else syntaxerror();return t;文法compound-stmt local-declaration statement-list分析函数treenode * compound_stmt(void)说明复合语句,直接调用local_declaration()函数和statement_list()函数,产生两个子节点代码treenode * compound_stmt(void) treenode * t = newnode(compk);match(lcbracket);t-child0 = local_d

28、eclaration();t-child1 = statement_list(); match(rcbracket);return t;文法local-declarations empty var- declaration分析函数treenode * local_declaration(void)说明全局变量声明,可以是空,也可以是若干变量声明,首先判断token是否等于int或void,从而得知是否为空,若不为空则创建一个var_declk节点代码treenode * local_declaration(void) treenode * t = null;treenode * q = nul

29、l;treenode * p = null;while(token=int | token=void) p = newnode(var_declk);if(token=int)treenode * q1 = newnode(intk);p-child0 = q1;match(int);else if(token=void)treenode * q1 = newnode(voidk);p-child0 = q1;match(int);if(p!=null)&(token=id) treenode * q2 = newnode(idk); = copystring(tok

30、enstring);p-child1 = q2;match(id);if(token=lbracket) treenode * q3 = newnode(var_declk);p-child3 = q3;match(lbracket);match(rbracket);match(semi);else if(token=semi)match(semi);elsematch(semi); else syntaxerror();if(p!=null)if(t=null)t = q = p;elseq-sibling = p;q = p;return t;文法statement-liststateme

31、nt分析函数treenode * statement_list(void)说明调用statement()创建根节点,向前探测一个token,创建兄弟节点代码treenode * statement_list(void) treenode * t = statement(); treenode * p = t;while (if=token | lcbracket=token | id=token | while=token | return =token | semi=token | lparen=token | num=token) treenode * q;q = statement();

32、if(q!=null)if(t=null) t = p = q;else p-sibling = q;p = q;return t;文法statementexpression-stmt| compound-stmt | selection-stmt | iteration-stmt | return-stmt分析函数treenode * statement(void)说明statement由表达式或复合语句或if语句或while语句或return语句构成。statement(void)函数通过判断先行token类型确定到底是哪一种类型。如果是if则调用selection_statement()

33、,如果是while,则调用iteration_stmt(),如果是return,则调用return(),如果是左大括号,则是复合语句类型,如果是id、semi、lparen、num,则是表达式语句类型代码treenode * statement(void) treenode * t = null;switch(token)case if:t = selection_stmt(); break;case while:t = iteration_stmt(); break;case return:t = return_stmt(); break;case lcbracket:t = compoun

34、d_stmt(); break;case id: case semi: case lparen: case num: t = expression_stmt(); break;default:syntaxerror();token = gettoken();break;return t;文法expression-stmt expression;分析函数treenode * expression_stmt(void)说明说明表达式语句有一个可选的且后面跟着分号的表达式。expression_stmt(void)函数通过判断先行token类型是否为分号,如果不是则直接调用函数expression(

35、)代码treenode * expression_stmt(void) treenode * t = null;if(token=semi) match(semi);return t;else t = expression();match(semi);return t;文法expression var = expression | simple-expression分析函数treenode * expression(void)说明expression(void)函数通过判断先行token类型是否为id,如果不是说明只能是simple_expression情况,则调用simple_express

36、ion(treenode * k)函数递归向下分析;如果是id说明可能是赋值语句,或simple_expression中的var和call类型的情况,所以再求其follow集合,如果集合求出来是赋值类型的token,则说明是赋值语句,于是新建一个assignk节点就行;如果集合求出来不是赋值类型的token则说明是simple_expression中的var和call类型的情况,然后再调用simple_expression(treenode * k)函数递归向下分析,并将已经取出idk节点传递给simple_expression(treenode * k)函数代码treenode * expr

37、ession(void) treenode * t = var();if(t=null)/不是以id开头,只能是simple_expression情况 t = simple_expression(t); else/以id开头,可能是赋值语句,或simple_expression中的var和call类型的情况 treenode * p = null;if(token=assign)/赋值语句 p = newnode(assignk);/ = ;match(assign);p-child0 = t;p-child1 = expression();return p;else /

38、simple_expression中的var和call类型的情况 t = simple_expression(t); return t;文法varid | id expression分析函数treenode * var(void)说明创建idk节点,判断先行token类型是否是中括号,如果是就创建arry_elemk节点,调用expression()得到子节点代码treenode * var(void) treenode * t = null;treenode * p = null;treenode * q = null;if(token=id)p = newnode(idk);p-attr.

39、name = copystring(tokenstring); match(id);if(token=lbracket) match(lbracket);q = expression();match(rbracket);t = newnode(arry_elemk);t-child0 = p;t-child1 = q;elset = p;return t;文法simple-expressionadditive-expression relop additive-expression relop = | | = | = = | ! =分析函数treenode * simple_expressio

40、n(treenode * k)说明simple_expression(treenode * k)函数先调用additive_expression(treenode * k)函数返回一个节点,然后再一直判断后面的token是否为=、=、=、!=,如果是则新建opk节点,然后令之前的节点为其第一个子节点,然后继续调用additive_expression(treenode * k)函数返回一个节点,作为opk节点的第二个节点代码treenode * simple_expression(treenode * k) treenode * t = additive_expression(k);k = n

41、ull;if(eq=token | gt=token | geq=token | lt=token | leq=token | neq=token) treenode * q = newnode(opk);q-attr.op = token; q-child0 = t;t = q;match(token);t-child1 = additive_expression(k); return t;return t;5 实验结果与分析测试文本test.cint a10;int min(int a,int low,void a)int k; int x; int i;k=low;while(i0)x=

42、1;return x;测试结果成功实现语法分析6 小结通过这次实验,我加深了对语法分析的认识,掌握了递归向下分析方法,实现了对词法分析程序所提供的token序列的语法检查和结构分析。 语法分析程序编写相对于词法分析要困难得多,首先要将bnf化为ebnf,运用递归向下的方法进行编写,构造出语法树,判别语法分析过程中是否出错以及出错位置和错误类型。虽然ebnf转换成代码的过程原理比较简单,但是操作起来比较繁琐。一开始我对treenode数据结构也不是很理解,通过阅读书后的tiny语言语法分析源代码,我弄懂了语法树的输出。附录(源代码)main.c#include global.h#include util.h#include scan.h/* 全局变量 */int lineno = 0;/* 编译过程标志 */int echosource = true;int tracescan = true;int error = fal

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论