编译原理 实验二 语法分析

一、实验目的:

编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

二、实验要求:

利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

1. 待分析的简单语言的语法

用扩充的BNF表示如下:

(1)<程序)::=begin<语句串>end

(2)<语句串)::=<语句>|;<语句》

(3)<语句)::=<赋值语句》

(4)<赋值语句)::=ID:=(表达式)

(5)<表达式)::=<项)|+<项)|-<项》

(6)<项)::=<因子)|*<因子)|/<因子>

(7)<因子)::= IDI NUMI(<表达式>)

2.实验要求说明

输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“suc-cess”,否则输出“error”。

例如:

输入 begin a:=9;x:=2*3;b:=a+xend#

输出 success

输入 x:=a+b*c end #

输出 error

三、实验算法思想:

  

(1)主程序示意图如图C.3所示。

(2)递归下降分析程序示意图如图C.4所示。

(3)语句串分析过程示意图如图C.5所示。

(4) statement 语句分析函数流程如图C.6、 图C.7、图C.8、图C.9所示。

四、实验源代码:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

//函数申明

void match();          //匹配的方法

void Bparser();     //匹配begin

void Pre();           //对语法进行预处理

void statement();   //匹配语法声明

void expression();  //匹配运算符

void term();        //匹配*/运算符

void factor();      //匹配括号

char temp[500],test[500];

char ch;

char a;

const char *keyword[6]= {"begin","if","then","while","do","end"};   //存储保留字

int i=0,num,n,ednum=0,bnum=0,k=0;

//匹配的方法

void match() {

    ch=temp[i++];

    while(ch==' ') {

        ch=temp[i++];

    }

    if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')) {        //保留字与标识符判断

        n=0;

        num=10;

        a=ch;

        while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')) { //字符串数组复制

            test[n++]=ch;

            ch=temp[i++];

        }

        test[n++]='\0';

        for(n=0; n<6; n++) {

            if(strcmp(test,keyword[n])==0) {  //判断两个字符串是否一致

                num=n+1;

                printf("[%s,%d]\n",test,num);

                if(num==1) {

                    bnum=1;//begin存在

                }

                if(num==6) {

                    ednum=1;//end存在

                }

                break;

            }

        }

        i--;

        if(num==10) {

            ch=a;

            printf("[%c,%d]\n",ch,num);

        }

    }

    if(ch>='0'&&ch<='9') {    //数字判断

        num=11;

        printf("[%c,%d]\n",ch,num);

    } else {

        switch(ch) {    //运算符界符的判断

            case '#':

                num=0;printf("[%c,%d]\n",ch,num);break;

            case '+':

                num=13;printf("[%c,%d]\n",ch,num);break;

            case '-':

                num=14;printf("[%c,%d]\n",ch,num);break;

            case '*':

                num=15;printf("[%c,%d]\n",ch,num);break;

            case '/':

                num=16;printf("[%c,%d]\n",ch,num);break;

            case ':':

                ch=temp[i++];

                if(ch=='=') {

                    num=18;

                    printf("[:%c,%d]\n",ch,num);

                } else {

                    i--;

                    ch=temp[i];

                    num=17;

                    printf("[%c,%d]\n",ch,num);

                }

                break;

                

            case '<':

                ch=temp[i++];

                if(ch=='=') {

                    num=21;

                    printf("[<%c,%d]\n",ch,num);

                } else if(ch='>') {

                    num=22;

                    printf("[<%c,%d]\n",ch,num);

                } else {

                    i--;

                    ch=temp[i];

                    num=20;

                    printf("[%c,%d]\n",ch,num);

                }

                break;

            case '>':

                ch=temp[i++];

                if(ch=='=') {

                    num=24;

                    printf("[>%c,%d]\n",ch,num);

                } else {

                    i--;

                    ch=temp[i];

                    num=23;

                    printf("[%c,%d]\n",ch,num);

                }

                break;

            case '=':

                num=25;printf("[%c,%d]\n",ch,num);break;

            case ';':

                num=26;printf("[%c,%d]\n",ch,num);break;

            case '(':

                num=27;printf("[%c,%d]\n",ch,num);break;

            case ')':

                num=28;printf("[%c,%d]\n",ch,num);break;

        }

    }

}

//对语法进行预处理,当匹配到分号时,进行一次match匹配下一个字符

void Pre() {   

    statement();

    while(num==26) {

        match();

        statement();

    }

    return;

}

//匹配begin、end

void Bparser() {   

    if(num==1) { //begin

        match();

        Pre();

        if(num==6){ //end

            match();

            if(num==0 && k==0){

                printf("【Success】分析完成!\n");

            }

        }else if(num==0 && ednum!=1){

            printf("【error】缺失'end'\n");

            k=1;

        }

    }else{

        Pre();

        printf("【error】缺失'begin'\n");

    }

    return;

}

//匹配语法声明

void statement() {  

    if (num==10) {   

        match();

        if(num==18) { //为 :=

            match();

            expression();

        } else {

            printf("【error】缺失符号':='\n");

            k=1;

        }

    }else{

        printf("【error】'表达式错误'\n");

        k=1;

    }

    return;

}

//匹配+-运算符

void expression() {  

    term();

    while(num==13||num==14) {

        match();

        term();

    }

    return;

}

//匹配*/运算符

void term() {   

    factor();

    while(num==15||num==16) {

        match();

        factor();

    }

    return;

}

//为标识符或整常数时,读下一个单词符号

void factor() {  

    if(num==10||num==11) {

        match();

    } else if(num==27) {

        match();

        expression();

        if(num==28) {

            match();

        } else {

            printf(" 【error】缺失')' \n");

            k=1;

        }

    } else {

        printf("【error】'表达式错误'\n");

        k=1;

    }

    return;

}

int main() {

    printf("\t\n请输入程序,以#号结束:\n");

    ch=getchar();

    while(ch!='#') {

        temp[i]=ch;

        ch=getchar();

        i++;

    }

    temp[i]='#';

    i++;

    temp[i]='\0';

    i=0;

    match();

    Bparser();

}

五、实验结果:

(一)、

输入begin a:=9;x:=2*3;b:=a+x end #

输入x:=a+b*c  end #

  • 31
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值