语法、词法分析结合

语法、词法分析结合
语法、词法分析结合

语法、词法分析结合

一、实验目的与要求

通过设计、编制、调试一个典型的语法分析程序(任选有代表性的语法分析方法,如算符优先法、递归下降法、LL(1)、SLR(1)、LR(1)等,作为编制语法分析程序的依据),对扫描器所提供的单词序列进行语法检查和结构分析,实现并进一步掌握常用的语法分析方法。

二、实验内容

选择对各种常见高级程序设计语言都较为通用的语法结构作为分析对象,给出其文法描述(注意应与所采用的语法分析方法比较贴近),设计并实现一个完整的语法分析程序(分析过程暂不嵌入任何的语义动作)。

输入:由实验一输出的单词串,例如:UCON,PL,UCON ······

输出:对于输入的符号串,若是给定文法定义的合法句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。

三、一般实现方法说明

例如,以如下文法G2所定义的算术表达式的赋值语句作为分析对象,编写并调试一个语法分析程序。

G2[<复合语句>]:

<复合语句> → begin<语句表>end

<语句表> → <语句>|<语句>;<语句表>

<语句> → <赋值语句>

<赋值语句> → <变量>:=<算术表达式>

<算术表达式> → <项> | <算术表达式>+<项> | <算术表达式>-<项>

<项> → <因式> | <项>*<因式> | <项>/<因式>

<因式> → <变量> | <常数> | (<算术表达式>)

<变量> → <标识符>

<标识符> → <标识符> <字母> | <标识符> <数字> | <字母>

<常数> → <整数> | <浮点数>

<整数> → <数字> | <数字> <整数>

<浮点数> →? <整数> | <整数> ? <整数>

<字母> → A|B|C|…|X|Y|Z|a|b|c|…|x|y|z

<数字> → 0|1|2|…|9

说明:1)可将以上文法G2[<复合语句>]中的语法范畴<常数>替换为实验一中的文法G1[<无符号数>],并将单词类型——无符号常数进一步细分成整数和浮点数两类单词。2)注意修改实验一中的词法分析程序,将它编写为子程序的形式,以便供语法分析程序调用,从而在对源程序的一遍扫描过程中,同时完成词法和语法分析任务。3)应加强错误检查,对输入符号串中的词法、语法错误,给出必要的说明信息,尽可能多地、确切地指出错误的位置、原因和性质。例如,在词法分析阶段,对当前正在处理的字符ch,可进一步定义一些与该字符相关的信息row和col,分别表示该字符所在的行和列,这些内容在出错处理时用来提供和源程序位置相关的信息。即定义:

char ch; /*The current character*/

int row; /*The line number position of the current character*/

int col; /*The column number position of the current character*/

四、基本实验题目

题目:对算术表达式的一个简化子集,根据如下其语法结构的BNF定义G3[<算术表达式>],任选学过的一种语法分析方法,针对运算对象为无符号数的四则运算,编制一个语法分析程序。

G3[<算术表达式>]:

<算术表达式> → <项> | <算术表达式>+<项> | <算术表达式>-<项>

<项> → <因式> | <项>*<因式> | <项>/<因式>

<因式> → <运算对象> | (<算术表达式>)

若将非终结符号<算术表达式>、<项>、<因式>和<运算对象>分别用E、T、F和i代表,则G3可写成:

E→T|E+T|E-T T→F|T*F|T/F F→i|(E)

本部分用SLR(1)分析器的开发。

可以根据文法G3[<算术表达式>]构造识别其全部活前缀的DFA,再据此构造SLR(1)分析表,然后编程实现SLR(1)分析表的驱动程序,即LR分析器的总控程序,完成对算术表达式的识别。主要是用三维字符数组构造一个slr(1)的状态转移表,然后主控程序控制查询三维数组,调用一次词法分析再调用一次语法分析。

五、源程序

说明:因为后面两个程序都是在第一个基础上改进的,所以工程的名字始终是“词法分析”

**********************词法分析.h

# include

# include

# include

# include

# include

# define LB 0//左括号

# define RB 1//右括号

# define PL 2

# define MI 3

# define MU 4

# define DI 5

# define UCON 6 //Suppose the class number of unsigned constant is 7

# define OVER 7

//# define INT 7

# define LT 8

# define LE 9

# define EQ 10

# define NE 11

# define GT 12

# define GE 13

# define IS 19//14至18被五个关键字占用

# define ID 20

#define MAX_KEY_NUMBER 20 /*关键字的数量*/

#define KEY_WORD_END "waiting for your expanding" /*关键字结束标记*/

char *KeyWordTable[MAX_KEY_NUMBER]={"begin","end", "if", "then", "else", KEY_WORD_END};

char TOKEN[20]="";

char ch=' ';//用于存储带判断的字符

int row=1;//row标识错误在第几行

//无符号数部分

#define DIGIT 1

#define POINT 2

#define OTHER 3

#define POWER 4

#define PLUS 5

#define MINUS 6

#define ClassOther 200

#define EndState -1

int index=0;//保存已读的字符串的索引

//char JudgeStr[256];//存储已读的字符串

int w,n,p,e,d;

int Class; //Used to indicate class of the word

int ICON;

float FCON;

static int CurrentState; //Used to present current state, the initial value:0

///////语法分析部分

//产生式

/* 1、E->E+T 2、E->E-T 3、E->T 4、T->T*F 5、T->T/F 6、T->F 7、F->(E) 8、F->i

*/

# define Max 256

//goto表的列项

# define E 0

# define T 1

# define F 2

int StateStack[Max];//状态栈

int StackPoint;//状态栈指针

int TopState;//作为状态栈盏栈顶指针

int InputWordType;//输入的单词类型

// ( ) + - * / i #

