第十二次作业——实验二-递归下降语法分析

一、实验目的:

 

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

 

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

 

 

 

二、实验原理

 

每个非终结符都对应一个子程序。

 

该子程序根据下一个输入符号(SELECT)来确定按照哪一个产生式进行处理,再根据该产生式的右端:

 

每遇到一个终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一个单词继续分析;不匹配,则进行出错处理

每遇到一个非终结符,则调用相应的子程序

 

 

三、实验要求说明

 

输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success,否则输出“error”,并指出语法错误的类型及位置。

 

例如:

 

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

 

输出success

 

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

 

输出end' error

 

 

 

四、实验步骤

 

      1.待分析的语言的语法(参考P90

 

      2.将其改为文法表示,至少包含

 

–语句

 

–条件

 

–表达式

 

3. 消除其左递归

 

4. 提取公共左因子

 

5. SELECT集计算

 

6. LL(1)文法判断

 

7. 递归下降分析程序

 

 完整实现代码:

#include <stdio.h>
#include <string.h>

#define gjword 13         //关键字个数

#define max 10           //标识符的最长长度

#define getchdo         if(-1==getch()) return -1;

char ch;                //读取的字符
char ch1[10];                //存放字符 
char id[max+1];          //传递标识符单词 
int num;                //传递数值 
int js, js2;             
char find[100];
char a[max+1];           //暂时存储符号
char word[gjword][max];    //保留字
int sym;                 //符号类型 

FILE* input;
void E();
void E1();
void T();
void T1();
void F();
void error();
 
int getch()
{
    if(js == js2)
    {
        if(feof(input))
        {
            printf("\n词法分析完毕!\n");
            return -1;
        }
        js2 = 0;
        js = 0;
        ch = ' ';
        while(ch != '\n')
        {
            if(fscanf(input, "%c", &ch) == EOF)
            {
                find[js2] = 0;
                break;
            }
//            printf("%c", ch);
            find[js2] = ch;
            js2++;
        }
        printf("\n");
    }
    ch = find[js];
    js++;
    return 0;
}
 
int getsym()
{
    int i, j, k;
    while(ch == ' ' || ch == '\n' )
    {
        getchdo;
    }
    if(ch >= 'a' && ch <= 'z')
    {
        k = 0;
        do
        {
            if(k < max)
            {
                a[k] = ch;
                k++;
            }
            getchdo;
        }while(ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9');
        a[k] = '\0';
        strcpy(id, a);
        i = 0;
        j = gjword-1;
        do
        {
            k = (i+j)/2;
            if(strcmp(id, word[k]) <= 0)
                j = k-1;
            if(strcmp(id, word[k]) >= 0)
                i = k+1;
        }while(i <= j);
 
        if(i-1 > j)
        {
//            printf("保留字 ('%s')\n", id);
            sym=i;
            strcpy(ch1, id); 
        }
        else
        {
//            printf("标识符 ('%s')\n", id);
            sym=10;
            strcpy(ch1, id); 
            k--; 
        }
    }
    else{
        if(ch >= '0' && ch <= '9')
        {
            k = 0;
            num = 0;
            do
            {
                num = num * 10 + ch - '0';
                k++;
                getchdo;
            }while(ch >= '0' && ch <= '9');
            k--;         
//            printf("整 数 ('%d')\n",num);
            sym=11; 
        }
        else
        {
            switch(ch){
                case ':':getchdo;
                        k++;
                        if(ch == '=')
                        {
                            sym=18; 
//                            printf("运算符 (':=')\n");
                            strcpy(ch1, ":="); 
                            getchdo;
                            break;
                        }
                        else
                        {
//                             printf("符号(':')\n");
                             sym=17;
                             ch1[0]=ch;
                             k--;
                             break; 
                        }
                case '<':getchdo;
                        k++;
                        if(ch == '=')
                        {
//                            printf("运算符 ('<=')\n");
                            sym=21;
                            strcpy(ch1, "<=");
                            getchdo;
                            break;
                        }
                        else if(ch == '>'){
                            sym=22;
                            strcpy(ch1, "<>");
                            break;
                        }
                        else
                        {
//                            printf("运算符 ('<')\n");
                            sym=20;
                            ch1[0]=ch;
                            k--;
                            break;
                        }
                case '>':getchdo;
                        k++;
                        if(ch == '=')
                        {
//                            printf("运算符 ('>=')\n");
                            sym=24;
                            strcpy(ch1, ">=");
                            getchdo;
                            break;
                        }
                        else
                        {
//                            printf("运算符 ('>')\n");
                            sym=23;
                            ch1[0]=ch;
                            k--;
                            break;
                        }
                case '+':
//                        printf("运算符 ('+')\n");
                            sym=13;
                            ch1[0]=ch;
                            getchdo;
                            break;
                case '-':
//                        printf("运算符 ('-')\n");
                            sym=14;
                            ch1[0]=ch;
                            getchdo;
                            break;
                case '*':
//                        printf("运算符 ('*')\n");
                            sym=15;
                            ch1[0]=ch;
                            getchdo;                            
                            break;
                case '/':
//                        printf("运算符 ('/')\n");
                            sym=16;
                            ch1[0]=ch;
                            getchdo;
                            break;
                case '=':
//                        printf("运算符 ('=')\n");
                            sym=25;
                            ch1[0]=ch;
                            getchdo;
                            break;
                case ';':
//                        printf("分界符 (';')\n");
                            sym=26;
                            ch1[0]=ch;
                            getchdo;
                            break;
                case '(': 
//                        printf("分界符 ('(')\n");
                            sym=27;
                            ch1[0]=ch;
                            getchdo;
                            break;
                case ')':
//                        printf("分界符 (')')\n");
                            sym=28;
                            ch1[0]=ch;
                            getchdo;
                            break;
                case '#':
//                        printf("分界符 ('#')\n");
                            sym=0;
                            ch1[0]=ch;
                            getchdo;
                            break;
                default:
//                        printf("其他字符('%c')\n",ch);
                            sym=-1;
                            ch1[0]=ch;
                            getchdo;
                            break;
                }
            }
        }
    return 0;
}
void init()
{

    strcpy(&(word[0][0]), "begin");
    strcpy(&(word[1][0]), "if");
    strcpy(&(word[2][0]), "then");
    strcpy(&(word[3][0]), "while");
    strcpy(&(word[4][0]), "do");
    strcpy(&(word[5][0]), "end");
    strcpy(&(word[6][0]), "void");
    strcpy(&(word[7][0]), "struct");

}

void E(){
    T();
    E1();
}
 
void E1(){
    if(sym == 13){
        getsym();
        T();
        E1();
    }
    else if(sym == 0 || sym == 28){
        
    }
    else{
        error();
    }
}

void T(){
    F();
    T1();
}

void T1(){
    if(sym == 15){
        getsym();
        F();
        T1();
    }
    else if(sym==0 || sym==28 ||sym==13){
        
    }
    else{
        error();
    }    
}
void F(){
    if(sym == 27){
        getsym();
        E();
        if(sym == 28){
            getsym();
        }
        else{
            error();
        }
    }
    else if(sym == 11 || sym == 10){
        getsym();
    }
    else{
        error();    
    }    
}

void error(){
    printf("\n(%s,文法出错!)\n",ch1);
}


int main()
{

    input = fopen("test.txt", "r");
    if(input)
    {
        init();
        js = js2 = 0;
        ch = ' ';
//        while(getsym() != -1)
//        {
          getsym();
          E();
//        }        
    }
    else
    {
        printf("找不到文件\n");
    }
    printf("\n");
    return 0;
}

 

运行结果:

 

 

 

 

posted @ 2019-11-28 01:46  木朽花  阅读(269)  评论(0编辑  收藏  举报