编译原理实验之语法分析(算符优先分析算法(C语言))

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
const double esp=1e-6;
using namespace std;

const int Maxn=110;
const int maxn=20;
char str[maxn][Maxn];//输入文法
char st[maxn];//输入串
char stac[maxn];//模拟栈的数组
char nstr[maxn][maxn];//储存转化文法
char mstr[maxn][maxn];
char fin[maxn];//存储终结符
char firstvt[maxn][maxn],lastvt[maxn][maxn];
char cmp[maxn][maxn];//存储表中的比较符
int firstflag[maxn],lastflag[maxn];//非终结符的firstvt,lastvt是否求出
int fcnt[maxn],lcnt[maxn];//非终结符firsvt和lastvt的个数
int is_fin(char c) { //判断终结符
    for(int i=0; fin[i]!='\0'; i++) {
        if(fin[i]==c)
            return 1;
    }
    return 0;
}
int site(char c) { //求在表中的下标
    for(int i=0; fin[i]!='\0'; i++) {
        if(fin[i]==c)
            return i;
    }
}

void get_firstvt(char s,int t) { //求s非终结符的firstvt值
    int i,j,ii,jj,tt;
    for(i=0; i<t; i++) {
        if(str[i][0]==s)
            break;
    }
    if(!firstflag[i]) {
        int k=fcnt[i];
        for(j=0; str[i][j]!='\0'; j++) {
            if(j==2||str[i][j]=='|') {
                if(is_fin(str[i][j+1])) {
                    firstvt[i][k++]=str[i][j+1];
                } else {
                    if(is_fin(str[i][j+2])) {
                        firstvt[i][k++]=str[i][j+2];
                    }
                    if(str[i][j+1]!=s) {
                        get_firstvt(str[i][j+1],t);
                        for(ii=0; ii<t; ii++) {
                            if(str[ii][0]==str[i][j+1])
                                break;
                        }
                        for(jj=0; jj<fcnt[ii]; jj++) {
                            for(tt=0; tt<k; tt++) {
                                if(firstvt[i][tt]==firstvt[ii][jj])
                                    break;
                            }
                            if(tt==k) {
                                firstvt[i][k++]=firstvt[ii][jj];
                            }
                        }
                    }
                }
            }
        }
        firstvt[i][k]='\0';
        fcnt[i]=k;
        firstflag[i]=1;
    }
}

void output_firstvt(int T) { //输出firstvt集
    for(int i=0; i<T; i++) {
        get_firstvt(str[i][0],T);
    }
    for(int i=0; i<T; i++) {
        printf("Firstvt[%c]:",str[i][0]);
        for(int j=0; j<fcnt[i]; j++) {
            printf("%c ",firstvt[i][j]);
        }
        puts("");
    }
}

void get_lastvt(char s,int t) { //求s非终结符的lastvt值
    int i,j,ii,jj,tt;
    for(i=0; i<t; i++) {
        if(str[i][0]==s)
            break;
    }
    if(!lastflag[i]) {
        int k=lcnt[i];
        for(j=0; str[i][j]!='\0'; j++) {
            if(str[i][j+1]=='|'||str[i][j+1]=='\0') {
                if(is_fin(str[i][j])) {
                    lastvt[i][k++]=str[i][j];
                } else {
                    if(is_fin(str[i][j-1])) {
                        lastvt[i][k++]=str[i][j-1];
                    }
                    if(str[i][j]!=s) {
                        get_lastvt(str[i][j],t);
                        for(ii=0; ii<t; ii++) {
                            if(str[ii][0]==str[i][j])
                                break;
                        }
                        for(jj=0; jj<lcnt[ii]; jj++) {
                            for(tt=0; tt<k; tt++) {
                                if(lastvt[i][tt]==lastvt[ii][jj])
                                    break;
                            }
                            if(tt==k) {
                                lastvt[i][k++]=lastvt[ii][jj];
                            }
                        }
                    }
                }
            }
        }
        lastvt[i][k]='\0';
        lcnt[i]=k;
        lastflag[i]=1;
    }
}

void output_lastvt(int T) { //输出lastvt集
    for(int i=0; i<T; i++) {
        get_lastvt(str[i][0],T);
    }
    for(int i=0; i<T; i++) {
        printf("Lastvt[%c]:",str[i][0]);
        for(int j=0; j<lcnt[i]; j++) {
            printf("%c ",lastvt[i][j]);
        }
        puts("");
    }
}

