⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lexer.c

📁 采用递归下降的语法分析器
💻 C
字号:
#include<stdio.h>
#define OD c=='+'||c=='-'||c=='*'||c=='/'
#define RELOP c=='<'||c=='>'||c=='='
#define SPACE c=='\0'||c=='\n'||c=='\t'||c==' '
int state=0,start=0;
int strmax=0;
char buf[1000];//缓冲区;
char *foward=buf; //指向缓冲区的两指针;
char *begin=buf;
int line=1;
struct S              
{
char word[100];
int va;
}smptable[100];//设置大小为100的符号表;

int lookup(char *s){                                      
    int i;
    for (i=0;i<strmax;i++){
        if (strcmp(smptable[i].word,s)==0) return i;
    }
    return -1;
}//符号表中查找字符串S,有返回位置,没有返回-1;

int insert(char *s,int value){
   int i=lookup(s);
   if(i==-1)                                       //符号表中没有这个字符串;
   {
        strcpy(smptable[strmax].word,s);
		smptable[strmax].va=value;
       return strmax++;
   }
   return i;
}//在符号表中插入s,并将s标记为记号value;

char nextchar()
{
	return *(foward++);
}//超前抄描字符;

void retract()
{
foward--;
}//回流;

void install_id()
{
char a[100]="";
strncpy(a,begin,foward-begin);
begin=foward;
if(lookup(a)<=10&&lookup(a)>=0) printf("%d  %s\n",0,a); //区别标示符与关键字,前11个为关键字
//输出标记为0;
else {insert(a,1);printf("%d  %s\n",1,a);}  //1为标示符;
}//识别标示符;

void install_num()
{
char a[100]="";
strncpy(a,begin,foward-begin);
begin=foward;
printf("%d  %s\n",2,a);
insert(a,2);
}//识别数字;

void install_relop()
{
char a[100]="";
strncpy(a,begin,foward-begin);

begin=foward;

printf("%d  %s\n",3,a);
insert(a,3);
}//识别关系运算符;

void install_operate()
{
char a[100]="";
strncpy(a,begin,foward-begin);
begin=foward;
printf("%d  %s\n",4,a);
insert(a,4);
}//识别操作运算符;

void recover()
{
printf("error in line %d\n",line);
while(*foward!=' '&&*foward!='\t'&&*foward!='\n'&&*foward!='\0'\
&&*foward!='>'&&*foward!='='&&*foward!='<'&&*foward!='+'&&*foward!='-'\
&&*foward!='*'&&*foward!='/'&&*foward!=';'&&*foward!=','&&*foward!=':')
{
foward++;
}
begin=foward;
start=0;state=0;
}//提示错误,并继续处理后面的输入;
char c;
int fail()
{
foward=begin;
switch(start){
case 0:start=9;break;
case 9:start=12;break;
case 12:start=20;break;
case 20:start=25;break;
case 25:start=28;break;
default:recover();
}
return start;
}//找出下一个开始状态;

