一.算符优先分析法即是一种针对算符优先文法的分析方法。
二.如果一个文法的任一产生式的右部都不存在两个相邻的非终结符,则称这个文法为算符文法(OG)。
三.假定文法G是一个不含e的算符文法,a,b∈Vt,P,Q,R∈Vn,满足:
(一)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...,a∈Vt,Q∈Vn}
LastVt(P)={a|P加号推导...a或者P加号推导...aQ,a∈Vt,Q∈Vn}
(二)假如一个产生式存在Q->...aP...的形式,那么对于任意b∈First(P),有a<b
假如一个产生式存在Q->...Pa...的形式,那么对于任意b∈Last(P),有a<b
(三)若存在产生式P->a...或者P->Qa...,则a∈First(P)
若存在产生式P->Q...,对于任意a∈First(Q),有a∈First(P)
若存在产生式P->...a或者P->...aQ,则a∈Last(P)
若存在产生式P->...Q,对于任意a∈Last(Q),有a∈Last(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