西安交大编译原理语法分析器实验报告

编译原理课内实验报告

学生姓名    石磊

专业/班级          计算机26

学      2120505140

所在学院    电信学院  

提交日期    20##-12-2 

一:实验目的:

1.强化对系统软件综合工程实现能力的训练;

2.加强对语法分析原理、方法和基本实现技术的理解;

二:实验内容

1. 用C语言或者其他的高级语言作为宿主语言完成C0语言的词法分析器的设计和实现。

2. 针对if语句的文法编写一个递归下降分析程序,输出结果为抽象语法树。注意,if语句文法中的表达式E采用四则运算表达式的文法;抽象语法树的格式自行设计,如果需要降低难度的话,也可用具体语法树而不用抽象语法树作为输出。

三:实验功能描述

1. 编写C0语言的语法分析器的源程序并调试通过。其中语法分析程序既可以自己手动去完成,也可以利用YACC自动生成。

2. 通过测试程序的验收;

四:功能描述:

该语法分析器用yacc生成,针对if语句的文法编写的向下递归程序,输出结果为语法树,实现了实验目标,达到了实验要求。

五:实验程序代码

%{

#include <string.h>

#include <stdlib.h>

#include "yystype.h"

#include "y.tab.h"

#include "treedisp.h"

int yycount = 0;

extern YYSTYPE yylval;

#define NSYMS 20

struct symtab {

    char *name;

    double value;

} symtab[NSYMS];

struct symtab *symlook(char *s);

#define NRSVS 10

struct rsvtab {

    char *name;

    int id;

} rsvtab[NRSVS] = {

    {"if", IF},

    {"else", ELSE},

    {"while", WHILE},

    {"for", FOR},

    {"other", OTHER},

    {"var", VAR}

};

int rsvlook(char *s);

%}

digit [0-9]

integer {digit}+

eq "=="

pl "+"

mi "-"

mu "*"

di "/"

sc ";"

as "="

identifier [a-zA-Z][a-zA-Z0-9_]*

delim [ \n\t]

ws {delim}+

other "other"

%%

{integer} {

        //yylval = atoi(yytext);

        rec_token("INTEGER");

        return INTEGER;

}