int nexttoken()
{state=0;
start=0;

while(1)
{
	switch(state){
	case 28:c=nextchar();
		if(c==' '||c=='\t')state=28;
		else if(c=='\n'){state=28;line++;}
		else  state=29;
		break;
	case 29:retract();
		if(*foward=='\0')  return 0;
		else state=fail();
		break;
	case 0:c=nextchar();
		if(c==' '||c=='\t'){
			state=0;
			begin++;
		}
		else if(c=='\n') {state=0;begin++;line++;}
		else if(c=='<')state=1;
		else if(c=='=')state=5;
		else if(c=='>')state=6;
		else if(c==';')state=30;
		else if(c==':')state=31;
        else if(OD||c=='('||c==')'||c==',')state=34;
		else state=fail();
		break;
	case 1:c=nextchar();
		if(c=='=') state=2;
		else if(c=='>')state=3;
		else state=4;
		break;
	case 2:
	case 3:
		install_relop();//调用install_relop(),输出操作符;
		if(*(foward-1)=='\0')   return 0;
		 else return 1;
	case 4:retract();install_relop();
		if(*(foward-1)=='\0')   return 0;
		 else return 1;
	case 5:
		install_relop();
		if(*(foward-1)=='\0')   return 0;
		 else return 1;
	case 6:c=nextchar();
		if(c=='=') state=7;
		else state=8;
		break;
    case 7:
		install_relop();
		if(*(foward-1)=='\0')   return 0;
		 else return 1;
	case 8:retract();install_relop();
		if(*(foward-1)=='\0')   return 0;
		 else return 1;
	case 9:c=nextchar();
		if(isalpha(c)) state=10;
		else state=fail();
		break;
	case 10:c=nextchar();
		if(isalpha(c)||isdigit(c)) state=10;
		
		else if(OD||RELOP||SPACE||c==';'||c==',') state=11;
        else if(c==':') state=35;
		else state=fail();
		break;
	case 11:retract();install_id();//调用install_id(),输出关键字或标识符;
		if(*foward=='\0')   return 0;
		 else return 1;
    
	  break;
	case 35: c=nextchar();
	if(c=='=') {retract();state=11;}
	else recover();
	break;
	case 12:c=nextchar();
		if(isdigit(c))state=13;
		else state=fail();
		break;
	case 13:c=nextchar();
		if(isdigit(c)) state=13;
		else if(c=='.') state=14;
		else if(c=='E'||c=='e') state=14;
        else state=fail();
		break;
	case 14:c=nextchar();
		if(isdigit(c)) state=15;
        else state=fail();
		break;
	case 15:c=nextchar();
        if(isdigit(c)) state=15;
		else if(c=='E'||c=='e') state=16;
		else state=fail();
		break;
	case 16:c=nextchar();
		if(c=='+'||c=='-') state=17;
		else if(isdigit(c)) state=18;
        else state=fail();
	case 17:c=nextchar();
		if(isdigit(c)) state=18;
        else state=fail();
		break;
	case 18:c=nextchar();
		if(isdigit(c)) state=18;
		else state=19;
		break;
	case 19:retract();install_num();//调用install_num(),输出数字;
		if(*foward=='\0')  return 0;
		 else return 1;
	case 20:c=nextchar();
		if(isdigit(c)) state=21;
		else state=fail();
		break;
    case 21:c=nextchar();
		if(isdigit(c)) state=21;
		else if(c=='.')state=22;
        else state=fail();
		break;
	case 22:c=nextchar();
		if(isdigit(c))state=23;
        else state=fail();
		break;
	case 23:c=nextchar();
		if(isdigit(c)) state=23;
		else state=24;
		break;
    case 24:retract();install_num();//调用install_num(),输出数字;
		if(*foward=='\0')  return 0;
		 else return 1;
	case 25:c=nextchar();
		if(isdigit(c)) state=26;
		else state=fail();
		break;
    case 26:c=nextchar();
		if(isdigit(c)) state=26;
		else state=27;
		break;
    case 27:retract();install_num();//调用install_num(),输出数字;
		if(*foward=='\0')  return 0;
		else return 1;
	case 30:install_relop();
		if(*(foward-1)=='\0')   return 0;
		 else return 1;
	case 31:c=nextchar();
		if(c=='=') state=32;
		else state=fail();
		break;
	case 32:install_relop();
		if(*(foward-1)=='\0')   return 0;
		 else return 1;
	case 33:retract();install_relop();
		if(*(foward-1)=='\0')   return 0;
		 else return 1;
    case 34:install_operate();
		if(*(foward-1)=='\0')   return 0;
		 else return 1;

	}	
}
}//根据状态图进行词法分析;

void keyword()
{
insert( "const",0);
insert("var",0);
insert("procedure",0);
insert("call",0);
insert("begin",0);
insert("end",0);
insert("if",0);
insert("then",0);
insert("while",0);
insert("do",0);
insert("odd",0);
}//初始化符号表,插入关键字,置关键字为0;

/*************************词法分析lexer.c*************************/
int main()
{ 
int a=1;
int i;
keyword();
freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
for(i=0;i<1000;i++)
	scanf("%c",&buf[i]);
while(a)
a=nexttoken();  //一直调用,直到遇到'\0'退出;
free(buf);
exit(0); 
return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -