编译原理——语法分析器(SLR)

编译原理——语法分析器(SLR)

识别语法结构:

  • 变量声明(不含变量初始化)
  • if单条件分支语句以及if else 双条件分支语句
  • for循环和while循环语句
  • 赋值语句 ,四则运算,逻辑判断复合语句
  • 函数声明 函数调用

文法

//其中$作为标识符判断  @常数值判断
Z->S
S->while(E)S
S->E;S
S->;S
S->for(E;E;E)S
S->CM;S
S->C$(W){SreturnE;}S
S->$(H);S
M->M,$
M->$
H->$H
H->nH
H->,$H
H->,@H
H->#
C->char
C->int
C->double
S->if(E)S
S->SelseS
S->{S}S
S->#
E->EOE
E->(E)
E->@
E->$
W->#
W->C$,W
W->C$
O->+
O->-
O->/
O->*
O->>
O->=
O->>=
O-><
O-><=
O->!=
O->==
O->&
O->&&
O->|
O->||

算法描述及实验步骤

数据结构解析

  • product—存放文法
  typedef struct Product{
      char left;
      char right[N];
      int length;
  }Product;
  • Follow—存放文法的follow集
  typedef struct Follow{
      char V;
      vector<char> fset;
  }Follow;
  • I—存放状态闭包集
  typedef struct I{
      vector<Product> pros;
  }I;

主要函数解析

  • SLR函数设计

    • 该函数能够实现将文件中输入好的文法自动根据SLR状态转移算法形成Action表和Goto表

    • 事先读入文法,并获取产生式中出现的终结符集合以及非终结符集合

    • 修正文法,将产生式右部添加 . 号,便于算法模拟

      Z->.S
      S->.while(E)S
      S->.E;S
      S->.;S
      S->.for(E;E;E)S
      S->.CM;S
      S->.C$(W){SreturnE;}S
      S->.$(H);S
      M->.M,$
      M->.$
      H->.$H
      H->.nH
      H->.,$H
      H->.,@H
      H->.
      C->.char
      C->.int
      C->.double
      S->.if(E)S
      S->.SelseS
      S->.{S}S
      S->.
      E->.EOE
      E->.(E)
      E->.@
      E->.$
      W->.
      W->.C$,W
      W->.C$
      O->.+
      O->.-
      O->./
      O->.*
      O->.>
      O->.=
      O->.>=
      O->.<
      O->.<=
      O->.!=
      O->.==
      O->.&
      O->.&&
      O->.|
      O->.||
      
    • 将第一个产生式放入闭包集I(0),并求出完整的闭包集

    • 依次依据识别出的非终结符和终结符,对第一个闭包集进行状态转移

    • 每次转移之后,得到新的闭包集I(i),并对I(i)求出完整的闭包集。求出之后在已有的闭包集中判断是否是重复的闭包集。

    • 如果不重复添加Action表和Goto表信息,状态I(i-1)中的i-1为横坐标,识别的终结符或者是非终结符为纵坐标,i为表项的值。

    • 如果重复则第一次出现该闭包集的状态下标作为表项的值

    • 依次次做上一步,直到没有新的闭包集出现

    • 对所有闭包集做判断,倘若闭包集中出现了规约性项目,查询该项目的左部的非终结符的Follow集,并将对应的闭包集状态下标以及Follow符号对应的Action表和Goto表表项进行修改。

  • close函数设计

    • 该函数实现求状态转移后,完整闭包集的求法
    • 遍历当前闭包集中的产生式,每个产生式寻找到 . 号,对 . 号后面的字符做判断
      • 倘若是**\0**则代表是规约型项目,不做处理
      • 倘若是终结符,不作处理
      • 倘若是非终结符,则寻找,当前所有产生式左部含有该非终结符的产生式添加到该闭包集中
    • 循环处理上一步,直至闭包集的大小不发生改变
  • SLR驱动函数设计

    • 该函数实现对输入字符串的语法解析,采用的是SLR的算法策略
    • 首先该函数调用之前应具有正确的Action表以及Goto表
    • 根据SLR算法思想设立字符栈,状态栈,初始状态为0
    • 读入所需判断的字符,根据状态栈顶和字符,查询Action表以及Goto表
      • 如果是移路状态,则将该字符放入字符栈中
      • 如果是规约状,则根据规约产生式,将字符(状态)从字符(状态)栈中弹出,并判断对应非终结符的状态,放入状态栈中
      • 如果是接受状态,则判断该字符串语法正确
      • 如果出现错误,将调用error函数,处理错误
  • error函数设计

    • 该函数为出现错误时调用
    • 判断当前字符栈中的字符串,与所有产生式进行比对,如果是该字符串是产生式的一部分,那么可以得到结论,原始需要判断的字符串的中缺少的是该产生式中未得到比对的字符
    • 记录当前出错的代码位置,以及错误信息,将字符栈,状态栈,置空,重新判断后面的代码。
    • 该函数处理的比较一般,无法处理较复杂的错误,暂时未能够想到更好的处理办法
  • init_Follow函数设计

    • 该函数能获取非终结的follow集
    • 该函数暂时未能用代码自动实现,主要靠文件读取。
  • main函数设计

    • 先做词法分析,倘若出现词法错误,输出错误信息结束程序
    • 读取文法,将文件中的文法读取,到程序中
    • 初始化得到非终结集合,终结符集合,follow集合
    • 初始化Action表以及Goto表
    • SLR函数,求闭包集
    • 更新Action表以及Goto表
    • 调用SLR驱动程序,进行语法分析
    • 输出错误信息

