语法分析程序

Posted fulianzhou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了语法分析程序相关的知识,希望对你有一定的参考价值。

工程代码http://download.csdn.net/detail/fulianzhou/9541833

config.h

/*****  *********/
#ifndef _CONFIG_H_
#define _CONFIG_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

//#define LEX_OUTPUT

#define MAXSTRLEN        1024	
#define UNDEFINE_DATA    -1

// 单词类型
const enum TYPE{
	em_start = 1,// #
	em_add,  // +
 	em_sub,  // -
 	em_mul,  // *
	em_div,  // /
	em_equ,  // =

	em_left, // ( 
	em_right, // )

	em_int,  // int
	em_real, // real
	
	em_mark, // mark

	em_sem,  // ;
	em_com,  // ,

	em_default, // 无法识别
};

// 元素数据
typedef struct {
	TYPE type;
	char *name;
	union{
		int int_dat;
		double real_dat;
	}value;
}ElemType;

// 优先关系表
const char g_cPriorList[10][10]={
    /*     +    -    *    /    =    (    )    i    V    #      */
/* + */   '>', '>', '<', '<', ' ', '<', '>', '<', '<', ' ',        // 0
/* - */   '>', '>', '<', '<', ' ', '<', '>', '<', '<', ' ',        // 1
/* * */   '>', '>', '>', '>', ' ', '<', '>', '<', '<', ' ',        // 2
/* / */   '>', '>', '>', '>', ' ', '<', '>', '<', '<', ' ',        // 3
/* = */   '<', '<', '<', '<', ' ', '<', '>', '<', '<', ' ',        // 4
/* ( */   '<', '<', '<', '<', ' ', '<', '=', '<', '<', ' ',        // 5
/* ) */   '>', '>', '>', '>', ' ', ' ', '>', ' ', ' ', '>',        // 6
/* i */   '>', '>', '>', '>', ' ', ' ', '>', ' ', ' ', '>',        // 7
/* V */   '>', '>', '>', '>', '=', ' ', '>', ' ', ' ', '>',        // 8
/* # */   '>', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '<', '=',        // 9
};

// 查询优先关系表,得优先关系
char GetPrior(TYPE left,TYPE right);
// 形成数据
ElemType FormElemData(char *name,TYPE type,double data);
// 显示元素内容
void DispElem(ElemType item);

#endif

config.cpp

#include "config.h"

// 形成数据结点
ElemType FormElemData(char *name,TYPE type,double data){
	ElemType item;
	item.name = (char*)calloc(sizeof(char),strlen(name)+1);
	strcpy(item.name,name);
	item.type = type;
	if(item.type == em_int) item.value.int_dat = (int)data;
	else if(item.type == em_real) item.value.real_dat = data;
	else item.value.real_dat = data;

	return item;
}

// 显示元素内容
void DispElem(ElemType item){
	printf("(%s,%d,%g)\\n",item.name,item.type,item.type == em_int ? item.value.int_dat : item.value.real_dat);
}

// 根据有限关系表获取坐标值
static int GetPos(TYPE type){
	switch(type){
		case em_add:return 0;
		case em_sub:return 1;
		case em_mul:return 2;
		case em_div:return 3;
		case em_equ:return 4;
		case em_left:return 5;
		case em_right:return 6;
		case em_int:
		case em_real:return 7;
		case em_mark:return 8;
		case em_start:return 9;
	}
	return -1;
}

// 查询优先关系表,得优先关系
char GetPrior(TYPE left,TYPE right){
	int iLeft = GetPos(left);
	int iRight = GetPos(right);
	if(iLeft >= 0 && iRight >= 0){
		return g_cPriorList[iLeft][iRight];	
	}
	else{
		printf("Error, can not recognition type.\\n");
		return '-';
	}
}

grammar_analysis.h

#ifndef _GRAMMAR_ANALYSIS_H_
#define _GRAMMAR_ANALYSIS_H_

#include "config.h"
#include "linklist.h"
#include "linkstack.h"