void get_table(int T,int cnt) { //得到表
    int x=0,y=0;
    int i,j,ii,jj;
    for(i=0; i<T; i++) {
        for(j=0; str[i][j]!='\0'; j++) {
            if(str[i][j]!='|')
                nstr[x][y++]=str[i][j];
            else if(str[i][j]=='|') {
                nstr[x][y]='\0';
                x++;
                y=0;
                nstr[x][y++]=str[i][0];
                nstr[x][y++]='-';
                nstr[x][y++]='>';
            }
        }
        nstr[x][y]='\0';
        x++;
        y=0;
    }
    //对于S1->#S#;
    char a='#';
    cmp[site(a)][site(a)]='=';
    for(i=0; i<fcnt[0]; i++) {
        cmp[site(a)][site(firstvt[0][i])]='<';
    }
    for(i=0; i<lcnt[0]; i++) {
        cmp[site(lastvt[0][i])][site(a)]='>';
    }
    //对于初始的文法
    for(i=0; i<x; i++) {
        for(j=3; nstr[i][j+1]!='\0'; j++) {
            if(is_fin(nstr[i][j])&&is_fin(nstr[i][j+1]))
                cmp[site(nstr[i][j])][site(nstr[i][j+1])]='=';
            if(is_fin(nstr[i][j])&&!is_fin(nstr[i][j+1])&&is_fin(nstr[i][j+2])&&nstr[i][j+2]!='\0')
                cmp[site(nstr[i][j])][site(nstr[i][j+2])]='=';
            if(!is_fin(nstr[i][j])&&is_fin(nstr[i][j+1])) { //对于非终结符在终结符之前
                for(ii=0; ii<T; ii++) {
                    if(str[ii][0]==nstr[i][j])
                        break;
                }
                for(jj=0; jj<lcnt[ii]; jj++)
                    cmp[site(lastvt[ii][jj])][site(nstr[i][j+1])]='>';
            }
            if(is_fin(nstr[i][j])&&!is_fin(nstr[i][j+1])) { //对于终结符在非终结符之前
                for(ii=0; ii<T; ii++) {
                    if(str[ii][0]==nstr[i][j+1])
                        break;
                }
                for(jj=0; jj<fcnt[ii]; jj++)
                    cmp[site(nstr[i][j])][site(firstvt[ii][jj])]='<';
            }
        }
    }
    for(i=0; fin[i]!='\0'; i++)
        printf("\t%c",fin[i]);
    puts("");
    for(i=0; i<cnt; i++) {
        printf("%c\t",fin[i]);
        for(j=0; j<cnt; j++) {
            if(cmp[i][j]!=0)
                printf("%c\t",cmp[i][j]);
            else
                printf(" \t");
        }
        puts("");
    }

}
void output(int i,int j,char *str) {
    printf("\t");
    for(int ii=i; ii<=j; ii++)
        printf("%c",str[ii]);
}

int isDX(char c)
{
    if(c>='A'&&c<='Z')
        return 1;
    return 0;
}
void exchange()
{
    int ecnt=0;
    for(int i=0;i<10;i++){
        int mcnt=0;
        for(int j=3;nstr[i][j]!='\0';j++){
            if(isDX(nstr[i][j])&&strlen(nstr[i])!=4)
                mstr[ecnt][mcnt++]='N';
            else if(!isDX(nstr[i][j]))
                mstr[ecnt][mcnt++]=nstr[i][j];
            else{
                break;
            }
        }
        mstr[ecnt][mcnt]='\0';
        if(strlen(mstr[ecnt])!=0)
        ecnt++;
    }
}
int get_process(char *st)//
{
    exchange();
    int len=strlen(st);
    int t=0;//栈内元素的个数
    int i=0,j;
    int bz=1;
    stac[0]='#';
    while(st[i]!='\0'){
        if(is_fin(stac[t])) j=t;
        else j=t-1;
        int a=site(stac[j]);
        int b=site(st[i]);
        if(cmp[a][b]=='<'||cmp[a][b]=='='){
            printf("\t%d",bz++);
            output(0,t,stac);
            printf("\t%c",cmp[a][b]);
            printf("\t%c",st[i]);
            output(i+1,len-1,st);
            printf("\t移进");
            puts("");
            t++;
            stac[t]=st[i];
            i++;
        }
        else if(cmp[a][b]=='>'){
            printf("\t%d",bz++);
           output(0,t,stac);
            printf("\t%c",cmp[a][b]);
            printf("\t%c",st[i]);
            output(i+1,len-1,st);
            printf("\t归约");
            puts("");
            int ii,jj,kk;
            int flag=0;
            for(ii=t;ii>=0;ii--){
                for(jj=0;jj<maxn;jj++){
                        int lee=strlen(mstr[jj]);
                        int kkn=0;
                    for(kk=lee-1;kk>=0;kk--){
                        if(stac[ii]==mstr[jj][kk]){
                            ii--;
                            kkn++;
                        }
                        else
                            break;
                    }
                    if(strlen(mstr[jj])==kkn){
                        t=ii+1;
                        stac[t++]='N';
                        stac[t]='\0';
                        t--;
                        flag=1;
                        break;
                    }
                    else{
                        ii=ii+kkn;
                    }
                }
                if(!flag){
                    printf("\t错误");
                    return 0;
                }
                else{
                    if(t==1&&st[i]=='#'){
                        printf("\t%d",bz++);
                        output(0,t,stac);
                        printf("\t=");
                        printf("\t%c",st[i]);
                        output(i+1,len,st);
                        printf("\t接受");
                        return 1;
                    }
                    break;
                }
            }
        }
    }
}
int main() {
    int T;
    int cnt=0;//终结符的个数
    memset(firstflag,0,sizeof(firstflag));
    memset(lastflag,0,sizeof(lastflag));
    memset(cmp,0,sizeof(cmp));
    scanf("%d",&T);
    for(int i=0; i<T; i++) {
        scanf("%s",str[i]);
        fcnt[i]=lcnt[i]=0;
    }
    for(int i=0; i<T; i++) {
        for(int j=0; str[i][j]!='\0'; j++) {
            if((str[i][j]<'A'||str[i][j]>'Z')&&(str[i][j]!='-'&&str[i][j]!='>')&&str[i][j]!='|')
                fin[cnt++]=str[i][j];
        }
    }
    fin[cnt++]='#';
    fin[cnt]='\0';
    printf("输出文法的Firstvt集和Lastvt集\n");
    output_firstvt(T);
    output_lastvt(T);
    printf("输出算符优先关系表\n");
    get_table(T,cnt);
    printf("请输入输入串\n");
    scanf("%s",st);
    printf("输出输入串的分析过程\n");
    printf("PS:分析过程每一列从左到右依次是:步骤 栈 有限关系 当前符号 剩余输入串 移进或规约\n\n");
    get_process(st);
    return 0;
}
/*
2
T->T,S|S
S->a|@|(T)
(a,a)#

3
B->BoT|T
T->TaF|F
F->nF|(B)|t|f
ntofat#
*/