char Action[16][8][4]={"s4", " ", " ", " ", " ", " ", "s5", " ",

" ", " ", "s6", "s7", " ", " ", " ", "A",

" ", "r3", "r3", "r3", "s8", "s9", " ", "r3",

" ", "r6", "r6", "r6", "r6", "r6", " ", "r6",

"s4", " ", " ", " ", " ", " ", "s5", " ",

" ", "r8", "r8", "r8", "r8", "r8", " ", "r8",

"s4", " ", " ", " ", " ", " ", "s5", " ",

"s4", " ", " ", " ", " ", " ", "s5", " ",

"s4", " ", " ", " ", " ", " ", "s5", " ",

"s4", " ", " ", " ", " ", " ", "s5", " ",

" ", "s15", "s6", "s7", " ", " ", " ", " ",

" ", "r1", "r1", "r1", "s8", "s9", " ", "r1",

" ", "r2", "r2", "r2", "s8", "s9", " ", "r2",

" ", "r4", "r4", "r4", "r4", "r4", " ", "r4",

" ", "r5", "r5", "r5", "r5", "r5", " ", "r5",

" ", "r7", "r7", "r7", "r7", "r7", " ", "r7",};//action表

// E T F

int Goto[16][3]={ { 1, 2, 3},

{-1, -1, -1},

{-1, -1, -1},

{-1, -1, -1},

{10, 2, 3},

{-1, -1, -1},

{-1, 11, 3},

{-1, 12, 3},

{-1, -1, 13},

{-1, -1, 14},

{-1, -1, -1},

{-1, -1, -1},

{-1, -1, -1},

{-1, -1, -1},

{-1, -1, -1},

{-1, -1, -1},};//goto表

int EXCUTE (int state, int symbol,FILE *fp,char JudgeStr[],int row,int index);

int GetChar (char ch);

int HandleError (char StrJudge[],int row);

int Push( int State );

int Pop(int count);

int SLRControl(FILE* fp);

************************************词法分析.c

#include "词法分析.h"

//////////////////////////////////////////////////查保留字表,判断是否为关键字

int lookup (char *token)

{

int n=0;

while (strcmp(KeyWordTable[n], KEY_WORD_END)) /*strcmp比较两串是否相同,若相同返回0*/

{

if (!strcmp(KeyWordTable[n], token)) /*比较token所指向的关键字和保留字表中哪个关键字相符*/

{

return n+1; /*根据单词分类码表I,设置正确的关键字类别码,并返回此类别码的值*/

break;

}

n++;

}

return 6; /*单词不是关键字,而是标识符*/

}

///////////////////////////////////////////////////输出分析结果

void out (int i, char* pStr)

{

char Mnemonic[5];

if(0==i)

{

strcpy(Mnemonic,"LB");

}

else if(1==i)

{

strcpy(Mnemonic,"RB");

}

else if(2==i)

{

strcpy(Mnemonic,"PL");

}

else if(3==i)

{

strcpy(Mnemonic,"MI");

}

else if(4==i)

{

strcpy(Mnemonic,"MU");

}

{

strcpy(Mnemonic,"DI");

}

else if(6==i)

{

strcpy(Mnemonic,"UCON"); }

else if(7==i)

{

strcpy(Mnemonic,"OVER"); }

else if(8==i)

{

strcpy(Mnemonic,"LT");

}

else if(9==i)

{

strcpy(Mnemonic,"LE");

}

else if(10==i)

{

strcpy(Mnemonic,"EQ");

}

else if(11==i)

{

strcpy(Mnemonic,"NE");

}

else if(12==i)

{

strcpy(Mnemonic,"GT");

}

else if(13==i)

{

strcpy(Mnemonic,"GE");

}

else if(14==i)

{

strcpy(Mnemonic,"BEGIN"); }

else if(15==i)

{

strcpy(Mnemonic,"END"); }

{

strcpy(Mnemonic,"IF");

}

else if(17==i)

{

strcpy(Mnemonic,"THEN");

}

else if(18==i)

{

strcpy(Mnemonic,"ELSE");

}

else if(19==i)

{

strcpy(Mnemonic,"IS");

}

else if(20==i)

{

strcpy(Mnemonic,"ID");

}

else

{

strcpy(Mnemonic,"Unkown Type");

}

printf("(%s )对应%s\n",Mnemonic,pStr);

}

/////////////////////////////////////////////////报错

void report_error (int row)

{

printf("%s Error! In the %d row\n",TOKEN,row);

}

/////////////////////////////////////////////////////////////扫描程序

void scanner(FILE *fp)//总的判断函数开始就应该判断已读取的字符是否为空字符,不为则不用再读,直接进行判断,否则再读

{

//printf("***ch=%c******\n",ch);

int i, c;

fseek(fp,-1,1);//首先回溯一个字符,就是将文件所有的字符都在scanner内部判断,外部while循环不会浪费任何字符

ch=fgetc (fp);//scanner中要想判断字符,必须开头先读一个字符

while(' '==ch||'\n'==ch||'\t'==ch)//将文件中的所有空字符浪费在这里

{

if('\n'==ch)

row++;

}

ch=fgetc (fp);

}

if(EOF==ch)

{

return;

}//必须在这里判断一下

/*if(' '==ch||'\n'==ch||'\t'==ch)

{

fseek(fp,-1,1);

return;

}*/

//ch=fgetc (fp);

/*if(' '==ch||'\n'==ch||'\t'==ch)

{

fseek(fp,-1,1);

return;//文件结束标志不能与这几个空白符作为一种情况考虑,因为文件遇到结束标志时,不能回退

}//文件指针,否则在外层的while循环中造成死循环,由此猜测fgetc函数执行的过程为,先读取

*/ //当前文件指针所指的字符,再将字符指针后移!

if (isalpha (ch)) /*it must be a identifer!*/

{

TOKEN[0]=ch; ch=fgetc (fp); i=1;

while (isalnum (ch))

{

TOKEN[i]=ch; i++;

ch=fgetc (fp);

}

TOKEN[i]= '\0';

fseek(fp,-1,1); /* retract*/

c=lookup (TOKEN);

if (c!=6) out (c+13,TOKEN); else out (c+14,TOKEN);//此处加13或者14因为一些常量的定义产生冲突,被迫修改以适应

}

else if(isdigit(ch)|| '.'==ch)