{identifier} {

   

        if (rsvlook(yytext) != 0) {

            rec_token("RESERVED");

            return rsvlook(yytext);

        }

        rec_token("SYMBOL");

        return SYMBOL;

{eq} { rec_token("OPR"); return EQ; }

{pl} { rec_token("OPR"); return PL; }

{mi} { rec_token("OPR"); return MI; }

{mu} { rec_token("OPR"); return MU; }

{di} { rec_token("OPR"); return DI; }

{as} { rec_token("OPR"); return ASSIGN; }

{sc} { rec_token("SC"); return SC; }

\(   { rec_token("LB"); return LB; }

\)   { rec_token("RB"); return RB; }

{ws} ;

.  {

        printf("error: %s\n", yytext);

        yyerror("Illigal input.");

}

%%

char *buffer[20];

void rec_token(char *s) {

    yylval.token_id = ++yycount;

    yylval.text = strdup(yytext);

    sprintf(buffer, "%s(%s)", s, yytext);

    name_node(yycount, buffer);

}

int rsvlook(char *s) {

    struct rsvtab *sp;

    for (sp = rsvtab; sp < &rsvtab[NRSVS]; ++sp) {

        if (sp->name && !strcmp(sp->name, s))

            return sp->id;

    }

    return 0;

}

struct symtab *symlook(char *s) {

    struct symtab *sp;

    for (sp = symtab; sp < &symtab[NSYMS]; ++sp) {

        if (sp->name && !strcmp(sp->name, s))

            return sp;

        if (!sp->name) {

            sp->name = strdup(s);

            return sp;

        }

    }

    yyerror("Too many symbols.");

    exit(1);

}

测试代码:

if (1+1)

    if (2*3+5)

        if (3*4+9)

            if (5*3+2)

                other;

            else

                other;

        else

            other;

    else

        other;

else

b=2*3+5;

测试结果:

stseq

 ├── statement

 │   └── mifst

 │       ├── RESERVED(if)

 │       ├── LB(()

 │       ├── exp

 │       │   └── term

 │       │       └── factor

 │       │           └── INTEGER(1)

 │       ├── RB())

 │       ├── mifst

 │       │   ├── RESERVED(if)

 │       │   ├── LB(()

 │       │   ├── exp

 │       │   │   ├── term

 │       │   │   │   ├── term

 │       │   │   │   │   └── factor

 │       │   │   │   │       └── INTEGER(2)

 │       │   │   │   ├── OPR(*)

 │       │   │   │   └── factor

 │       │   │   │       └── INTEGER(3)

 │       │   │   ├── OPR(+)

 │       │   │   └── exp

 │       │   │       └── term

 │       │   │           └── factor

 │       │   │               └── INTEGER(5)

 │       │   ├── RB())

 │       │   ├── mifst

 │       │   │   ├── RESERVED(if)

 │       │   │   ├── LB(()

 │       │   │   ├── exp

 │       │   │   │   ├── term

 │       │   │   │   │   ├── term

 │       │   │   │   │   │   └── factor

 │       │   │   │   │   │       └── INTEGER(3)

 │       │   │   │   │   ├── OPR(*)

 │       │   │   │   │   └── factor

 │       │   │   │   │       └── INTEGER(4)

 │       │   │   │   ├── OPR(+)

 │       │   │   │   └── exp

 │       │   │   │       └── term

 │       │   │   │           └── factor

 │       │   │   │               └── INTEGER(9)

 │       │   │   ├── RB())

 │       │   │   ├── mifst

 │       │   │   │   ├── RESERVED(if)

 │       │   │   │   ├── LB(()

 │       │   │   │   ├── exp

 │       │   │   │   │   ├── term

 │       │   │   │   │   │   ├── term

 │       │   │   │   │   │   │   └── factor

 │       │   │   │   │   │   │       └── INTEGER(5)

 │       │   │   │   │   │   ├── OPR(*)

 │       │   │   │   │   │   └── factor

 │       │   │   │   │   │       └── INTEGER(3)

 │       │   │   │   │   ├── OPR(+)

 │       │   │   │   │   └── exp

 │       │   │   │   │       └── term

 │       │   │   │   │           └── factor

 │       │   │   │   │               └── INTEGER(2)

 │       │   │   │   ├── RB())

 │       │   │   │   ├── statement

 │       │   │   │   │   ├── RESERVED(other)

 │       │   │   │   │   └── SC(;)

 │       │   │   │   ├── RESERVED(else)

 │       │   │   │   └── statement

 │       │   │   │       ├── RESERVED(other)

 │       │   │   │       └── SC(;)

 │       │   │   ├── RESERVED(else)

 │       │   │   └── statement

 │       │   │       ├── RESERVED(other)

 │       │   │       └── SC(;)

 │       │   ├── RESERVED(else)

 │       │   └── statement

 │       │       ├── RESERVED(other)

 │       │       └── SC(;)

 │       ├── RESERVED(else)

 │       └── mifst

 │           ├── SYMBOL(b)

 │           ├── OPR(=)

 │           ├── exp

 │           │   ├── term

 │           │   │   ├── term

 │           │   │   │   └── factor

 │           │   │   │       └── INTEGER(2)

 │           │   │   ├── OPR(*)

 │           │   │   └── factor

 │           │   │       └── INTEGER(3)

 │           │   ├── OPR(+)

 │           │   └── exp

 │           │       └── term

 │           │           └── factor

 │           │               └── INTEGER(5)

 │           └── SC(;)

 └── stseq

     └── (empty)


六:实验心得

在本次实验中,我耗费了大量时间来设计分析设计。用一天的时间来思考,用了两个多小时在纸上设计演算,编程总共用了七八个小时。基于上次语法分析的实验,终于利用flex设计出了语法分析器并成功输出语法分析树。实验中遇到的最大困难是无法输出语法树,经过在网上以及书本上等多种渠道的学习,最终得以解决问题。虽然耗费大量了时间,但我很开心,因为通过本次实验,我又掌握了不少知识,使自己的能力得到了极大的提升。

通过本次实验,更加明白在学习生活中,应该学会积极主动的自主探索,,只有这样,才能使自己的能力有所提升,才能真正掌握知识,将所学知识用于实践。

 

第二篇:C++词法分析器

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

一、实验目的

1.设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。

2.掌握在对程序设计语言的源程序扫描的过程中,将其分解后各类单词的语法分析方法。

二、实验要求:

1. 对给定的程序通过词法分析器弄够识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。而本程序则是通过对给定路径的文件的分析后以单词符号和文字提示显示。

2. 本程序自行规定:

(1)关键字"begin","end","if","then","else","while","write","read",

"do", "call","const","char","until","procedure","repeat"

(2)运算符:"+","-","*","/","="

(3)界符:"{","}","[","]",";",",",".","(",")",":"

(4)其他标记 如字符串,表示以字母开头的标识符。
(5)空格、回车、换行符跳过。

在屏幕上显示如下:
( 1 , 无符号整数)

( begin , 关键字 )

( if , 关键字 )

( +, 运算符 )

( ; , 界符 )
( a , 普通标识符 )

三、使用环境:
Window vista 下的 Visual Studio 2008;

四、实验步骤

1.查询资料,了解词法分析器的工作过程与原理。

2.分析题目,整理出基本设计思路。

3.实践编码,将设计思想转换用c语言编码实现,编译运行。

4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。

五、流程图

五、调试程序:

1.举例说明

文件位置:C:\TEST.txt

目标程序如下:

Int  main() 

  {

i=10;

j=100;

n=1;

sum=0;

mult=1;

while (i>0) {n=n+1;i=i-1;}

if (j>=50) then sum=sum+j; else {mult=mult*(j+1);sum=sum+i;}

if (i<=10) then sum=sum-i; else mult=mult+i/2;

if (i==j) then sum=sum-j; else mult=mult-j/2;

if (n>1) then n=n-1; else n=n+1;

if (n<2) then n=n+2; else n=n-2;

}

2.运行结果:

六、程序源代码:

#include <iostream>

#include<string>

using namespace std;

#define  MAX 22         

char ch =' ';

string key[15]={"begin","end","if","then","else","while","write","read",

"do", "call","const","char","until","procedure","repeat"};

int Iskey(string c){         //关键字判断

   int i;

   for(i=0;i<MAX;i++) {

      if(key[i].compare(c)==0) return 1;

       }

    return 0;

}

int IsLetter(char c) {        //判断是否为字母

    if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;

    else return 0;

}

int IsDigit(char c){          //判断是否为数字

     if(c>='0'&&c<='9') return 1;

     else return 0;

}

void analyse(FILE *fpin){

    string arr="";         

    while((ch=fgetc(fpin))!=EOF) {

            arr="";       

         if(ch==' '||ch=='\t'||ch=='\n'){}    

         else if(IsLetter(ch)){

                 while(IsLetter(ch)||IsDigit(ch)) {

                                if((ch<='Z')&&(ch>='A')) ch=ch+32;  

                             arr=arr+ch;

                    ch=fgetc(fpin);

                               }

                 fseek(fpin,-1L,SEEK_CUR);   

                 if (Iskey(arr)){cout<<arr<<"\t$关键字"<<endl;}    

                 else  cout<<arr<<"\t$普通标识符"<<endl;          

               }

     

            else if(IsDigit(ch)){

                  while(IsDigit(ch)||ch=='.'&&IsDigit(fgetc(fpin))){

                        arr=arr+ch;

                        ch=fgetc(fpin);

                       }

                  fseek(fpin,-1L,SEEK_CUR);

                  cout<<arr<<"\t$无符号实数"<<endl; 

             }

       else switch(ch){         

               case'+':

               case'-' :

               case'*' :

               case'=' :

               case'/' :cout<<ch<<"\t$运算符"<<endl;break;

               case'(' :

               case')' :

               case'[' :

               case']' :              

               case';' :

               case'.' :

               case',' :

               case'{' :

               case'}' :cout<<ch<<"\t$界符"<<endl;break;

               case':' :{ch=fgetc(fpin);

                        if(ch=='=') cout<<":="<<"\t$运算符"<<endl;

                        else {cout<<"="<<"\t$运算符"<<endl;;

                               fseek(fpin,-1L,SEEK_CUR);}

                        }break;

case'>' :{ch=fgetc(fpin);

                         if(ch=='=') cout<<">="<<"\t$运算符"<<endl;

                         if(ch=='>')cout<<">>"<<"\t$输入控制符"<<endl;

                         else {cout<<">"<<"\t$运算符"<<endl;

                             fseek(fpin,-1L,SEEK_CUR);}

                         }break;

               case'<' :{ch=fgetc(fpin);

                         if(ch=='=')cout<<"<="<<"\t$运算符"<<endl;

                         else if(ch=='<')cout<<"<<"<<"\t$输出控制符"<<endl;

                         else if(ch=='>') cout<<"<>"<<"\t$运算符"<<endl;

                         else{cout<<"<"<<"\t$运算符"<<endl;

                            fseek(fpin,-1L,SEEK_CUR);}

                        }break;

              default : cout<<ch<<"\t$无法识别字符"<<endl;

        }

    }

}

void main(){

   char in_fn[30];

   FILE * fpin;

   cout<<"请输入源文件名(包括路径和后缀名):";

   for(;;){

       cin>>in_fn;

       if((fpin=fopen(in_fn,"r"))!=NULL) break;

       else cout<<"文件路径错误!请输入源文件名(包括路径和后缀名):";

     }

   cout<<"\n********************分析如下*********************"<<endl;

   analyse(fpin);

   fclose(fpin);

   cout<<endl;

   cout<<"按任意键结束"<<endl;

   int a;

   cin>>a;

}

六、实验心得:

   通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,使用某种高级语言(例如C++语言)直接编写此法分析程序。另外,也让我重新熟悉了C++语言的相关内容,加深了对C++语言的用途的理解。在本次实验中,我纠正了一个一直以来的概念错误:main不是关键字,它定义为程序的入口,是主函数!在本实验中,虽然我把main初始化在关键字表

(字符指针类型数组)*Key[10]中,当与该数组中字符串进行比较时,若与main匹配成功,则返回2,若为其他关键字则返回1,以此来把main从关键字中区别出来。

在本实验中的关键字表只初始化了几个常用的关键字,还可继续扩充(只需扩大数组,向其中补充要添加的关键字)。

相关推荐