// 语法分析
int Grammar_Analysis(PT_List list);

#endif

grammar_analysis.cpp
#include "grammar_analysis.h"

static int Grammar_CheckFormat(PT_List list){
	int i;
	TYPE t1,t2;
	int l = LinkList_GetLength(list);
	TYPE t = LinkList_GetNode(list,1)->data.type;
	if(!(t == em_int || t==em_real || t==em_left)) return 0;
	
	for(i=1;i < l;i++){

		if(LinkList_GetNode(list,i)->data.type == em_mark) return 0;
		if(LinkList_GetNode(list,i)->data.type == em_default) return 0;
		if(LinkList_GetNode(list,i)->data.type == em_equ) return 0;
		if(i>1 && i < l){
			t1 = LinkList_GetNode(list,i-1)->data.type;
			t2 = LinkList_GetNode(list,i)->data.type;	
			if((t1 == em_left && t2 == em_right) || (t1 == em_right && t2 == em_left))  // (),)(
				return 0;
			if((t1 == em_add || t1 == em_sub || t1 == em_mul || t1 == em_div) && 
			   (t2 == em_add || t2 == em_sub || t2 == em_mul || t2 == em_div)) // ++,+-,+/...
			   return 0;
			if(t1 == em_int || t1 == em_real){
				if(t2 == em_add || t2 == em_sub || t2 == em_mul || t2 == em_div || t2 == em_right)
				{}
				else // 2 2,2(,
					return 0;
			}
			if(t1 == em_add || t1 == em_sub || t1 == em_mul || t1 == em_div){
				if(t2 == em_int || t2 == em_real || t2 == em_left){
				}
				else // +),++,...
					return 0;
			}
		}
	}
	return 1;
}

// 计算
Data EvaluateExpression(PT_List ptlist,int *flag)
{
	int iIndex = 3;
	int len = LinkList_GetLength(ptlist);
	//printf("len = %d\\n",len);
	*flag = 1;     // 先置为合格

	ElemType tmpData;
	LinkList OPTR,OPND;
	ListInit(OPTR);            //寄存运算符
	ListInit(OPND);            // 寄存数字

	Push_sign(OPTR,em_start);
	/* 获取下一个 */
	if(iIndex < len){ /*  */ 
		tmpData = LinkList_GetNode(ptlist,iIndex)->data;
		//printf("GetNode: iIndex:%d,name:%s\\n",iIndex,tmpData.name);
		iIndex++;
	}
	else{
		tmpData.type = em_start;
	}
	if(tmpData.type == em_int || tmpData.type == em_real){
		Push_num(OPND,tmpData.type == em_int ? atoi(tmpData.name):atof(tmpData.name));//Push_num(OPND,tmpData.value.real_dat);

		/* 获取下一个 */
		if(iIndex < len){ /*  */ 
			tmpData = LinkList_GetNode(ptlist,iIndex)->data;
			//printf("GetNode: iIndex:%d,name:%s\\n",iIndex,tmpData.name);
			iIndex++;
		}
		else{
			tmpData.type = em_start;
		}
	}
	while(tmpData.type != em_start || Get_top_sign(OPTR) != em_start)
	{
		if(tmpData.type == em_int || tmpData.type == em_real){
			Push_num(OPND,tmpData.type == em_int ? atoi(tmpData.name):atof(tmpData.name));

			/* 获取下一个 */
			if(iIndex < len){ /*  */ 
				tmpData = LinkList_GetNode(ptlist,iIndex)->data;
				//printf("GetNode: iIndex:%d,name:%s\\n",iIndex,tmpData.name);
				iIndex++;
			}
			else{
				tmpData.type = em_start;
			}
		}
		switch(/*GetPrior*/Precede(Get_top_sign(OPTR),tmpData.type))
		{
		case '<':
			Push_sign(OPTR,tmpData.type);

			/* 获取下一个 */
			if(iIndex < len){ /*  */ 
				tmpData = LinkList_GetNode(ptlist,iIndex)->data;
				//printf("GetNode: iIndex:%d,name:%s\\n",iIndex,tmpData.name);
				iIndex++;
			}
			else{
				tmpData.type = em_start;
			}
			break;
		case '=':
			Pop_sign(OPTR);

			/* 获取下一个 */
			if(iIndex < len){ /*  */ 
				tmpData = LinkList_GetNode(ptlist,iIndex)->data;
				//printf("GetNode: iIndex:%d,name:%s\\n",iIndex,tmpData.name);
				iIndex++;
			}
			else{
				tmpData.type = em_start;
			}
			break;
		case '>':{
			double s = Operate(Pop_num(OPND),Pop_sign(OPTR),Pop_num(OPND));
			//printf("s = %g\\n",s);
			Push_num(OPND,s);
			break;
				 }
		case '-':
		case ' ': // 出现不合法的语法单元,退出
			*flag = 0;
			break;
		}
		if(*flag == 0) {
			//printf("flag = 0,break;\\n");
			break;
		}
	}
	//printf("Out!tmpdata.type = %d,top sign=%d\\n",tmpData.type,Get_top_sign(OPTR));
	return Pop_num(OPND);
}