{

fseek (fp,-1,1);//首先回溯一个字符,下面为了循环内部使用先读字符后判

int Type;

CurrentState=0;

i=0;

do

{

ch=fgetc(fp);

TOKEN[i]=ch;

i++;

TOKEN[i]='\0';//为随时输出字符串做准备

Type=GetChar(ch);

EXCUTE (CurrentState,Type,fp,TOKEN,row,i);

}while(CurrentState!=EndState);

/*TOKEN[0]=ch; ch=fgetc(fp); i=1;

while(isdigit(ch))

{

TOKEN[i]=ch; i++;

ch=fgetc(fp);

}

TOKEN[i]= '\0';

fseek(fp,-1,1);

out(INT,TOKEN);*/

}

else

switch(ch)

{

case '<': ch=fgetc(fp);

if(ch=='=')out(LE,"<=");

else if(ch=='>') out (NE,"<>");

else

{

//fseek (fp,-1,1);

out (LT,"<");

}

break;

case '=':

{

ch=fgetc(fp);

if('='==ch)

{

out(EQ, "==");

}

else

{

//fseek (fp,-1,1);

out(IS, "=");

}

}

break;

case '>': ch=fgetc(fp);

if(ch=='=')out(GE,">=");

else

{

//fseek(fp,-1,1);

out(GT,">");

}

break;

case '+':

{

InputWordType=PL;

out(PL,"+");

}

break;

case '-':

{

InputWordType=MI;

out(MI,"-");

}

break;

case '*':

{

InputWordType=MU;

out(MU,"*");

}

break;

case '/':

{

InputWordType=DI;

out(DI,"/");

}

break;

case '(':

{

InputWordType=LB;

out(LB,"(");

}

break;

case ')':

{

InputWordType=RB;

out(RB,")");

}

break;

case '#':

{

InputWordType=OVER;

out(OVER,"#");

}

break;

default: report_error(row); break;

}

return;

}

///////////////////////////////////无符号数判断矩阵执行程序

int EXCUTE (int state, int symbol,FILE *fp,char JudgeStr[],int row,int index)

{//row用于指示出错的行数,index用于为待输出的字符串赋结束符‘\0’时用switch (state)

{

case 0:switch (symbol)

{

case DIGIT: n=0;p=0;e=1;w=d;CurrentState=1;Class=UCON;break;

case POINT: w=0;n=0;p=0;e=1;CurrentState=3;Class=UCON;break;

default:

{

Class=ClassOther;

CurrentState=EndState;

printf("无符号数的第一个字符是非法的!\n");

}

}

break;

case 1:switch (symbol)

{

case DIGIT: w=w*10+d;break; //CurrentState=1

case POINT: CurrentState=2;break;

case POWER: CurrentState=4;break;

default:

{

if (ch!=EOF)//如果是因为读到文件结束字符而终止识别(是正确识别一个无符号数结束),就不应该回退,否则可能造成死循环

{

fseek(fp,-1,1);//遇到其他的字符,可能是一条语句中的其他字符,需后退,因为主函数外层循环每次都要读一个字符进行判断,而这个判读不回溯,所以在内部把这个多读的字符回溯

}

ICON=w;CurrentState=EndState;

JudgeStr[index-1]='\0';

InputWordType=UCON;

printf("(UCON,%i)对应%s\n",ICON,JudgeStr);

}break;

}

break;

case 2:switch (symbol)

{

case DIGIT: n++;w=w*10+d;break;

case POWER: CurrentState=4;break;

default:

{

if (ch!=EOF)

{

fseek(fp,-1,1);

}

FCON=w*pow(10,e*p-n);CurrentState=EndState;

JudgeStr[index-1]='\0';

InputWordType=UCON;

printf("(UCON,%f)对应于%s\n",FCON,JudgeStr);

}

}

break;

case 3:switch (symbol)

{

case DIGIT: n++;w=w*10+d;CurrentState=2;break;

default:

{

/* if (ch!=EOF)//识别无符号数产生错误时,不应该再回溯,应该把造成错误的那个字符算到错误的无符号数字符串中,再向下面识别单词时跳过这个字符,不回溯就能达到这个目的

{

fseek(fp,-1,1);

}*/

HandleError(JudgeStr,row);CurrentState=EndState;

}

}

break;

case 4:switch (symbol)

{

case DIGIT: p=p*10+d;CurrentState=6;break;

case MINUS: e=-1;CurrentState=5;break;

case PLUS: CurrentState=5;break;

default:

{

/* if (ch!=EOF)

{

fseek(fp,-1,1);

}*/

HandleError(JudgeStr,row);CurrentState=EndState;

}

}

break;

case 5:switch (symbol)

{

case DIGIT: p=p*10+d;CurrentState=6;break;

default:

{

/* if (ch!=EOF)

{

fseek(fp,-1,1);

}*/

HandleError(JudgeStr,row);CurrentState=EndState;

}//判断一个无符号数的最后一个字符应该都是多余读取的,所以为了防止引起后面再次判断下一无符号数时产生呑字符的现象,都应该回溯一个字符

}

break;

case 6:switch (symbol)

{

case DIGIT:p=p*10+d;break;

default:

{

if (ch!=EOF)

{

fseek(fp,-1,1);

}

FCON=w*pow(10,e*p-n);CurrentState=EndState;

JudgeStr[index-1]='\0';

InputWordType=UCON;

printf("(UCON,%f)对应%s\n",FCON,JudgeStr);

}break;

}

break;

}

return CurrentState;

}

////////////////////////////////无符号数判断过程中的字符类型判断程序

int GetChar (char ch)

{

if(isdigit(ch)) {d=ch-'0';return DIGIT;}

if (ch=='.') return POINT;

if (ch=='E'||ch=='e') return POWER;

if (ch=='+') return PLUS;

if (ch=='-') return MINUS;

return OTHER;

}

/////////////////////////////判断出错报错程序

int HandleError (char StrJudge[],int row)

{

printf ("Row: %d*****%s Error!\n",row,StrJudge); return 0;

}

/////////////////////////////////////语法分析程序

int SLRControl(FILE* fp)