这里写图片描述

  • 23
    点赞
  • 102
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
算符优先分析法是一种自下而上的语法分析方法,它可以用于分析和处理算术表达式、布尔表达式等。下面是算符优先分析法的实现步骤: 1. 定义终结和非终结:终结是指不能再分解的基本号,如数字、运算等;非终结是指可以分解成其他号的号,如表达式、语句等。 2. 定义运算之间的优先关系和结合性质:将运算按照优先级从高到低排列,相同优先级的运算再按照结合性质(左结合或右结合)进行排列。 3. 构造算符优先关系表:根据定义的运算符优先关系和结合性质,构造算符优先关系表。表中的行和列分别表示两个相邻的运算,表中的元素表示它们之间的优先关系(“<”表示优先级低,“>”表示优先级高,“=”表示优先级相等)。 4. 进行语法分析:将输入的表达式转换成一个个终结和非终结的序列,然后根据算符优先关系表进行分析。具体地,从左到右扫描输入序列,将扫描到的号压入栈中,同时比较栈顶号和下一个输入号之间的优先关系,如果栈顶号的优先级低于或等于下一个输入号的优先级,则将下一个输入号压入栈中;否则,从栈中弹出一个或多个号进行归约,直到栈顶号的优先级低于或等于下一个输入号的优先级。 5. 进行表达式求值:在进行归约时,如果遇到两个相邻的终结之间有一个运算,则可以对它们进行求值,并将结果压入栈中。最终,栈中只剩下一个值,即为表达式的值。 下面是一个简单的算符优先分析法的实现例子,用于分析和处理四则运算表达式: ```python # 定义终结和非终结 terminals = ['+', '-', '*', '/', '(', ')', 'num'] non_terminals = ['E', 'T', 'F'] # 定义运算之间的优先关系和结合性质 precedence = { '+': {'+': '>', '-': '>', '*': '<', '/': '<', '(': '<', ')': '>', 'num': '<'}, '-': {'+': '>', '-': '>', '*': '<', '/': '<', '(': '<', ')': '>', 'num': '<'}, '*': {'+': '>', '-': '>', '*': '>', '/': '>', '(': '<', ')': '>', 'num': '<'}, '/': {'+': '>', '-': '>', '*': '>', '/': '>', '(': '<', ')': '>', 'num': '<'}, '(': {'+': '<', '-': '<', '*': '<', '/': '<', '(': '<', ')': '=', 'num': '<'}, ')': {'+': '>', '-': '>', '*': '>', '/': '>', '(': ' ', ')': '>', 'num': ' '}, 'num': {'+': '>', '-': '>', '*': '>', '/': '>', '(': ' ', ')': '>', 'num': ' '} } # 构造算符优先关系表 table = {} for i in range(len(terminals)): table[terminals[i]] = {} for j in range(len(terminals)): table[terminals[i]][terminals[j]] = precedence[terminals[i]][terminals[j]] # 进行语法分析 def parse(expr): stack = ['#'] tokens = expr.split() for token in tokens: while table[stack[-1]][token] == '>': op = stack.pop() if op in ['+', '-', '*', '/']: b = stack.pop() a = stack.pop() stack.append(str(eval(a + op + b))) else: stack.pop() if table[stack[-1]][token] == '<' or table[stack[-1]][token] == '=': stack.append(token) else: raise ValueError('Invalid expression') while stack[-1] != '#': op = stack.pop() if op in ['+', '-', '*', '/']: b = stack.pop() a = stack.pop() stack.append(str(eval(a + op + b))) else: raise ValueError('Invalid expression') return stack[0] # 进行表达式求值 expr = '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3' result = parse(expr) print(result) # 输出:3.0001220703125 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rocky0429

一块也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值