文档库 最新最全的文档下载
当前位置:文档库 › C语言词法分析器和C语言语法分析器编译原理课程设计

C语言词法分析器和C语言语法分析器编译原理课程设计

《编译原理课程设计》课程报告题目 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 , FLOAT , 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=(+|-)?nat

NUM=signedNat(“.”nat)?

letter = a|..|z|A|..|Z

ID = letter(letter|digit|“_”)+

CHAR = 'other+' STRING = “other+”

3 Token定义

3.2 tokenType类型代码

4 DFA设计

4.1 注释的DFA设计

注释的DFA如下所示,一共分为5个状态,在开始状态1时,如果输入的字符为/, 则进入状态2,此时有可能进入注释状态,如果在状态2时,输入的字符为*,则进入注释状态,状态将转到3,如果在状态3时,输入的字符为*,则有可能结束注释状态,此时状态将转到状态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的状态,INSTRING表示字符串(STRING)类型Token的状态,INCHAR表示字符(CHARACTER)类型Token的状态,状态DONE表示接收状态。

●在开始状态START时

?如果输入的字符为空白符,如空格换行等,则仍在START状态

?如果输入的字符为digit,则进入状态INNUM,即可能是数字类型(NUM)Token的状态

?如果输入的字符为letter,则进入状态INID,即可能是标识符类型Token的状态

?如果输入的字符为>、<、!、=,则进入状态INCOMPARE,即可能是比较运算符型Token的状态

?如果输入的字符为+、—、*、/,则进入状态INOPERATE,即可能是算数运算符类型Token的状态

?如果输入的字符为‘,则进入状态INCHAR,即可能是字符类型Token的状态

?如果输入的字符为“,则进入状态INSTRING,即可能是字符串类型Token的状态

?如果输入的字符为是除以上之外的,则进入状态DONE,这次输入的字符可能是单目运算符、错误等

●在状态INNUM时

?如果输入的字符为digit,则仍停留在INNUM状态

?如果输入的字符为”.”,则转到INNUM1状态

●在状态INNUM1时

?如果输入的字符为digit,则进入INNUM2状态

●在状态INNUM2时

●如果输入的为其他的字符,则转到DONE状态

?如果输入字符为digit,则停留在INNUM2状态

?如果输入的为其他字符,则转到DONE状态

●在状态INID时

?如果输入的字符为letter或“_”或digit,则仍停留在INID状态

?如果输入的为其他的字符,则转到DONE状态

●在状态INCOMPARE时

?如果输入的字符为=,则转到DONE状态

?如果输入的为其他的字符,则直接转到DONE状态

●在状态INOPERATE时

?如果输入的字符为=,转到DONE状态

?如果输入的为其他的字符,则直接转到DONE状态

●在状态INCOMPARE时

?如果输入的字符为=,则转到DONE状态

?如果输入的为其他的字符,则直接转到DONE状态

●在状态INCHAR时

?如果输入为单引号,则转到DONE状态

?如果输入的为其他字符,则停留在INCHAR状态

●在状态INSTRING时

?如果输入为双引号,则转到DONE状态

?如果输入的为其他字符,则停留在INSTRING状态

●在状态DONE时

接受状态,根据分析过程中获取的字符串确定Token的类型,并生成和保存相应的Token

5 代码结构分析

5.1主要结构

词法分析部分的代码在scan.c和scan.h文件中,全局变量以及公共函数代码在global.h以及util.h和util.c文件中。主函数中进行文件打开和关闭,并调用scan.c中的getToken()函数对源文件进行词法分析。

5.2 函数和成员变量的作用和含义

void printToken(TokenType,const char*); /*输出token */

char* copyString(char*); /* 字符串复制*/

TokenType getToken(void);/* 词法分析函数*/

static int getNextChar(void)/* 获取下一个字符*/

static void ungetNextChar(void)/* 退回一个字符*/

static TokenType reservedLookup (char* s) /* 查找对应的保留字*/

char tokenString[MAXTOKENLEN+1]; /* token字符串*/

int lineno =0;/* 当前行号*/

static char lineBuf[BUFLEN];/* 整行代码缓冲区*/

static int linepos =0;/* 当前行的位置*/

static int bufsize =0;/* 缓冲区大小*/

static int EOF_flag = FALSE;/* 文件结束标志*/

6 实验结果与分析

6.1 测试文件test.c

/*test.c*/

int main(void)

{

###

int a =0;

float b =20.1;

char c[]="abcdefg";

char d ='h';

if(a>=2)

{

b+=0.1

a++;

}

}