{

while(Action[TopState][InputWordType][0] != 'A')

{

printf("栈顶状态:%i\n",TopState);

printf("扫描的单词类型:%i\n",InputWordType);

/*if ('A'==Action[State][WordType][0])

{

TopState=0;//正确后把栈顶状态置为初始化

StackPoint=0;//同理上面

memset(StateStack,-1,sizeof(StateStack));

printf("Right!");

return 1;

}*/

if (-1==TopState)

{

printf("状态栈栈顶指针错误!\n");

return 0;

}

if (' ' == Action[TopState][InputWordType][0])

{

printf("语法分析出错!\n");

return 0;

}

else if('s'==Action[TopState][InputWordType][0])

{

//TopState=atoi(&Action[TopState][InputWordType][1]);

Push(atoi(&Action[TopState][InputWordType][1]));

printf("执行压栈操作\n");

if (EOF!=fgetc(fp))

{

scanner(fp);

}

else

{

printf("语句不完整!\n");

return 0;

}

}

else if('r'==Action[TopState][InputWordType][0])

{

//do//用一个while循环为了可能遇到连续规约的情况,即从文件中扫描一个单词之后,可能连续规约多次

//{

int ProductionNum=atoi(&Action[TopState][InputWordType][1]);

int ProdutionLeft=0;

if (1==ProductionNum)

{

ProdutionLeft=E;//为下面差goto表提供列坐标

Pop(3);

printf("用产生式1 归约\n");

}

else if(2==ProductionNum)

{

ProdutionLeft=E;

Pop(3);

printf("用产生式2 归约\n");

}

else if(3==ProductionNum)

{

ProdutionLeft=E;

Pop(1);

printf("用产生式3 归约\n");

}

else if(4==ProductionNum)

{

ProdutionLeft=T;

Pop(3);

printf("用产生式4 归约\n");

}

else if(5==ProductionNum)

{

ProdutionLeft=T;

Pop(3);

printf("用产生式5 归约\n");

}

else if(6==ProductionNum)

{

ProdutionLeft=T;

Pop(1);

printf("用产生式6 归约\n");

}

else if(7==ProductionNum)

{

ProdutionLeft=F;

Pop(3);

printf("用产生式7 归约\n");

}

else if(8==ProductionNum)

{

ProdutionLeft=F;

Pop(1);

printf("用产生式8 归约\n");

}

else

{

printf("产生式编号超出范围!\n");

return 0;

}

Push(Goto[TopState][ProdutionLeft]);

// }while('r' == Action[TopState][InputWordType][0]) }

}

printf("栈顶状态:%i\n",TopState);

printf("扫描的单词类型:%i\n",InputWordType);

printf("语句正确!\n");

return 1;

}

/////////////////////////////////状态栈的压栈和出栈程序

int Push( int State )

{

if (Max==StackPoint)

{

printf("状态栈已满!");

return 0;

}

StateStack[StackPoint]=State;

StackPoint++;

TopState=State;//用topstate存储当前栈顶状态

return 1;

}

int Pop(int count) //内部要把处理完的数组的顶部的值赋给topstate

{

StackPoint=StackPoint-count;

if (StackPoint<0)

{

printf("状态栈指针不能为负值!");

return 0;

}

TopState=StateStack[StackPoint-1];

return 1;

}

/////////////////////////////////主程序

int main(int argc, char* argv[])

{

printf("Please input the complete path of the file you want to compile:\n");

//char c;

char pStr[20];

scanf("%s",pStr);

//printf("%s hahah",pStr);

FILE *p=fopen(pStr,"r");

//ch=fgetc(p);

if(ch=fgetc(p)==EOF)//不管小括号内的判断是否成功,p指针都会向后移一个位置,判断不成功,ch中存的字符不变

{

printf("The file is null.\n");

return 0;

}

// printf("第一个字母是:%c\n",ch);

TopState=0;

StackPoint=0;

memset(StateStack,-1,sizeof(StateStack));

scanner(p);

SLRControl(p);

//fseek(p,-1,1);

/*do

{

scanner(p);

}while(ch=fgetc(p)!=EOF);*/

fclose(p);

return 0;

}

六、测试用例及运行结果分析

测试用例1:

1.5E-2*(100+

2.5) #

运行结果1:

测试用例2:

1.5E-2*(100+

2.5+abc) #

运行结果2:

结果分析:构造slr(1)表时,没有添加标识符这一项,所以当时别到标识符时,语法分析会出错。

编译原理课程设计-词法语法分析器

编译原理课程设计Course Design of Compiling (课程代码3273526) 半期题目:词法和语法分析器 实验学期:大三第二学期 学生班级:2014级软件四班 学生学号:2014112218 学生姓名:何华均 任课教师:丁光耀 信息科学与技术学院 2017.6

课程设计1-C语言词法分析器 1.题目 C语言词法分析 2.内容 选一个能正常运行的c语言程序,以该程序出现的字符作为单词符号集,不用处理c语言的所有单词符号。 将解析到的单词符号对应的二元组输出到文件中保存 可以将扫描缓冲区与输入缓冲区合成一个缓冲区,一次性输入源程序后就可以进行预处理了 3.设计目的 掌握词法分析算法,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解 4.设计环境(电脑语言环境) 语言环境:C语言 CPU:i7HQ6700 内存:8G 5.概要设计(单词符号表,状态转换图) 5.1词法分析器的结构 词法分析程序的功能:

输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 词法分析程序可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词. 为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序: 1) ch 存放最新读进的源程序字符 2) strToken 存放构成单词符号的字符串 3) Buffer 字符缓冲区 4)struct keyType 存放保留字的符号和种别 5.2待分析的简单词法 (1)保留字 break、case、char、const、int、do、while… (2)运算符和界符 = 、+、-、* 、/、%、,、;、(、)、?、# 5.3各种单词符号对应的种别码

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

编译技术 班级网络0802 学号3080610052姓名叶晨舟 指导老师朱玉全2011年 7 月 4 日

一、目的 编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 二、任务及要求 基本要求: 1.词法分析器产生下述小语言的单词序列 这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表: 单词符号种别编码助记符内码值 DIM IF DO STOP END 标识符 常数(整)= + * ** , ( )1 2 3 4 5 6 7 8 9 10 11 12 13 14 $DIM $IF $DO $STOP $END $ID $INT $ASSIGN $PLUS $STAR $POWER $COMMA $LPAR $RPAR - - - - - - 内部字符串 标准二进形式 - - - - - - 对于这个小语言,有几点重要的限制: 首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的: IF(5)=x 其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。 再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为