// 语法分析
int Grammar_Analysis(PT_List list){
	PT_List  ptlist = list;
	if(!(LinkList_GetNode(ptlist,1)->data.type == em_mark && LinkList_GetNode(ptlist,2)->data.type == em_equ)){
		LinkList_DispAllRaw(list);
		printf("\\t --> can not calculate.\\n");
		return 0;
	}
	else
	{
		ptlist=ptlist->next;
		ptlist=ptlist->next;
		if(Grammar_CheckFormat(ptlist) == 0) {
			LinkList_DispAllRaw(list);
			printf("\\t --> can not calculate.\\n");
			return 0;
		}	
	}		
	int flag = 1;
	double sum = EvaluateExpression(list,&flag);

	LinkList_DispAllRaw(list);
	if(flag){
		printf("\\t --> %s%s%g;\\n",LinkList_GetNode(list,1)->data.name,LinkList_GetNode(list,2)->data.name,sum);
	}
	else puts("\\t --> can not calculate.\\n");
	return 0;
}

lexical_analysis.h 

#ifndef _LEXICAL_ANALYSIS_
#define _LEXICAL_ANALYSIS_

#include "config.h"
#include "linklist.h"

// 词法分析
PT_List ParseWord(char strInput[]);
#endif

Lexical_analysis.cpp

/*
   输入串必须以'#'号结尾
*/

#include "lexical_analysis.h"
#include "linklist.h"

/* 类别标志 */
TYPE g_type = em_default;

void OutputStr(char str[],int flag){
	switch(flag){
		case em_int:fprintf(stdout,"(%s,%d)\\t整数\\n",str,flag);break;
		case em_real:fprintf(stdout,"(%s,%d)\\t实数\\n",str,flag);break;
		case em_default:fprintf(stdout,"(%s,%d)\\t无法识别\\n",str,flag);break;
		case em_mark:fprintf(stdout,"(%s,%d)\\t标识符\\n",str,flag);break;
	}
}

