递归下降子程序实现LL(1)文法的语法分析

这是一次编译原理的实验,总结输出一下:

原理:

对每一个非终结符(分别代表一个语法单位)按其产生方式结构构造相应的语法子程序,以完成非终结符号所对应的语法单位的分析和识别任务。其中终结符号产生匹配命令,而非终结符号则产生过程调用命令。因为文法可以递归,相应子程序也是递归的。

1)示范,示例LL(1)文法如下:

G[A]:

(1)S::=pA

(2)S::=qB

(3)A::=cAd

(4)A::=a

(5)B::=dB

(6)B::=b

对应每条规则的选择集如下:

(1){p}

(2){q}

(3){c}

(4){a}

(5){d}

(6){b}

上述LL(1)递归下降子程序示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SourceMaxLength 10000
//声明函数
void A();
void B();

//结构体存放待比较字符串
struct sourceStr{
    char source[SourceMaxLength];//缓存字符串
    int pointer;//字符串下表指针
};
struct sourceStr sour;
char token;//存放当前比较的字符
int flag=1;//编译成功标记
char getToken()//获取当前字符
{
    token=sour.source[sour.pointer];
    sour.pointer++;
    return token;
}
void getSource(FILE *fp)//用于从文件中获取字符串
{

}
void error()//错误输出操作
{
    flag=0;
    printf("error;");
}
void S()//开始判断函数
{
    token=getToken();
    if(token != 'p' && token!='q')//如果下一个当前取得的字符不为p\q,则字符串错误
        error();
    else
    {
        if(token == 'p')//如果当前字符为p
        {
            A();//执行非终结符A的判断
        }
        else//否则执行非终结符B的判断
        {
            B();
        }
    }
}
void A()//执行非终结符A的判断
{
    token=getToken();
    if(token!='c'&&token!='a')//如果当前字符不符合,输出错误
        error();
    else{
        if(token=='c')//如果为c,则执行A判断
        {
            A();
            //判断下一个字符是否为d
            token=getToken();
            if(token!='d')
                error();
        }
        else{
            ;
        }
    }
}

void B()//执行非终结符A的判断
{
    token=getToken();
    if(token!='d'&&token!='b')//如果当前字符不符合,输出错误
        error();
    else{
        if(token=='d')//如果为d,执行B函数
        {
            B();
        }
    }
}

int main()
{
    sour.pointer=0;
    strcpy(sour.source,"pccaadd");//将字符串复制给sour.source

    //首先执行初始非终结符
    S();
    if(flag==1)
    {
        printf("success!");
    }
    else
    {
        printf("error");
    }
    return 0;
}

2)下面是简化的四则运算的语法规则,递归下降子程序法不能直接用这组规则进行语法分析

G[E]:

E::=E+T

E::=T

T::=T*F

T::=F

F::=(E)

F::=i

但是我们可以通过改造文法后,构建一等价文法,可以利用递归下降子程序发进行语法分析,该等价文法如下:

1.  E::=TA

2.  A::=+TA

3.  A::=

4.  T::=FB

5.  B::=*FB

6.  B::=

7.  F::=(E)

8.  F::=i

对应规则的选择集如下:

1.  {(,i}

2.  {+}

3.  {),#}

4.  {(,i}

5.  {*}

6.  {+,),#}

7.  {(}

8.  {i}

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SourceMaxLength 10000
//声明函数
void A();
void B();
void F();
void T();

//字符串结构体
struct sourceStr{
    char source[SourceMaxLength];//缓存字符串
    int pointer;//字符串下表指针
};

struct sourceStr sour;
char token;//存放当前比较的字符
int flag=1;//编译成功标记
char getToken()//获取当前字符
{
    token=sour.source[sour.pointer];
    sour.pointer++;
    return token;
}
void getSource(FILE *fp)//用于从文件中获取字符串
{

}
void error()//错误输出操作
{
    flag=0;
    printf("error;");
}
void E()//开始判断函数
{
    token=getToken();
    if(token != '(' && token!='i')//如果下一个当前取得的字符不为(、i,则字符串错误
        error();
    else{
        if(token=='('){//如果为(,执行(),并取下一个字符
            E();
            token=getToken();
            if(token!=')')
                error();

        }
        B();
        A();
    }
}

void T()//非终结符T判断
{
    token=getToken();
    if(token != '(' && token!='i')//如果下一个当前取得的字符不为(、i,则字符串错误
        error();
    else
    {
        if(token=='('){
            E();
            token=getToken();
            if(token!=')')
                error();

        }
        B();
    }
}

void F()//非终结符F判断
{
    token=getToken();
    if(token != '(' && token!='i')
        error();
    else
    {
        if(token=='('){
            E();
            token=getToken();
            if(token!='(') error();
        }
        else{
            ;
        }
    }
}

void A()//非终结符A判断
{
    token=getToken();
    if(token!='+'&&token!=')'&&token!='#')//如果当前字符不符合,输出错误
        error();
    else{
        if(token=='+')
        {
            T();
            A();
        }else{//如果A终结符为空,字符串指针回溯一个
            sour.pointer--;
        }
    }
}
void B()
{
    token=getToken();
    if(token!='*'&&token!='+'&&token!=')'&&token!='#')//如果当前字符不符合,输出错误
        error();
    else{
        if(token=='*')
        {
            F();
            B();
        }else{//如果B终结符为空,字符串指针回溯一个
            sour.pointer--;
        }
    }
}

int main()
{
    sour.pointer=0;
    strcpy(sour.source,"(i+i*i)+i*i#");//将字符串复制给sour.source

    //首先执行初始非终结符
    E();
    if(flag==1)
    {
        printf("success!");
    }
    else
    {
        printf("error");
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/SICAUliuy/article/details/80270108