c语言实现n的阶层递归下降语法分析,电子科大编译实验

需求

采用递归下降分析法对n!的pascal程序进行语法分析,生成四个结果文件

文法

原始文法

ps: <>代表非终结符

<程序>→<分程序>
<分程序>→begin <说明语句表>;<执行语句表> end
<说明语句表>→<说明语句>│<说明语句表> ;<说明语句>
<说明语句>→<变量说明>│<函数说明>
<变量说明>→integer <变量>
<变量>→<标识符>
<函数说明>→integer function <标识符>(<参数>);<函数体>
<参数>→<变量>
<函数体>→begin <说明语句表>;<执行语句表> end
<执行语句表>→<执行语句>│<执行语句表>;<执行语句>
<执行语句>→<读语句>│<写语句>│<赋值语句>│<条件语句>
<读语句>→read(<变量>)
<写语句>→write(<变量>)
<赋值语句>→<变量>:=<算术表达式>
<算术表达式>→<算术表达式>-<项>│<项>
<项>→<项>*<因子>│<因子>
<因子>→<变量>│<常数>│<函数调用>
<常数>→<无符号整数>
<无符号整数>→<数字>│<无符号整数><数字>
<条件语句>→if<条件表达式>then<执行语句>else <执行语句>
<条件表达式>→<算术表达式><关系运算符><算术表达式>
<关系运算符> →<│<=│>│>=│=│<>
<标识符>→<字母>│<标识符><字母>│ <标识符><数字>
<字母>→a│b│c│d│e│f│g│h│i│j│k│l│m│n│o │p│q │r│s│t│u│v│w│x│y│z|A|…|Z
<数字>→0│1│2│3│4│5│6│7│8│9

经过英语化、消除直接与间接左递归、提取直接与间接公共左因子的文法

ps:

  • x()指x为非终结符
  • e表示空
  • 引入A(),B(),C()为了提取公共左因子
  • 引入AA(),BB(),CC(),DD()为了消除直接左递归

variousAndFunctionCall()→e|( agloSen() )
program()→subprogram()
subprogram ()→begin stateTable()exertTable() end
stateTable()→stateSen()AA()
AA()→;stateSen()AA()|e
stateSen()→integer state()
state→variousState()│functionState()
variousState()→various()
functionState()→function various() (arg() ); functionBody()
arg()→various()
functionBody()→begin stateTable();exertTable() end;
exertTable()→exertSen()BB()
BB()→;exertSen()BB()|e
exertSen()→readSen()│writeSen()│assignSen()| ifSen()
readSen()→read(various())
writeSen()→write(various())
assignSen()→various() := agloSen()
agloSen()→xiang()CC()
CC()→- xiang()CC()|e
xiang()→yinzi()DD()
DD()→*yinzi()DD()|e
yinzi()→constt()│various() variousAndFunctionCall()
constt()→digit()A()
A()→e|constt()
variousAndFunctionCall()→e|( agloSen() )
ifSen()→if conditionSen() then exertSen() else exertSen()
conditionSen()→agloSen()relationSymbol()agloSen()
relationSymbol()→<B()│>C()|=
B()→e|=|>
C()→e|=
various()→letter()D()
D→e| letter()|digit()
letter()→a│…│z|A|…|Z
digit()→0│1│2│3│4│5│6│7│8│9

目录文件

在这里插入图片描述

文件格式

在这里插入图片描述
在这里插入图片描述
err文件

##注意事项
在这里插入图片描述

实验代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ERR "x.err"
#define PRO "x.pro"
#define VAR "x.var"
#define DYS "x.dys"
#define LINEMAX 20
int line=1,status,varPosition=0,vkind=0;
char proName[16];
int proLevel=0;;
char tmpWord[35];
char word[25];
FILE* source= fopen("source.dyd", "r+");
int advance();
void writeErr(const char * message);
void writeVar(const char * message);
void writePro(const char * message);
void writeDys(char * message);
void program();
void subprogram ();
void state();
void stateTable();
void AA();
void stateSen();
void variousState();
void functionState();
void arg();
void functionBody();
void exertTable();
void BB();
void exertSen();
void readSen();
void writeSen();
void assignSen();
void agloSen();
void CC();
void xiang();
void DD();
void yinzi();
void constt();
void A();
void variousAndFunctionCall();
void ifSen();
void conditionSen();
void relationSymbol();
void B();
void C();
void various();
void D();
void letter();
void digit();
int latter();
void program(){
    writePro("main");
    subprogram();
}
void subprogram (){
    if (!strcmp(word, "begin"))
    {
        advance();
        stateTable();
        vkind--;
        exertTable();
        if(!strcmp(word,"end")){
            int state=advance();
            if (state==-1)return;
        }else writeErr("no matched end");
    }else writeErr("no begin");
}
void stateTable(){
stateSen(); 
AA();
}
void stateSen(){
    if(!strcmp(word, "integer")){
        advance();
        state();
    }else writeErr("no correct integer");
}
void AA(){
    if(*word==';')
    {  
        advance();
        // if(!strcmp(word, "integer"))
        stateSen();
        AA();
    }
    else return;
}
void state(){
    if(!strcmp(word, "function"))
    functionState();
    else
    variousState();
}
void variousState(){
writeVar(word);
various();
}
void functionState(){
        if(!strcmp(word, "function")){
            advance();
            writePro(word);
            various();
            if(*word=='('){
                advance();
                arg();
                if(*word==')'){
                    advance();
                    if(*word==';')
                    {advance();functionBody();
                    }
                    else writeErr("7qwe");
            }else writeErr("8qwe");
        }else writeErr("9qwe");
    }else writeErr("10qwe");
}
void arg(){
various();
}
void functionBody(){
    if(!strcmp(word, "begin")){
        advance();
        stateTable();
        exertTable();
        if(!strcmp(word, "end")){
            advance();
        if(*word==';')advance();else {writeErr("qwe");};
    }else writeErr("qwe");
    }
}
void exertTable(){
exertSen();
BB();
}
void BB(){
    if(*word==';')
    {
        advance();exertSen();BB();
    }
    else return;
}
void exertSen(){
    if(!strcmp(word, "read"))
    readSen();
    else if(!strcmp(word, "write"))
    writeSen();
    else if(!strcmp(word, "if"))
    ifSen();
    else assignSen();
}
void readSen(){
    if(!strcmp(word, "read")){
        advance();
        if(*word=='('){
            advance();
            various();
            if(*word==')'){
                advance();
            }else writeErr("qwe");
        }else writeErr("no correct symbol match to read");
    }else writeErr("qwe");
}
void writeSen(){
        if(!strcmp(word, "write")){
        advance();
        if(*word=='('){
            advance();
            various();
            if(*word==')'){
                advance();
            }else writeErr("qwe");
        }else writeErr("qwe");
    }else writeErr("qwe");
}
void assignSen(){
    various();
    if(!strcmp(word, ":="))
    {
        advance();agloSen();
    }
    else writeErr("err");
}
void agloSen(){
xiang();CC();
}
void CC(){
    if(*word=='-')
    {
        advance();xiang();CC();
    }
    else return;
}
void xiang(){
yinzi();DD();
}
void DD(){
    if(*word=='*')
    {
        advance();yinzi();DD();
    }
    else return;
}
void yinzi(){
    if((*word)*1>47&&(*word)*1<58)
    constt();
    else {various();variousAndFunctionCall();}
}
void constt(){
digit();A();
}
void A(){
    if((*word)*1>47&&(*word)*1<58)
    constt();
    else return;
}
void variousAndFunctionCall(){
    if(*word=='('){
    advance();
    agloSen();
    if(*word==')'){
        advance();
    }else writeErr("qwe");
}else return;

}
void ifSen(){
    if(!strcmp(word, "if")){
        advance();
        conditionSen();
        if(!strcmp(word, "then")){
            advance();
            exertSen();
            if(!strcmp(word, "else")){
                advance();
                exertSen();
            }else writeErr("qwe");
        }else writeErr("qwe");
    }else writeErr("qwe");
}
void conditionSen(){
agloSen();relationSymbol();agloSen();

}
void relationSymbol(){
    switch(*word){
        case '<':advance();B();break;
        case '>':advance();C();break;
        case '=':advance();
        default:writeErr("qwe");
    }
}
void B(){
    switch (*word){
    case '=':advance();break;
    case '>':advance();break;
    default:return;
    }
}
void C(){
    if(*word=='=')
    advance();
    else return;
}
void various(){
letter();D();
}
void D(){
    if((*word>='a'&&*word<='z')||(*word>='A'&&*word<='Z'))
    letter();
    else if((*word)*1>47&&(*word)*1<58) digit();
    else return;
}
void letter(){
    if((*word>='a'&&*word<='z')||(*word>='A'&&*word<='Z'))
    advance();
    else {writeErr("is not correct expression");}
}
void digit(){
    if((*word)*1>47&&(*word)*1<58)
    advance();
    else writeErr("errd");
}