源代码

```c++
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string.h>
#include <cmath>
#include <vector>
#include <stack>
//词法分析器
#include "CIFA.h"
using namespace std;
//const int N=100;
//const int MAXSIZE=1000;
//产生式存储
typedef struct Product{
    char left;
    char right[N];
    int length;
}Product;
//状态闭包集存储
typedef struct I{
    vector<Product> pros;
}I;
//follow集存储
typedef struct Follow{
    char V;
    vector<char> fset;
}Follow;
//闭包集 集合
vector<I> Is;
//follow集 集合
vector<Follow> FollowSet;
int prod_len;
//产生式集
Product products[MAXSIZE];

//非终结符集,终结符集
char V[MAXSIZE];int V_len=0;
char T[MAXSIZE];int T_len=0;

//action goto 表
char _action[MAXSIZE][MAXSIZE];
int _goto[MAXSIZE][MAXSIZE];
//action 表初始化
void init_action(){
    for(int i=0;i<MAXSIZE;i++)
        for(int j=0;j<MAXSIZE;j++)
        _action[i][j]='e';
}
//goto 表初始化
void init_goto(){
    for(int i=0;i<MAXSIZE;i++)
        for(int j=0;j<MAXSIZE;j++)
        _goto[i][j]=-1;
}
//字符串比对函数
bool mystrcmp(char *s,char *p){
    int i=0,j=0;
    while(s[i]!='\0' && p[j]!='\0' && s[i]==p[j]){++i;++j;}
    if(s[i]=='\0' && p[j]=='\0')return true;
    else return false;
}
//判断产生式是否相同
bool is_sameProduct(Product a,Product b){
    if(a.length!=b.length)return false;
    if(a.left==b.left && mystrcmp(a.right,b.right))return true;
    else return false;
}
//判断是否为操作符
bool is_operate(char c){
    char op[N]="+-*/=&|><";
    int i=0;
    while(op[i]!='\0'){
         if(op[i]==c)return true;
         i++;
    }
    return false;
}
//判断是否为非终结符
bool is_signV(char c){
    if(c>='A' && c<='Z')return true;
    else return false;
}
//判断状态闭包集是否相同
bool is_sameI(I a,I b){
    if(a.pros.size()!=b.pros.size())return false;
    int i,j;
    int cnt=0;
    for(i=0;i<a.pros.size();i++){
        for(j=0;j<b.pros.size();j++){
            if(is_sameProduct(a.pros[i],b.pros[j])){cnt++;break;}
        }
    }
    if(cnt==a.pros.size()){
        return true;
    }
    else return false;
}
//产生式拷贝
Product newProduct(Product a){
    Product ans;
    ans.left=a.left;
    strcpy(ans.right,a.right);
    ans.length=a.length;
    return ans;
}
//下标索引转换
int changIndex(char c){
    for(int i=0;i<T_len;i++){
        if(T[i]==c)return i;
    }
    for(int i=0;i<V_len;i++){
        if(V[i]==c)return T_len+i;
    }
    return -1;
}
//判断产生式是否在闭包集中
bool is_inI(I s,Product a){
    for(int i=0;i<s.pros.size();i++){
        if(is_sameProduct(s.pros[i],a))return true;
    }
    return false;
}
//输出产生式
void print_product(Product a){
    printf("%c->%s\n",a.left,a.right);
}
//输出产生式 --- 保存文件
void print_I(I a,int ans){
    char filename[10]="Is/I";
    int t=0,cnt=ans;
    string s="";
    while(filename[t]!='\0')t++;
    while(cnt){s+=(cnt%10)+'0';cnt/=10;}
    for(int i=s.size()-1;i>=0;i--)filename[t++]=s[i];
    filename[t++]='.';filename[t++]='t';filename[t++]='x';filename[t++]='t';
    filename[t]='\0';
    FILE *fp=fopen(filename,"w");
    for(int i=0;i<a.pros.size();i++){
        fprintf(fp,"%c->%s\n",a.pros[i].left,a.pros[i].right);
    }
    fclose(fp);
}
//判断是否是对应产生式
bool judge_product(Product a,Product b){
    int i=1,j=0;
    while(a.right[i]!='\0' && b.right[j]!='.' && a.right[i]==b.right[j]){++i;++j;}
    if(a.left==b.left && a.right[i]=='\0' && b.right[j]=='.')return true;
    else return false;
}
//闭包集求解
I close(I a){
    for(int i=0;i<a.pros.size();i++){
            char *s=a.pros[i].right;
            int k=0;
            while(s[k]!='\0' && s[k]!='.')k++;
            char c=s[k+1];
            if(c!='\0' && c>='A' && c<='Z'){
                for(int j=0;j<prod_len;j++){
                    if(products[j].left==c){
                        if(!is_inI(a,products[j]))
                            a.pros.push_back(products[j]);
                    }
                }
            }
        }
        return a;
}
//寻找非终结符对应follow集
int findFollow(char v){
    for(int i=0;i<FollowSet.size();i++){
        if(FollowSet[i].V==v)return i;
    }
    return -1;
}
//寻找产生式
int findProduct(Product a){
    for(int i=0;i<prod_len;i++){
        if(judge_product(products[i],a))return i;
    }
    return -1;
}
//SLR
void SLR(){
    I t;
    t.pros.push_back(products[0]);
    t=close(t);
    Is.push_back(t);
    int z=0;
    do{
        /*求状态闭包集*/
        /*状态转移---非终结符*/
        for(int m=0;m<V_len;m++){
            I t;
            for(int n=0;n<Is[z].pros.size();n++){
                Product ans=newProduct(Is[z].pros[n]);
                int k=0;
                while(ans.right[k]!='\0' && ans.right[k]!='.')k++;
                if(ans.right[k+1]=='\0')continue;
                if(V[m]==ans.right[k+1]){
                    swap(ans.right[k],ans.right[k+1]);
                    t.pros.push_back(ans);

                }
            }
            t=close(t);
            if(t.pros.size()==0)continue;
            int u;
            for(u=0;u<Is.size();u++){
                if(is_sameI(Is[u],t)){
                    int xx=z,yy=changIndex(V[m]);
                    _goto[xx][yy]=u;
                    break;
                }
            }
            if(u==Is.size()){
                Is.push_back(t);
                 int xx=z,yy=changIndex(V[m]);
                 _goto[xx][yy]=Is.size()-1;
            }
        }

        for(int m=0;m<T_len;m++){
            if(T[m]=='\0')continue;
            I t;
            for(int n=0;n<Is[z].pros.size();n++){
                Product ans=newProduct(Is[z].pros[n]);
                int k=0;
                while(ans.right[k]!='\0' && ans.right[k]!='.')k++;
                if(ans.right[k+1]=='\0')continue;
                if(T[m]==ans.right[k+1]){
                    swap(ans.right[k],ans.right[k+1]);
                    t.pros.push_back(ans);

                }
            }
            t=close(t);
            if(t.pros.size()==0)continue;
            int u;
            for(u=0;u<Is.size();u++){
                if(is_sameI(Is[u],t)){
                    int xx=z,yy=changIndex(T[m]);
                    _action[xx][yy]='s';
                    _goto[xx][yy]=u;
                    break;
                }
            }
            if(u==Is.size()){
                Is.push_back(t);
                int xx=z,yy=changIndex(T[m]);
                _action[xx][yy]='s';
                _goto[xx][yy]=Is.size()-1;
            }
        }
        z++;
    }while(z<Is.size());
    //printf("66\n");

    int l,xx,yy,index,r;
    for(int i=0;i<Is.size();i++){
        for(int j=0;j<Is[i].pros.size();j++){
            l=Is[i].pros[j].length;
            if(Is[i].pros[j].right[l-1]=='.'){
                xx=i;index=findFollow(Is[i].pros[j].left);
                //printf("%d \n",index);
                r=findProduct(Is[i].pros[j]);
                for(int k=0;k<FollowSet[index].fset.size();k++){
                    yy=changIndex(FollowSet[index].fset[k]);
                    _action[xx][yy]='r';
                    _goto[xx][yy]=r;
                }
            }

        }
    }
    _action[1][T_len-1]='a';
}
//初始化非终结符
void init_V(){
    char c;
    int i,j;
    for(i=0;i<prod_len;i++){
        c=products[i].left;
        //printf("%c",c);
        for(j=0;j<V_len;j++){
            if(c==V[j]){break;}
        }
        if(j==V_len){V[V_len]=c;V_len++;}
    }
    //for(int i=0;i<V_len;i++){printf("%c ",V[i]);}
}
//初始化终结符
void init_T(){
    char *s,c;
    int i,j,k;
    for(i=0;i<prod_len;i++){
        s=products[i].right;
        k=0;
        while(s[k]!='\0'){
            c=s[k];k++;
            if((c>'Z' || c<'A') && c!='#'){
                //printf("%c ",c);
                for(j=0;j<T_len;j++){
                    if(c==T[j]){break;}
                }
                if(j==T_len){T[T_len]=c;T_len++;}
            }

        }
    }
    T[T_len++]='\0';
    //for(int i=0;i<T_len;i++){printf("%c ",T[i]);}
    //printf("\n");
}
//初始化follow集
/*暂时还无法用程序实现*/
void init_Follow(){
    FILE * fp=fopen("Follow.txt","r");
    char ans[N];
    int v,k;
    while(!feof(fp)){
        fscanf(fp,"%s",ans);
        k=0;
        Follow t;
        while(ans[k]!='\0' && ans[k]!=EOF){
            if(ans[k]>='A' && ans[k]<='Z')t.V=ans[k];
            else {
                if(ans[k]=='#')t.fset.push_back('\0');
                else t.fset.push_back(ans[k]);
            }
            k++;
        }
        FollowSet.push_back(t);
        fgetc(fp);
    }
    fclose(fp);
}
//读取文件中的产生式
void GetProduct(char *filename){
    FILE  *fp=fopen(filename,"r");
    int ans;
    char c;
    prod_len=0;
    while(!feof(fp)){
        fscanf(fp,"%c->%s",&products[prod_len].left,products[prod_len].right);
        c=fgetc(fp);
        ans=0;
        while(products[prod_len].right[ans]!='\0')ans++;
        products[prod_len].length=ans;
        prod_len++;
    }
    fclose(fp);
}
//更新产生式
char* updateProduct(){
    FILE * fp=fopen("t_WENFA.txt","w");
    for(int i=0;i<prod_len;i++){
        if(i==prod_len-1){
            if(mystrcmp("#",products[i].right))fprintf(fp,"%c->.",products[i].left);
            else fprintf(fp,"%c->.%s",products[i].left,products[i].right);
        }
        else{
            if(mystrcmp("#",products[i].right))fprintf(fp,"%c->.\n",products[i].left);
            else fprintf(fp,"%c->.%s\n",products[i].left,products[i].right);
        }
    }
    fclose(fp);
    return "t_WENFA.txt";
}
//错误处理
void error(int eline,stack<char> s,char c,FILE *fp){
    if(s.empty())return ;
    int i,j,index,t=0;
    char tmp[20],ct;
    vector<char> ans(s.size());
    for(i=ans.size()-1;i>=0;i--){
        ans[i]=s.top();s.pop();
    }
    if(is_operate(ans[ans.size()-1])){insert_error(eline,"操作数","语法错,此处缺少");}
    bool judge=false;
    for(i=0;i<ans.size();i++)
    {
        if(ans[i]=='(')judge=true;
        if(ans[i]==')')judge=false;
    }
    if(judge){insert_error(eline,")","语法错,此处缺少");}
    judge=false;
    for(i=0;i<ans.size();i++)
    {
        if(ans[i]=='{')judge=true;
        if(ans[i]=='}')judge=false;
    }
    if(judge){insert_error(eline,"}","语法错,此处缺少");}
//    for(i=0;i<ans.size();i++){cout<<ans[i]<<" ";}
//    cout<<endl;
    for(i=0;i<prod_len;i++){
        j=0;
        while(j<products[i].length && j<ans.size() && products[i].right[j]==ans[j])j++;
        //cout<<i<<endl;
        if(j==ans.size()){
            while(products[i].right[j]!='\0'){
                if(products[i].right[j]<'A' || products[i].right[j]>'Z')tmp[t++]=products[i].right[j++];
                else break;
                //cout<<tmp[t-1]<<endl;
            }
            //print_product(products[i]);
            tmp[t]='\0';
            if(t==1){
                if(tmp[0]=='@' || tmp[0]=='$')
                    {insert_error(eline,"操作数","语法错,此处缺少");return ;}
                else{
                    if(is_operate(tmp[0])){insert_error(eline,tmp,"语法错,此处缺少");return ;}
                    else{
                        insert_error(eline,tmp,"语法错,非法字符");
                        return ;
                    }
                }

            }else if(t>1){
                if(t>1)insert_error(eline,tmp,"语法错,此处缺少");
                return ;
            }else{
                tmp[t++]=c;
                while((ct=fgetc(fp))!=EOF){
                        if(ct>='a' && ct<='z')tmp[t++]=ct;
                        else break;
                }
                tmp[t]='\0';
                insert_error(eline,tmp,"语法错,非法字符");
                return ;
            }

        }
    }
    //for(int i=0;i<=Erlen;i++){printf("%d :%s  %s\n",Errors[i].line,Errors[i].info,Errors[i].c);}
    //exit(0);
}
//更新action表
void update_action(){
    FILE *file_action=fopen("action.txt","w");
    fprintf(file_action,"\t");
    for(int i=0;i<T_len;i++){
        if(T[i]!='\0')fprintf(file_action,"%c\t",T[i]);
        else fprintf(file_action,"#\t");
    }
    fprintf(file_action,"\n");
    for(int i=0;i<Is.size();i++)
    {
        fprintf(file_action,"%d\t",i);
        for(int j=0;j<T_len;j++)
            fprintf(file_action,"%c\t",_action[i][j]);
        fprintf(file_action,"\n");
    }
    fclose(file_action);
}
//更新goto表
void update_goto(){
    FILE *file_goto=fopen("goto.txt","w");
    fprintf(file_goto,"\t");
    for(int i=0;i<T_len;i++){
            if(T[i]!='\0')fprintf(file_goto,"%c\t",T[i]);
            else fprintf(file_goto,"#\t");
    }
    for(int i=0;i<V_len;i++){fprintf(file_goto,"%c\t",V[i]);}
    fprintf(file_goto,"\n");
    for(int i=0;i<Is.size();i++)
    {
        fprintf(file_goto,"%d\t",i);
        for(int j=0;j<V_len+T_len;j++)
            fprintf(file_goto,"%d\t",_goto[i][j]);
        fprintf(file_goto,"\n");
    }
    fclose(file_goto);
}
//SLR驱动程序
void SLR_Driver(){
    FILE *fp_Token=fopen("Token.txt","r");
    FILE *fp_debug=fopen("debug.txt","w");
    stack<int> s_state;
    stack<char> s_char;
    int i=0,pos,state,code_line=1,ju=10;
    char ans,c,s[N];
    s_state.push(0);
    c=fgetc(fp_Token);
    while(1){
        if(c=='\n'){c=fgetc(fp_Token);code_line++;continue;}
        if(c==EOF){c='\0';}
        state=s_state.top();
        pos=changIndex(c);
        ans=_action[state][pos];
                //cout<<"状态栈顶"<<" "<<"符号栈顶"<<endl;
        fprintf(fp_debug,"状态栈顶   符号栈顶\n");
        if(!s_state.empty()&&!s_char.empty()){
                //cout<<s_state.top()<<" "<<s_char.top()<<endl;
                fprintf(fp_debug,"%d   %c\n",s_state.top(),s_char.top());
        }
        //cout<<c<<" "<<" "<<ans<<" "<<_goto[state][pos]<<endl;
        fprintf(fp_debug,"%c   %c   %d\n",c,ans,_goto[state][pos]);
        switch(ans){
                case 's':{s_state.push(_goto[state][pos]);s_char.push(c);c=fgetc(fp_Token);break;}
                case 'r':{
                    if(products[_goto[state][pos]].right[0]!='#')
                        for(int i=0;i<products[_goto[state][pos]].length;i++){s_state.pop();s_char.pop();}
                    s_char.push(products[_goto[state][pos]].left);
                    s_state.push(_goto[s_state.top()][changIndex(s_char.top())]);
                    break;
                }
                case 'a':{
                    if(Erlen<0)
                        printf("Accept,语法分析成功666\n");
                    return ;
                }
                default :{
                    //cout<<c<<endl;
                    error(code_line,s_char,c,fp_Token);
                    s_char=stack<char>();
                    s_state=stack<int>();s_state.push(0);
                    c=fgetc(fp_Token);
                    if(c==EOF)return ;
                    break;
                }
            }
    }
    fclose(fp_Token);
    fclose(fp_debug);
}
int main()
{
    ci_start();
    if(Erlen!=-1){
        printf("词法分析错误\n");
        for(int i=0;i<=Erlen;i++){printf("%d :%s  %s\n",Errors[i].line,Errors[i].info,Errors[i].c);}
        exit(0);
    }
    GetProduct("WENFA.txt");
    init_V();
    init_T();
    init_Follow();
    char *filename=updateProduct();
    GetProduct(filename);
    init_action();init_goto();
    SLR();
    update_action();
    update_goto();
    for(int i=0;i<Is.size();i++){print_I(Is[i],i);}
    GetProduct("WENFA.txt");
    update_action();
    update_goto();
    SLR_Driver();
    for(int i=0;i<=Erlen;i++){printf("%d :%s  %s\n",Errors[i].line,Errors[i].info,Errors[i].c);}

    return 0;
}

效果呈现

test.c

int max(int a,int b){
	int m;
	if(a>b)m=a;
	else m=b;
	return m;
}
int main(){
	int sum,i,n;
	int cnt;
	double ave;
	sum=0;
	cnt=0;
	for(i=1;i<=n;i=i+1){
		sum=sum+i;
	}
	max(sum,n);
	ave=sum/n;
	for(i=1;i<=n;i=i+1){
		if(i==ave)cnt=cnt+1;
	}
	i=0;
	while(i<=n){
		if(cnt/i==0){printf("YES\n");}
		else{printf("NO\n");}
		i=i+1;
	}
	return 0;
}

调用程序,进行解析(该程序未出现语法错)

在这里插入图片描述

test2.c

int main(){
	int name;
	name=;
	for(name=0;name<10;name=name+name)name+1;
	return 0;
}

调用程序,进行解析(显然该程序出现语法错),因为一个错,带动后面一起错,所以出错处理不是非常好。

在这里插入图片描述

该程序可能会有bug,请见谅…欢迎指正。

递归下降分析法 一、实验目的: 根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对递归下降分析法的理解。 二、实验说明 1、递归下降分析法的功能 词法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。 2、递归下降分析法的前提 改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法, 3、递归下降分析法实验设计思想及算法 为G的每个非终结符号U构造一个递归过程,不妨命名为U。 U的产生式的右边指出这个过程的代码结构: (1)若是终结符号,则和向前看符号对照, 若匹配则向前进一个符号;否则出错。 (2)若是非终结符号,则调用与此非终结符对应的过程。当A的右部有多个产生式时,可用选择结构实现。 三、实验要 (一)准备: 1.阅读课本有关章节, 2.考虑好设计方案; 3.设计出模块结构、测试数据,初步编制好程序。 (二)上课上机: 将源代码拷贝到机上调试,发现错误,再修改完善。第二次上机调试通过。 (三)程序要: 程序输入/输出示例: 对下列文法,用递归下降分析法对任意输入的符号串进行分析: (1)E->eBaA (2)A->a|bAcB (3)B->dEd|aC (4)C->e|dc 输出的格式如下: (1)递归下降分析程序,编制人:姓名,学号,班级 (2)输入一以#结束的符号串:在此位置输入符号串例如:eadeaa# (3)输出结果:eadeaa#为合法符号串 注意: 1.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好); 2.对学有余力的同学,可以详细的输出推导的过程,即详细列出每一步使用的产生式。 (四)程序思路 0.定义部分:定义常量、变量、数据结构。 1.初始化:从文件将输入符号串输入到字符缓冲区中。 2.利用递归下降分析法分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。
这个里面的都是测试数据,总共得分5分。从控制台输入,不能从文件中读取。实现了基本功能,加分项目都没有去实现,没有函数数组这些的实现。这是用C++语言写的,新建parser类别要选C++,其他对于VS的配置和C语言一样。for语句用的是枚举所有情况,你可以自行修改。 对预备工作中自然语言描述的简化C编译器的语言特性的语法,设计上下文无关文法进行描述 借助Yacc工具实现语法分析器 考虑语法树的构造: 1.语法树数据结构的设计:节点类型的设定,不同类型节点应保存哪些信息,多叉树的实现方式 2.实现辅助函数,完成节点创建、树创建等功能 3.利用辅助函数,修改上下文无关文法,设计翻译模式 4.修改Yacc程序,实现能构造语法树的分析器 考虑符号表处理的扩充 1.完成语法分析后,符号表项应增加哪些标识符的属性,保存语法分析的结果 2.如何扩充符号表数据结构,Yacc程序如何与Lex程序交互,正确填写符号表项 以一个简单的C源程序验证你的语法分析器,可以文本方式输出语法树结构,以节点编号输出父子关系,来验证分析器的正确性,如下例: main() { int a, b; if (a == 0) a = b + 1; } 可能的输出为: 0 : Type Specifier, integer, Children: 1 : ID Declaration, symbol: a Children: 2 : ID Declaration, symbol: b Children: 3 : Var Declaration, Children: 0 1 2 4 : ID Declaration, symbol: a Children: 5 : Const Declaration, value:0, Children: 6 : Expr, op: ==, Children: 4 5 7 : ID Declaration, symbol: a Children: 8 : ID Declaration, symbol: b Children: 9 : Const Declaration, value:1, Children: 10: Expr, op: +, Children: 8 9 11: Expr, op: =, Children: 7 10 12: if statement, Children: 6 11 13: compound statement, Children: 3 12
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值