词法分析程序设计与实现

` 实验一词法分析程序设计与实现 一、实验目的及容 调试并完成一个词法分析程序,加深对词法分析原理的理解。 二、实验原理(状态转换图) 1、C语言子集 (1)关键字: begin if then while do end 所有关键字都是小写。 (2)运算符和界符: := + – * / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter| digit)* NUM=digit digit * (4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。 2、各种单词符号对应的种别码 文档Word

` 3、词法分析程序的功能 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 二、软件平台及工具 PC机以及VISUAL C++6.0软件。 三、实验方法、步骤(或:程序代码或操作过程)(1)程序代码: #include #include #include char prog[80],token[8]; char ch; int syn,p,m=0,n,row,sum=0; char *rwtab[6]={egin,if,hen,while,do,end}; void scaner() { for(n=0;n<8;n++) token[n]=NULL; ch=prog[p++]; while(ch==' ') { ch=prog[p]; p++; } if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) 文档Word ` {

词法分析器的实现与设计

题目:词法分析器的设计与实现 一、引言................................ 错误!未定义书签。 二、词法分析器的设计 (3) 2.1词的内部定义 (3) 2.2词法分析器的任务及功能 (3) 3 2.2.2 功能: (4) 2.3单词符号对应的种别码: (4) 三、词法分析器的实现 (5) 3.1主程序示意图: (5) 3.2函数定义说明 (6) 3.3程序设计实现及功能说明 (6) 错误!未定义书签。 7 7 四、词法分析程序的C语言源代码: (7) 五、结果分析: (12) 摘要:词法分析是中文信息处理中的一项基础性工作。词法分析结果的好坏将直接影响中文信息处理上层应用的效果。通过权威的评测和实际应用表明,IRLAS是一个高精度、高质量的、高可靠性的词法分析系统。众所周知,切分歧义和未登录词识别是中文分词中的两大难点。理解词法分析在编译程序中的作用,加深对有穷自动机模型的理解,掌握词法分析程序的实

现方法和技术,用c语言对一个简单语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。Abstract:lexical analysis is a basic task in Chinese information processing. The results of lexical analysis will directly affect the effectiveness of the application of Chinese information processing. The evaluation and practical application show that IRLAS is a high precision, high quality and high reliability lexical analysis system. It is well known that segmentation ambiguity and unknown word recognition are the two major difficulties in Chinese word segmentation. The understanding of lexical analyse the program at compile, deepen of finite automata model for understanding, master lexical analysis program implementation method and technology, using C language subset of a simple language compilation of a scanned again compiler, to deepen to compile the principle solution, master compiler implementation method and technology. 关键词:词法分析器?扫描器?单词符号?预处理 Keywords: lexical analyzer word symbol pretreatment scanner 一、引言 运用C语言设计词法分析器,由指定文件读入预分析的源程序,经过词法分析器的分析,将结果写入指定文件。本程序是在Visual?Studio环境下,使用C语言作为开发工具。基于实验任务

TEST语言 -语法分析,词法分析实验报告

编译原理实验报告 实验名称:分析调试语义分析程序 TEST抽象机模拟器完整程序 保证能用!!!!! 一、实验目的 通过分析调试TEST语言的语义分析和中间代码生成程序,加深对语法制导翻译思想的理解,掌握将语法分析所识别的语法范畴变换为中间代码的语义翻译方法。 二、实验设计 程序流程图

extern int TESTScan(FILE *fin,FILE *fout); FILE *fin,*fout; //用于指定输入输出文件的指针 int main() { char szFinName[300]; char szFoutName[300]; printf("请输入源程序文件名(包括路径):"); scanf("%s",szFinName); printf("请输入词法分析输出文件名(包括路径):"); scanf("%s",szFoutName); if( (fin = fopen(szFinName,"r")) == NULL) { printf("\n打开词法分析输入文件出错!\n"); return 0; } if( (fout = fopen(szFoutName,"w")) == NULL) { printf("\n创建词法分析输出文件出错!\n"); return 0; } int es = TESTScan(fin,fout); fclose(fin); fclose(fout); if(es > 0) printf("词法分析有错,编译停止!共有%d个错误!\n",es); else if(es == 0) { printf("词法分析成功!\n"); int es = 0;

编译原理词法分析和语法分析报告 代码(C语言版)

词法分析 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 3.1 主程序示意图: 扫描子程序主要部分流程图 其他

词法分析程序的C语言程序源代码: // 词法分析函数: void scan() // 数据传递: 形参fp接收指向文本文件头的文件指针; // 全局变量buffer与line对应保存源文件字符及其行号,char_num保存字符总数。 void scan() { char ch; int flag,j=0,i=-1; while(!feof(fp1)) { ch=fgetc(fp1); flag=judge(ch); printf("%c",ch);//显示打开的文件 if(flag==1||flag==2||flag==3) {i++;buffer[i]=ch;line[i]=row;} else if(flag==4) {i++;buffer[i]='?';line[i]=row;} else if(flag==5) {i++;buffer[i]='~';row++;} else if(flag==7) continue; else cout<<"\n请注意,第"<

CMinus词法分析和语法分析设计编译器编译原理课程设计报告书

编译原理课程设计报告 课题名称:C- Minus词法分析和语法分析设计 提交文档学生姓名:X X X 提交文档学生学号:XXXXXXXXXX 同组成员名单:X X X 指导教师姓名:X X 指导教师评阅成绩: 指导教师评阅意见: . . 提交报告时间:2015年6月10日

1.课程设计目标 实验建立C-编译器。只含有扫描程序(scanner)和语法分析(parser)部分。 2.分析与设计 C-编译器设计的整体框架,本实验实现扫描处理和语法分析程序(图中粗黑部分)。 2.1 、扫描程序scanner部分 2.1.1系统设计思想 设计思想:根据DFA图用switch-case结构实现状态转换。 惯用词法:

①语言的关键字:else if int return void while ②专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */ ③其他标记是ID和NUM,通过下列正则表达式定义: ID = letter letter* NUM = digit digit* letter = a|..|z|A|..|Z digit = 0|..|9 大写和小写字母是有区别的 ④空格由空白、换行符和制表符组成。空格通常被忽略,除了它必须分开ID、NUM 关键字。 ⑤注释用通常的C语言符号/ * . . . * /围起来。注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。注释不能嵌套 scanner的DFA

说明:当输入的字符使DFA到达接受状态的时候,则可以确定一个单词了。初始状态设置为START,当需要得到下一个token时,取得次token的第一个字符,并且按照DFA与对此字符的类型分析,转换状态。重复此步骤,直到DONE为止,输出token类型。当字符为“/”时,状态转换为SLAH再判断下一个字符,如果为“*”则继续转到INCOMMENT,最后以“*”时转到ENDCOMMENT状态,表明是注释,如果其他的则是字符停滞于当前字符,并且输出“/”。 2.1.2程序流程图

实验1-3 《编译原理》词法分析程序设计方案

实验1-3 《编译原理》S语言词法分析程序设计方案 一、实验目的 了解词法分析程序的两种设计方法之一:根据状态转换图直接编程的方式; 二、实验内容 1.根据状态转换图直接编程 编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。在此,词法分析程序作为单独的一遍,如下图所示。 具体任务有: (1)组织源程序的输入 (2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件 (3)删除注释、空格和无用符号 (4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。将错误信息输出到屏幕上。 (5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。 标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址 注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。 常量表结构:常量名,常量值 三、实验要求 1.能对任何S语言源程序进行分析 在运行词法分析程序时,应该用问答形式输入要被分析的S源语言程序的文件名,然后对该程序完成词法分析任务。 2.能检查并处理某些词法分析错误 词法分析程序能给出的错误信息包括:总的出错个数,每个错误所在的行号,错误的编号及错误信息。 本实验要求处理以下两种错误(编号分别为1,2): 1:非法字符:单词表中不存在的字符处理为非法字符,处理方式是删除该字符,给出错误信息,“某某字符非法”。 2:源程序文件结束而注释未结束。注释格式为:/* …… */ 四、保留字和特殊符号表

C++实现词法分析器

#include #include using namespace std; char inchar[80], token[8]; char character; int zbbm, p, m = 0, n, row, sum = 0; char *blz[6] = { "while", "if", "else", "switch", "case" }; void input() { for (n = 0; n<8; n++) token[n] = NULL; character = inchar[p++]; while (character == ' ') { character = inchar[p]; p++; } if ((character >= 'a'&&character <= 'z') || (character >= 'A'&&character <= 'Z')) { m = 0; while ((character >= '0'&&character <= '9') || (character >= 'a'&&character <= 'z') || (character >= 'A'&&character <= 'Z')) { token[m++] = character; character = inchar[p++]; } token[m++] = '\0'; p--; zbbm = 6; for (n = 0; n<5; n++) if (strcmp(token, blz[n]) == 0) { zbbm = n + 1; break; } } else if ((character >= '0'&&character <= '9')) { { sum = 0; while ((character >= '0'&&character <= '9')) { sum = sum * 10 + character - '0'; character = inchar[p++]; } } p--; zbbm = 7; if (sum>32767) zbbm = -1; } else switch (character) { case'<':m = 0; token[m++] = character; character = inchar[p++]; if (character == '=') { zbbm = 11; token[m++] = character; }

编译原理课程设计-词法分析器(附含源代码)

编译原理-词法分析器的设计 一.设计说明及设计要求 一般来说,编译程序的整个过程可以划分为五个阶段:词法分析、语法分析、中间代码生成、优化和目标代码生成。本课程设计即为词法分析阶段。词法分析阶段是编译过程的第一个阶段。这个阶段的任务是从左到右一个字符一个字符地读入源程序,对构成源程序的字符流进行扫描和分解,从而识别出一个个单词(也称单词符号或符号)。如保留字(关键字或基本字)、标志符、常数、算符和界符等等。 二.设计中相关关键字说明 1.基本字:也称关键字,如C语言中的 if , else , while , do ,for,case,break, return 等。 2.标志符:用来表示各种名字,如常量名、变量名和过程名等。 3.常数:各种类型的常数,如12,6.88,和“ABC” 等。 4.运算符:如 + ,- , * , / ,%, < , > ,<= , >= 等。5.界符,如逗点,冒号,分号,括号,# ,〈〈,〉〉等。 三、程序分析 词法分析是编译的第一个阶段,它的主要任务是从左到右逐个字符地对源 程序进行 扫描,产生一个个单词序列,用以语法分析。词法分析工作可以是独立的一遍,把字符流的源程序变为单词序列,输出在一个中间文件上,这个文件做为语法分析程序的输入而继续编译过程。然而,更一般的情况,常将

词法分析程序设计成一个子程序,每当语法分析程序需要一个单词时,则 调用该子程序。词法分析程序每得到一次调用,便从源程序文件中读入一 些字符,直到识别出一个单词,或说直到下一个单词的第一个字符为止。 四、模块设计 下面是程序的流程图 五、程序介绍 在程序当前目录里建立一个文本文档,取名为infile.txt,所有需要分析的程序都写在此文本文档里,程序的结尾必须以“@”标志符结束。程序结果输出在同一个目录下,文件名为outfile.txt,此文件为自动生成。本程序所输出的单词符号采用以下二元式表示:(单词种别,单词自身的值)如程序输出结果(57,"#")(33,"include")(52,"<")(33,"iostream") 等。 程序的功能:(1)能识别C语言中所有关键字(共32个)(单词种别分别为1 — 32 ,详情见程序代码相关部分,下同) (2)能识别C语言中自定义的标示符(单词种别为 33) (3)能识别C语言中的常数(单词种别为0) (4)能识别C语言中几乎所有运算符(单词种别分别为41 — 54) (5)能识别C语言中绝大多数界符(单词种别分别为 55 — 66)六、运行结果 输入文件infile.txt 运行结果(输出文件 outfile.txt)

实验一、词法分析器(含源代码)

词法分析器实验报告 一、实验目的及要求 本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。 运行环境: 硬件:windows xp 软件:visual c++6.0 二、实验步骤 1.查询资料,了解词法分析器的工作过程与原理。 2.分析题目,整理出基本设计思路。 3.实践编码,将设计思想转换用c语言编码实现,编译运行。 4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。 三、实验内容 本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。标识符、常数是在分析过程中不断形成的。 对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。 输出形式例如:void $关键字

流程图 、程序 流程图: 开始 输入源文件路径 路径是否有 效 是初始化文件指针 否 将字符加入字符数 组Word[] 是空格,空白或换 行吗 是字母吗是数字吗否否是界符吗否打开源文件 跳过该字符 是是 文件结束? 否 将字符加入字符数 组Word[] 否 将字符加入字符数组Word[] 是 指向下一字符识别指针内容 指向下一字符 是字母惑数字 吗 是 将word 与关键字表key 进行匹 配 否匹配?是输出word 为关键字 输出word 为普通标示符 否将字符加入字符数组Word[] 指向下一字符输出word 为常数 识别指针内容 回退 是数字吗 是 否输出word 为界符 指向下一字符 结束 是输出Word 内容为不可识别 将字符加入字符数组Word[]

编译原理课程设计(词法分析,语法分析,语义分析,代码生成)

#include #include #include #include #include #include using namespace std; /*********************下面是一些重要数据结构的声明***************************/ struct token//词法token结构体 { int code;//编码 int num;//递增编号 token *next; }; token *token_head,*token_tail;//token队列 struct str//词法string结构体 { int num;//编号 string word;//字符串内容 str *next; }; str *string_head,*string_tail;//string队列 struct ivan//语法产生式结构体 { char left;//产生式的左部 string right;//产生式的右部 int len;//产生式右部的长度 }; ivan css[20];//语法20个产生式 struct pank//语法action表结构体 { char sr;//移进或归约 int state;//转到的状态编号 }; pank action[46][18];//action表 int go_to[46][11];//语法go_to表 struct ike//语法分析栈结构体,双链 { ike *pre; int num;//状态 int word;//符号编码 ike *next;

编译器的词法分析器

一.实验目的 ●了解编译器的词法分析器的作用。其作用是源程序转化为便于编译程序其余部分进行处 理的内部格式。 ●了解词法分析器的任务。识别出源程序中的各个基本语法单位;删除无用的空白字符, 回车以及其他与输入介质相关的非实质性的字符,以及注释等。 一.实验说明 ●词法分析程序:词法分析程序完成的是编译第一阶段的工作。词法分析工作可以是独立 的一遍,把字符流的源程序变为单词序列,输出在一个中间文件上,这个文件做为语法分析程序的输入而继续编译过程。然而,更一般的情况,是将词法分析程序设计成一个子程序,每当语法分析程序需要一个单词时,则调用该子程序。词法分析程序每得到一次调用,便从源程序文件中读入一些字符,直到识别出一个单词,或说直到下一单词的第一个字符为止。 ●词法分析程序的主要功能是从字符流的源程序中识别单词,它要从左至右逐个字符地扫 描源程序,因此它还可完成其它一些任务。比如,滤掉源程序中的注释和空白(由空格,制表或回车换行字符引起的空白);又比如,为了使编译程序能将发现的错误信息与源程序的出错位置联系起来,词法分析程序负责记录新读入的字符行的行号,以便行号与出错信息相联;再有,在支持宏处理功能的源语言中,可以由词法分析程序完成其预处理等等。 ●以下是五种单词符号: - 保留字,关键字 - 标识符 - 常数(量) - 运算符 - 界符 ●词法分析程序所输出的单词符号常常采用以下二元式表示:(单词种别,单词自身的值)。 单词的种别是语法分析需要的信息,而单词自身的值则是编译其它阶段需要的信息。比如在PASCAL的语句const i=25, yes=1;中的单词25和1的种别都是常数,常数的值25和1对于代码生成来说,是必不可少的。有时,对某些单词来说,不仅仅需要它的值,还需要其它一些信息以便编译的进行。比如,对于标识符来说,还需要记载它的类别、层次还有其它属性,如果这些属性统统收集在符号表中,那么可以将单词的二元式表示设计成如下形式(标识符,指向该标识符所在符号表中位置的指针),如上述语句中

编译原理词法分析和语法分析报告+代码(C语言版)

词法分析 一、实验目的 设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 二、实验要求 2.1 待分析的简单的词法 (1)关键字: begin if then while do end 所有的关键字都是小写。 (2)运算符和界符 : = + - * / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义: ID = letter (letter | digit)* NUM = digit digit* (4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。 2.2 各种单词符号对应的种别码: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列: (1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)…… 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1 主程序示意图: 主程序示意图如图3-1所示。其中初始包括以下两个方面: ⑴关键字表的初值。 关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下: Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,}; 图3-1 (2)程序中需要用到的主要变量为syn,token和sum 3.2 扫描子程序的算法思想: 首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。扫描子程序主要部分流程如图3-2所示。

词法分析程序的设计与实现

实验一词法分析程序的设计与实现 一、实验内容 【实验目的和要求】 设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解。 【实验内容】 通过对PL/0词法分析程序(GETSYM)的分析,并在此基础上按照附录A中给出的PL/0语言的语法描述,编写一个PL/0语言的词法分析程序。此程序应具有如下功能:输入为字符串(待进行词法分析的源程序),输出为单词串,即由(单词、类别)所组成的二元组序列。 有一定检查错误的能力,例如发现2A这类不能作为单词的字符串。 【实验环境】 Windows PC机,任何语言。 【提交内容】 提交实验报告,报告内容如下: 目的要求、算法描述、程序结构、主要变量名说明、程序清单、调试情况、设计技巧、心得体会。 提交源程序和可执行文件。 【学时】 4课时。 二、实验说明 词法分析程序的任务就是扫描源程序,依据词法规则识别单词并报告构词错误信息。通常将单词分为5种类型。

1)基本字:也叫关键字、保留字,是程序设计语言用来表示特定语法含义的一种标识符,如if、begin等。 2)运算符:如+、-、*、/、:=、>、<等。 3)标识符:用户定义的变量名、常数名、函数名等。不同的高级程序设计语言对关键字是否可以作为普通标识符有不同的要求,有的语言允许程序员使用关键字作为普通标识符,有的程序设计语言则不允许程序员将关键字用着普通标识符(如C/C++、Pascal等都不允许)。在允许程序员将关键字用作普通标识符的程序设计语言的编译器中,编译器必须具备能够区分一个标识符到底是关键字还是普通标识符的功能。 4)常数:如23、6等。 5)界符:如“,”、“;”、“(”、“)”、“.”等。 注意事项 ●空格的作用仅仅是将一个个单词分割开来,源程序中的空格不具备别的语法意义,在语法分析及其后续阶段都没有任何作用,因此,词法分析的另一个工作是过滤空格。 ●注释对整个源程序的编译也没有任何语法意义,只是为了便于阅读和交流,因此,有的编译程序的词法分析程序也负责过滤注释。 ●输出的单词符号采用[单词类别,单词自身值]的二元组形式来表示。 ●为了使扫描程序尽可能的高效,在进行词法分析程序的设计和实现时还需十分注意扫描程序结构的实际细节问题。 ●用于间隔单词的空格和我们通常所说的键盘上的空格是不同的,这里的空格指的是所有能引起一个单词结束的字符,它们包括空格、制表或回车换行符。 ●a*(b+c)这样的没有空格间隔的情况时要正确地识别出所有的单词 ●123ab这样的字符串时,一般字符串的首字符必须为字母,不要将123识别为数字,将ab识别为标识符 转换图说明