// 解析单词
PT_List ParseWord(char strInput[]){
	int i,j;
	char strTemp[MAXSTRLEN] = { 0 };        // 临时数组,用于保存单词
	int iLen = 0;                           // 临时数组长度
	int iDot;                               // 小数点出现标识符
	PT_List ptlist = (PT_List)calloc(sizeof(T_List),1);
	LinkList_Init(ptlist);

	g_type = em_default;                    // 标志为未处理

	for(i=0;strInput[i] && strInput[i] != '#';i++){
		if(isdigit(strInput[i])){                  // 如果是数字
			iDot = 0;                              // 小数点没有出现过
			memset(strTemp,0,sizeof(strTemp));     // 清空临时数组
			iLen = 0;                              // 临时数组长度为0
			g_type = em_int;                       // 标志为整数

			for(j=i;strInput[i] && strInput[j] != '#';j++){
				if(strInput[j] == '.'){            // 如果出现小数点x
					if(iDot == 0){                 // 如果小数点没有出现过
						iDot = 1;                  // 标识为小数点已经出现
						strTemp[iLen++] = strInput[j];  // 存在临时数组中
						g_type = em_default;            // 标志为无法识别
					}
					else{                                // 第二次出现小数点出错
						j--;
						break;
					}
				}
				else if(isdigit(strInput[j])){     // 如果是数字
					strTemp[iLen++] = strInput[j];
					if(g_type == em_default)
						g_type = em_real;
				}
				else{
					j--;
					break;
				}
			}
#ifdef LEX_OUTPUT
			OutputStr(strTemp,g_type);
#endif	
			if(g_type == em_default){
				LinkList_AddNode(ptlist,FormElemData(strTemp,g_type,UNDEFINE_DATA));			
			}
			else{
				LinkList_AddNode(ptlist,FormElemData(strTemp,g_type,g_type == em_int ? atoi(strTemp) : atof(strTemp)));
			}
			memset(strTemp,0,sizeof(strTemp));     // 清空临时数组
			iLen = 0;                              // 临时数组长度为0
			i = j;
		}
		else if(isalpha(strInput[i])){             // 如果是以字母开头
			memset(strTemp,0,sizeof(strTemp));
			iLen = 0;
			g_type = em_mark;                   // 标记为标识符
			for(j=i;strInput[i] && strInput[j] != '#';j++){
				if(isalpha(strInput[j]) || isdigit(strInput[j])){        // 如果是数字或者字母
					strTemp[iLen++] = strInput[j];
				}
				else{          
					j--;// 否则
					break; 
				}
			}
#ifdef LEX_OUTPUT
			OutputStr(strTemp,g_type);
#endif
			LinkList_AddNode(ptlist,FormElemData(strTemp,g_type,UNDEFINE_DATA));
			iLen = 0;
			memset(strTemp,0,sizeof(strTemp));
			i = j;
		}
		else if(isspace(strInput[i])) continue;
		else{
			switch(strInput[i]){
				case '+':g_type = em_add;break;
				case '-':g_type = em_sub;break;
				case '*':g_type = em_mul;break;
				case '/':g_type = em_div;break;
				case '=':g_type = em_equ;break;
				case ';':g_type = em_sem;break;
				case ',':g_type = em_com;break;	
				case '(':g_type = em_left;break;
				case ')':g_type = em_right;break;
				default:g_type = em_default;
			}
			strTemp[0] = strInput[i];
			strTemp[1] = '\\0';
			LinkList_AddNode(ptlist,FormElemData(strTemp,g_type,UNDEFINE_DATA));
#ifdef LEX_OUTPUT
			fprintf(stdout,"(%c,%d)",strInput[i],g_type);	
			if(g_type == em_add  || g_type == em_sub || g_type == em_mul || g_type == em_div || g_type == em_equ)    
				printf("\\t运算符\\n");
			else if(g_type == em_sem || g_type == em_com) 
				printf("\\t界符\\n");
			else
				printf("\\t无法识别\\n");
#endif
		}
	}	
	return ptlist;
}

linklist.h

#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#include "config.h"

typedef struct tLNode{
	tLNode *next;
	ElemType data;
}T_List,*PT_List;

// 添加结点
int LinkList_AddNode(PT_List ptlist,ElemType item);
// 初始化链表
void LinkList_Init(PT_List ptlist);
// 添加结点
int LinkList_AddNode(PT_List ptlist,ElemType item);
// 显示所有节点
void LinkList_DispAll(PT_List ptlist);
// 获取链表长度
int LinkList_GetLength(PT_List ptlist);
// 获取指定位置结点
PT_List LinkList_GetNode(PT_List ptlist,int pos);
// 显示所有节点名字
void LinkList_DispAllRaw(PT_List ptlist);
// 销毁链表
void LinkList_Destroy(PT_List ptlist);
#endif

Linklist.cpp