void writeErr(const char * message){
    FILE *result=fopen(ERR,"a+");
    char linec[4];
    itoa(line,linec,10);//fputs不能接受int,只能字符串,所以要类型转换
    fputs("Line ",result);
    fputs(linec,result);
    fputs(": ",result);
    fputs(message,result);
    fputs("\n",result);
    fclose(result);
    // advance();
}

void writeVar(const char * message){
    FILE *var=fopen(VAR,"a+");
    char varPositionc[4],proLevelc[4],vkindc[4];
    itoa(varPosition,varPositionc,10);
    itoa(proLevel,proLevelc,10);
    itoa(vkind,vkindc,10);
    fputs(message,var);//name
    fputs("--",var);
    fputs(proName,var);//belong Func
    fputs("--",var);
    fputs(vkindc,var);
    fputs("--ints--",var);
    fputs(proLevelc,var);//fun level
    fputs("--",var);
    fputs(varPositionc,var);//var position
    fputs("\n",var);
    varPosition++;
    vkind++;
    fclose(var);
}

void writePro(const char * message){
    FILE *result=fopen(PRO,"a+");
    char proLevelc[4];
    itoa(proLevel,proLevelc,10);//fputs不能接受int,只能字符串,所以要类型转换
    fputs(message,result);//name
    fputs("--",result);
    fputs("ints--",result);
    fputs(proLevelc,result);//level
    fputs("\n",result);
    strcpy(proName,message);
    proLevel++;
    fclose(result);
}

void writeDys(char * message){
    FILE *result=fopen(DYS,"a+");
    fputs(message,result);
    // fputs("\n",result);
    fclose(result);
}

int latter(){
    char *tmpWord=(char *)malloc(sizeof(char)*50);
    if(fgets(tmpWord, 30, source)!=NULL){
    writeDys(tmpWord);
    int position=0;
    while(*tmpWord==' ')
    tmpWord++;
    strcpy(word,tmpWord);
    while(*tmpWord!=' ')
    {
        tmpWord++;
        position++;
    }
    word[position]='\0';
    tmpWord-=16;
    if(!strcmp(word, "EOLN")){
        line++;
        latter();
    }
    if(!strcmp(word, "EOF"))return -1;
    return 1;
    }
    free(tmpWord);
    return -1;
}

int advance(){
    int x=latter();
    // printf("%s\n",word);
    return x;
}
int main(){
    status=advance();
    if(status==-1)return 0;
    program();
    return 0;
}


测试代码

测试程序:
begin
integer k;
integer function F(n);
begin
integer n;
if n<=0 then F:=1
else F:=n*F(n-1)
end;
read(m);
k:=F(m);
write(k)
end
语法分析中必须处理的几种情况:

  1. 第二行改为:intger m;
  2. 第三行改为:integer funtion F(n);
  3. 第九行改为:readm)
    4.begin
    integer k;
    integer function F(n);
    begin
    integer n;
    if n<=0 then F:=1
    else F:=n*F(n-1)
    end;
    read(m);
    integer m;
    k:=F(m);
    write(k)
    第九行后加一行 integer m;
    注意:第二种修改可能导致重大语法错误,同学们可以自己再另选一种重大语法错误进行测试。

结果

ps:本人原创,抄袭后果自负

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值