编译原理课程设计报告C语言词法与语法分析器的实现

编译原理课程设计报告 课题名称:编译原理课程设计 C-语言词法与语法分析器的实现

C-词法与语法分析器的实现 1.课程设计目标 (1)题目实用性 C-语言拥有一个完整语言的基本属性,通过编写C-语言的词法分析和语法分析,对于理解编译原理的相关理论和知识有很大的作用。通过编写C-语言词法和语法分析程序,能够对编译原理的相关知识:正则表达式、有限自动机、语法分析等有一个比较清晰的了解和掌握。(2)C-语言的词法说明 ①语言的关键字: else if int return void while 所有的关键字都是保留字,并且必须是小写。 ②专用符号: + - * / < <= > >= == != = ; , ( ) [ ] { } /* */ ③其他标记是ID和NUM,通过下列正则表达式定义: ID = letter letter* NUM = digit digit* letter = a|..|z|A|..|Z digit = 0|..|9 注:ID表示标识符,NUM表示数字,letter表示一个字母,digit表示一个数字。 小写和大写字母是有区别的。 ④空格由空白、换行符和制表符组成。空格通常被忽略。 ⑤注释用通常的c语言符号/ * . . . * /围起来。注释可以放在任何空白出现的位置(即注释不能放在标记)上,且可以超过一行。注释不能嵌套。