#include "linklist.h"


// 初始化链表
void LinkList_Init(PT_List ptlist){
	ptlist->data = FormElemData("<head>",em_default,UNDEFINE_DATA);
	ptlist->next = NULL;
}

// 添加结点
int LinkList_AddNode(PT_List ptlist,ElemType item){
	PT_List tmplist = ptlist;
	while(tmplist->next != NULL){
		tmplist = tmplist->next;
	}
	PT_List newNode = (PT_List)calloc(sizeof(T_List),1);
	newNode->next = NULL;
	newNode->data = item;

	tmplist->next = newNode;
	return 1;
}

// 显示所有节点
void LinkList_DispAll(PT_List ptlist){
	PT_List tmplist = ptlist;
	while(tmplist->next != NULL){
		tmplist = tmplist->next;
		DispElem(tmplist->data);
	}
}
// 显示所有节点名字
void LinkList_DispAllRaw(PT_List ptlist){
	PT_List tmplist = ptlist;
	while(tmplist->next != NULL){
		tmplist = tmplist->next;
		//DispElem(tmplist->data);
		printf("%s",tmplist->data.name);
	}
}
// 获取链表长度
int LinkList_GetLength(PT_List ptlist){
	int len = 0;
	PT_List tmplist = ptlist;
	while(tmplist->next != NULL){
		tmplist = tmplist->next;
		len++;
	}
	return len;
}

// 获取指定位置结点
PT_List LinkList_GetNode(PT_List ptlist,int pos){
	if(pos <= 0 || pos > LinkList_GetLength(ptlist)){
		printf("Out of range.\\n");
		return NULL;
	}
	int num = 1;
	PT_List tmpList = ptlist;
	while(tmpList->next != NULL && num <= pos){
		tmpList = tmpList->next;
		num++;
	}
	return tmpList;
}

// 获取下一个
PT_List LinkList_GetNext(PT_List ptlist){
	if(ptlist->next != NULL){
		PT_List tmpList = ptlist;
		ptlist = ptlist->next;
		return tmpList;
	}
	return NULL;
}

// 销毁链表
void LinkList_Destroy(PT_List ptlist){
	while(ptlist->next){
		PT_List tmplist = ptlist;
		ptlist = ptlist->next;
		free(tmplist);
	}
	free(ptlist);
}

linkstack.h

#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_

#define OK 1
#define NO 0
#define ERROR 0
#define OVERFLOW -1
typedef TYPE   Sign;
typedef int    Status;
typedef double Data;

typedef struct LNode
{
	Sign sign;
	Data num;
	struct LNode *prior;
}LNode,*LinkList;

//初始化
Status ListInit(LinkList &L);
//数字入栈   
Status Push_num(LinkList &L,Data e);
//字符入栈
Status Push_sign(LinkList &L,Sign e);
// 字符出栈 
Sign Pop_sign(LinkList &L); 
//数字出栈
Data Pop_num(LinkList &L);          
// 判断栈空
Status Empty(LinkList L);
// 得栈顶字符元素
Sign Get_top_sign(LinkList L);
// 判断优先性  
char Precede(TYPE c1,TYPE c2);
// 运算
double Operate(double x,TYPE c,double y);                         
#endif

linkstack.cpp

#include "config.h"
#include "linkstack.h"

Status ListInit(LinkList &L)    ///初始化
{
	L=(LinkList)malloc(sizeof(LNode));
	L->prior=NULL;
	return OK;
}