6.2 测试结果

6.3结果分析

test.c文件中包括注释,保留字,整数和小数,标识符,特殊符号,字符串以及错误输入。

本程序成功对test.c文件进行了词法分析,对注释进行了忽略,输出了相应的行号、类型、取值,对于错误的输入显示ERROR。

7 小结

通过编写C语言词法分析器,我对编译器的基本原理有了更深的认识,同时掌握了DFA 的设计与实现。

在最开始的编写过程中,我总是把词法和语法分析混淆,比如一些错误应该在语法分析中判断,我却写进了词法分析中,后来我逐步认识到词法分析的作用就是提取源代码中的Token。在DFA的实现过程中,我主要参考了书后tiny语言DFA的实现方法,将它扩展到C 语言。另外C语言词法比较复杂,因为时间关系我省略了一些,比如位运算符,转义字符等等,希望今后能完善。

C-语言语法分析器

1 实验目的及意义

用C语言编制Tiny/C-语言的语法分析程序,实现对词法分析程序所提供的Token

序列的语法检查和结构分析。

2 文法规则(EBNF)

program→declaration-list

declaration_list → declaration{ declaration }

declaration→var-declaration|fun-declaration

var_declaration →type-specifier ID; | type-specifier ID [NUM];

type - specifier → int | void

fun-declatation→type-specifier ID (params) | compound-stmt

params→param_list | void

param_list→param{, param}

param→ type-specifier ID{[ ]}

compound-stmt→{ local-declaration statement-list}

local-declarations → empty {var- declaration}

statement-list→{statement}

statement→expression-stmt | compound-stmt | selection-stmt | iteration-stmt | return-stmt expression-stmt→ [expression];

selection-stmt→if (expression) statement [else statement]

iteration-stmt→while (expression)statement

return-stmt→return [expression];

expression→ var = expression | simple-expression

relop → < = | < | > | > = | = = | ! =

var→ID | ID [expression]

simple-expression->additive-expression{ relop additive-expression }

additive-expression→term{addop term }

addop → + | -

term→factor{mulop factor }

mulop →* | /

factor→(expression) | var | call | NUM call→ID( args )

args→arg-list | empty

arg-list→ expression{, expression}

3 节点类型及定义

3.1节点类型

3.2节点定义

typedef struct treeNode

{

struct treeNode *child[4];

struct treeNode *sibling;

int lineno;

NodeKind nodekind;

union{ TokenType op;int val;const char* name;} attr;

ExpType type;

} TreeNode;

4 代码结构分析

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=p=q;

}

else

{

p->sibling=q;

p=q;

}

}

}

match(ENDFILE);

return t;

}

{

t = newNode(Var_DeclK);

a = newNode(Arry_DeclK);

t->child[0]= p;//p是t子节点

t->child[1]= a;

match(LBRACKET);

s = newNode(ConstK);

s->attr.val = atoi(tokenString);

match(NUM);

a->child[0]=q;

a->child[1]=s;

match(RBRACKET);

match(SEMI);

}

else if(token==SEMI)

{

t = newNode(Var_DeclK);

t->child[0]= p;

t->child[1]= q;

match(SEMI);

}

else

{

syntaxError("");

}

}

else

{

syntaxError("");

}

return t;

}

else if(k!=NULL)

{

p = k;

}

if(p!=NULL)

{

t->child[0]= p;

if(token==ID)

{

q = newNode(IdK);

q->https://www.wendangku.net/doc/457492946.html, = copyString(tokenString);

t->child[1]= q;

match(ID);

}

else

{

syntaxError("");

}

if(token==LBRACKET&&(t->child[1]!=NULL))//@@@@@@@@@@@@

{

match(LBRACKET);

t->child[2]= newNode(IdK);

match(RBRACKET);

}

else

{

return t;

}

}

else

{

syntaxError("");

}

return t;

}

TreeNode * q2 = newNode(IdK);

q2->https://www.wendangku.net/doc/457492946.html, = copyString(tokenString);

p->child[1]= q2;

match(ID);

if(token==LBRACKET)

{

TreeNode * q3 = newNode(Var_DeclK);

p->child[3]= q3;

match(LBRACKET);

match(RBRACKET);

match(SEMI);

}

else if(token==SEMI)

{

match(SEMI);

}

else

{

match(SEMI);

}

}

else

{

syntaxError("");

}

if(p!=NULL)

{

if(t==NULL)

t = q = p;

else

{

q->sibling = p;

q = p;

}

}

}

return t;

}

相关文档
相关文档 最新文档