算符优先分析法的简单实现

本文详细介绍了算符优先分析法,包括算符优先文法的概念、关系定义、FirstVt和LastVt的计算,以及如何构造算符优先分析表进行分析。通过实例展示了算符优先分析法在解决表达式解析问题中的应用,并讨论了代码实现中的注意事项和测试结果。
摘要由CSDN通过智能技术生成

一.算符优先分析法即是一种针对算符优先文法的分析方法。

二.如果一个文法的任一产生式的右部都不存在两个相邻的非终结符,则称这个文法为算符文法(OG)。

三.假定文法G是一个不含e的算符文法,a,bVt,P,Q,RVn,满足:

(一)a=b当且仅当文法G含有形如P->...ab...或者P->...aQb...的产生式

(二)a<b当且仅当文法G含有形如P->...aR...的产生式,且R加号推导b...或者R加号推导Qb...

(三)a>b当且仅当文法G含有形如P->...Rb...的产生式,且R加号推导...a或者R加号推导...aQ

文法G中任何非终结符号对(a,b)至多满足上述三种关系之一,则称文法G为算符优先文法(operator precedence grammar)

四.(一)FirstVt(P)={a|P加号推导a...或者P加号推导Qa...,aVt,QVn}

              LastVt(P)={a|P加号推导...a或者P加号推导...aQ,aVt,QVn}

    (二)假如一个产生式存在Q->...aP...的形式,那么对于任意bFirst(P),有a<b

              假如一个产生式存在Q->...Pa...的形式,那么对于任意bLast(P),有a<b

    (三)若存在产生式P->a...或者P->Qa...,则aFirst(P)

              若存在产生式P->Q...,对于任意aFirst(Q),有aFirst(P)

              若存在产生式P->...a或者P->...aQ,则aLast(P)

              若存在产生式P->...Q,对于任意aLast(Q),有aLast(P)

五.求出算符优先关系,构造算符优先分析表,#<任意其它算符,任意其它算符>#,#=#

六.1.初始化:#入栈,在输入串尾部加上#,栈顶指针p,输入串头指针为s

    2.p指向的符号为非终结符则下移,为终结符(记为a)则执行步骤3

    3.s指向的符号记为b,查算符优先分析表,若(a,b)为<或者=,则将s指向的符号入栈,若为>则执行步骤4

    4.从栈顶开始向下找两个终结符c,d(c靠近栈顶,c和d之间不存在其它终结符,c和d相邻或者其间只有非终结符),查表若(d,c)为=,则继续向下找终结符e,将d,e重新记为c,d,重复步骤4,若(d,c)为<则执行步骤5,若为空则不匹配,输入串不是该文法的句子

    5.d上面到栈顶的所有符号为最左素短语,可归约为非终结符,栈顶指针p指向这个非终结符,s指向下一个符号,栈中只存在一个非终结符和#,输入串只剩下#,则归约完毕输入串是该文法的句子,否则执行步骤2

 

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define TERMINAL_SYMBOL_MAX_NUM 10
#define FIRST_VT_SET_MAX_NUM TERMINAL_SYMBOL_MAX_NUM
#define LAST_VT_SET_MAX_NUM TERMINAL_SYMBOL_MAX_NUM
#define STRING_MAX_LENGTH 10
typedef enum{false, true} bool;
typedef struct right{
    char c;
    int label;//-1表示非终结符,0和正整数表示在终结符数组中的下标
    struct right *next;
    struct right *pre;
}*PRight, Right;//产生式右部
typedef struct grammar{
    char left_symbol;
    Right *right_head;
    Right *right_tail;
    struct grammar *next;
}*PGrammar, Grammar;//文法产生式
typedef struct str{
    char c;
    struct str *next;
}*PStr, Str;//输入串
typedef struct non_terminal{
    char c;
    bool isFirstInvariant;
    bool isLastInvariant;
    bool firstVtSet[FIRST_VT_SET_MAX_NUM];
    bool lastVtSet[LAST_VT_SET_MAX_NUM];
    struct non_terminal *next;
}*PNon_terminal, Non_terminal;//非终结符
typedef Right Stack;
typedef Stack* PStack;
char terminal_symbol[TERMINAL_SYMBOL_MAX_NUM];
char operator_precedence[TERMINAL_SYMBOL_MAX_NUM][TERMINAL_SYMBOL_MAX_NUM];//算符优先关系表
Grammar *head_Grammar, *tail_Grammar;
Non_terminal *head_Non_terminal, *tail_Non_terminal;
void ReadGrammar(FILE *fp);
void FindAllNonTerminal();
bool IsNonTerminal(char c);
void FindAndMark();
void FindAllTerminal();
bool IsNewTerminal(Right *pR);
void FirstLastVtSet();//计算非终结符firstVt和lastVt集
void AddFirstLast(Non_terminal *pN, Right *pR, bool type);//false表示添加first,true表示添加last
void OPATable();//构建算符优先分析表
void Input(Str *s);
void Judge(Str *s);
void PrintGrammar();
void PrintSymbol();
void PrintFirstLastVtSet();
void PrintOPATable();
void PrintJudge(Stack *pS, Stack *last_terminal, Str *p, int i);
int main(int argc, char *argv[])
{
    FILE *fp = NULL;
    Str *s;
    if((fp=fopen("OPG.txt", "r")) == NULL)
    {
        printf("File open failed!\n");
        exit(1);
    }
    s = (PStr)malloc(sizeof(Str));
    s->next = NULL;
    head_Grammar = NULL;
    tail_Grammar = NULL;
    head_Non_terminal = NULL;
    tail_Non_terminal = NULL;
    memset(operator_precedence, '\0', TERMINAL_SYMBOL_MAX_NUM*TERMINAL_SYMBOL_MAX_NUM*sizeof(char));
    ReadGrammar(fp);
    PrintGrammar();
    FindAllNonTerminal();
    FindAndMark();
    FindAllTerminal();
    PrintSymbol();
    FirstLastVtSet();
    PrintFirstLastVtSet();
    OPATable();
    PrintOPATable();
    Input(s);
    Judge(s);
    fclose(fp);
    return 0;
}
void ReadGrammar(FILE *fp)
{
    char ch;
    Grammar *pG = NULL;
    Right *pR = NULL;
    bool one_production = false;//标记一个产生式是否读取完毕,是针对一条语句中有|可以分解为多条产生式的情况,true表示读取到|,这条语句后面至少还有一个和当前产生式左部非终结符相同的产生式,false则表示一条语句读取完毕初值为false,因为开始读取时是一条语句的开始
    while(!feof(fp))
    {
        pG = (PGrammar
  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值