Status Push_num(LinkList &L,double e)         ///数字入栈
{
	LinkList p=(LinkList)malloc(sizeof(LNode));
	p->num=e;
	p->prior=L;
    L=p;
	//printf("Push_num:%.2f\\n",e);
	return OK;
}
Status Push_sign(LinkList &L,Sign e)          /// 字符入栈
{
	LinkList p=(LinkList)malloc(sizeof(LNode));
	p->sign=e;
	p->prior=L;
	L=p;
	//printf("Push_sign:%d\\n",e);
	return OK;
}
Sign Pop_sign(LinkList &L)                      /// 字符出栈
{
	if(L->prior!=NULL)
	{
		LinkList p=L;
		Sign x=L->sign;
		L=L->prior;
		free(p);
		//printf("Pop_sign:%d\\n",x);
		return x;
	}
}
Data Pop_num(LinkList &L)                   ///数字出栈
{
	if(L->prior!=NULL)
	{
		LinkList p=L;  
		Data a=L->num;
		L=L->prior;
		free(p);
		//printf("Pop_num:%g\\n",a);
		return a;
	}
}
Status Empty(LinkList L)                    /// 判断栈空
{
	if(L->prior==NULL) return 1;
	return 0;
}
Sign Get_top_sign(LinkList L)               /// 得栈顶字符元素
{
	if(L->prior!=NULL)  
		return L->sign;
}
char Precede(TYPE c1,TYPE c2)                 /// 判断优先性
{
	if((c1==em_add||c1== em_sub) && (c2==em_add||c2==em_sub||c2==em_right||c2==em_start))                     
		return '>';
	else if((c1==em_add||c1==em_sub) && (c2==em_mul||c2==em_div||c2==em_left))                         
		return '<';

	if((c1==em_mul||c1==em_div) && (c2==em_add||c2==em_sub||c2==em_mul||c2==em_div||c2==em_right||c2==em_start))   
		return '>';
	else if((c1==em_mul||c1==em_div) && c2==em_left )											   
		return '<'; 

	if(c1==em_left && (c2==em_add||c2==em_sub||c2==em_mul||c2==em_div||c2==em_left))                       
		return '<';
	else if(c1==em_left && c2==em_right)                                                        
		return '=';

	if(c1==em_right)                                                                        
		return '>';

	if(c1==em_start && c2==em_start)                                                             
		return '=';
	else
		return '<';
}

// 运算
double Operate(double x,TYPE type,double y){
	double s = 0;
	switch(type){
		case em_add:s = x + y;break;
		case em_sub:s = x - y;break;
		case em_mul:s = x * y;break;
		case em_div:s = x / y;break;
	}
	return s;
}

main.cpp

#include "lexical_analysis.h"
#include "grammar_analysis.h"

int main(int argc,char *argv[]){
	char strInput[MAXSTRLEN] = { 0 };
	char c;
	int  iLen = 0;
	
	printf("Input lines.\\n\\tevery sentence end by ';',end of '#':\\n");

	while(1){
		memset(strInput,0,sizeof(strInput));
		iLen = 0;
		c = 0;
		while((c = (char)getc(stdin)) != '#') strInput[iLen++] = c;
		strInput[iLen] = '\\0';
		PT_List ptList = ParseWord(strInput);
		int listlen = LinkList_GetLength(ptList);
		//printf("length = %d\\n",listlen);
		puts("lexical analysis:");
		LinkList_DispAll(ptList);

		puts("");
		puts("grammar analysis:");
		int n = 1;
		ElemType e;
		while(n <= LinkList_GetLength(ptList)){
			PT_List list = (PT_List)calloc(sizeof(T_List),1);
			LinkList_Init(list);	
			while(n < listlen && (e = LinkList_GetNode(ptList,n)->data).type != em_sem){                 // 找出一句
				LinkList_AddNode(list,e);
				n++;
			}
			LinkList_AddNode(list,LinkList_GetNode(ptList,n)->data);
			n++;
			/* 开始语法分析 */
			Grammar_Analysis(list);
			LinkList_Destroy(list);
		}
		printf("\\ninput new lines:\\n");
	}
	return 0;
}



以上是关于语法分析程序的主要内容,如果未能解决你的问题,请参考以下文章

JSP语法

JSP开发中的基础语法

在下面的代码片段中的剩余 ='passthrough' 处的代码中出现语法错误

编译原理-第二章 一个简单的语法指导编译器-2.4 语法制导翻译

微信小程序第七天WXML语法之模板用法

微信小程序第七天WXML语法之模板用法