(3)程序设计目标 能够对一个程序正确的进行词法及语法分析。 2.分析与设计 (1)设计思想 a.词法分析 词法分析的实现主要利用有穷自动机理论。有穷自动机可用作描述在输入串中识别模式的过程,因此也能用作构造扫描程序。通过有穷自动机理论能够容易的设计出词法分析器。b.语法分析 语法分析采用递归下降分析。递归下降法是语法分析中最易懂的一种方法。它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。其中子程序的结构与产生式结构几乎是一致的。 (2)程序流程图 程序主流程图: 词法分析: 语法分析:

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

编译原理实验报告

实验一 一、实验名称:词法分析器的设计 二、实验目的: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 #include #include 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]);

编译原理实验-词法分析器的设计与实现.docx

南华大学 计算机科学与技术学院实验报告 (2018~2019学年度第二学期) 课程名称编译原理 实验名称词法分析器的设计与 实现 姓名学号 专业班级 地点教师

1.实验目的及要求 实验目的 加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。 实验要求 1.对单词的构词规则有明确的定义; 2.编写的分析程序能够正确识别源程序中的单词符号; 3.识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护 符号表; 4.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误 提示,保证顺利完成整个源程序的词法分析; 2.实验步骤 1.词法分析规则 <标识符>::=<字母>|<标识符><字母>|<标识符><数字> <常数>::=<数字>|<数字序列><数字> <数字序列>::=<数字序列><数字>|<数字>|<.> <字母>::=a|b|c|……|x|y|z <数字>::=0|1|2|3|4|5|6|7|8|9 <运算符>::=<关系运算符>|<算术运算符>|<逻辑运算符>|<位运算符>|<赋值运算符> <算数运算符>::=+|-|*|/|...|-- <关系运算符>::=<|>|!=|>=|<=|== <逻辑运算符>::=&&| || |! <位运算符>::=&| | |! <赋值运算符>::==|+=|-=|/=|*= <分界符>::=,|;|(|)|{|}|:| // |/**/ <保留字>::=main|if|else|while|do|for|...|void

编译原理实验 词法分析&语法分析程序

编译原理实验 词 法 分 析 程 序

实验一:词法分析程序 1、实验目的 从左至右逐个字符的对源程序进行扫描,产生一个个单词符号,把字符串形式的源程序改造成单词符号形式的中间程序。 2、实验内容 表C语言子集的单词符号及内码值 单词符号种别编码助记符内码值 while 1 while -- if 2 if -- else 3 else -- switch 4 switch -- case 5 case -- 标识符 6 id id在符号表中的位置 常数7 num num在常数表中的位置 + 8 + -- - 9 - -- * 10 * -- <= 11 relop LE < 11 relop LT == 11 relop LQ = 12 = -- ; 13 ; -- 输入源程序如下 if a==1 a=a+1; else a=a+2; 输出对应的单词符号形式的中间程序 3、实验过程 实验上机程序如下: #include "stdio.h" #include "string.h" int i,j,k; char s ,a[20],token[20]; int letter() { if((s>=97)&&(s<=122))return 1; else return 0; } int Digit() {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() { 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 you source program,end('#'):\n"); i=0; do { i=i+1; scanf("%c",&a[i]); }while(a[i]!='#'); i=1; memset(token,0,sizeof(char)*10); j=0; get(); while(s!='#') { if(s==' '||s==10||s==13) get(); else { switch(s)

相关文档
最新文档