c++词法分析器

将词法分析结果放入vector向量中,为语法分析做准备


// MyLex.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;

typedef struct{
	int syn;
	char name[10];
	double value;
} TOKEN;

void scaner();
int isnumber(char* s);
int isdigit(char c);
int isalpha(char c);
int isspace(char c);
void strappend(char *text,char c);
void skiperror();
void skipcomment();
void input();

char prog[200],token[100];
char *tok;
int syn;
double val = 0;
char *rwtab[9]={"main","int","float","double","char","if","else","do","while"};
vector<TOKEN> token_table;
char *ValidVar="非法变量";
char *NumError="数字错误";
char *UnknownTok="未知符号";
char eMsg[20];

int _tmain(int argc, _TCHAR* argv[]){
	TOKEN temp_token;

begin:
    memset(prog,0,sizeof(prog)); 
	token_table.clear();//清空向量里的元素
    syn = 100;
    printf("请输入语句:\n");
    input();//获取输入字符串
	printf("(%5s,%5s)\n","编码","符号");
    tok = prog;
    do{
        scaner();
		temp_token.syn=syn;
		if( syn==20){
			temp_token.value=val;
		}else{
			strcpy(temp_token.name,token);
		}
		token_table.push_back(temp_token);
    }while (syn!=0);

	for(int i = 0; i < token_table.size();i++){
		switch(token_table[i].syn){
			case 20: printf("(%2d,%8g)\n",token_table[i].syn,token_table[i].value);break;  
			case -1: printf("(-1,%8s)\n", token_table[i].name);break;
			default: printf("(%2d,%8s)\n",token_table[i].syn,token_table[i].name);break;
		}
	}

	getchar();
    char ans;
    printf("继续?(Y/N):");
	//清空getchar()缓冲区
    fflush(stdin);
    ans = getchar();
    if(ans == 'Y' || ans == 'y'){
		putchar('\n');
		//跳转到开始再次执行词法分析
        goto begin;
    }
	getchar();
	return 0;
}
//获取输入字符串
void input(){
    char c;
    do{
        c=getchar();
        strappend(prog,c);
    }while(c!='#');
}

void scaner(){
    //清空token
    memset(token,0,sizeof(token));
	memset(eMsg,0,sizeof(eMsg));
    //跳过空白字符
	for(;isspace(*tok);tok++){}
	//跳过注释
	skipcomment();
	//跳过空白字符
	for(;isspace(*tok);tok++){}

    //变量或关键字
    if(isalpha(*tok)){
        strappend(token,*tok);
        tok ++;
        for(;isalpha(*tok) || isdigit(*tok);tok++){
            strappend(token,*tok);
        }
        // 变量
        syn = 10;
        for(int n = 0; n < 9; n++){
            //关键字
            if(strcmp(token,rwtab[n]) == 0){
                syn = n + 1;
                return;
            }
        }
    }
    //数字
    else if(isnumber(tok)) {
		
        val=0;//数值
        int flag = 1;//正负号
        int e = 0;//指数
        int sign = 1;//指数符号

        if(*tok == '+'){
            flag = 1;
			strappend(eMsg,*tok);
            tok++;
        }else if(*tok == '-'){
            flag = -1;
			strappend(eMsg,*tok);
            tok++;
        }
        for(;isdigit(*tok);tok++){
            val = val * 10 + (*tok)  - '0';
			strappend(eMsg,*tok);
        }
        //浮点数
        if(*tok == '.'){
			strappend(eMsg,*tok);
            tok++;
			//小数点后不带数字为错误并且返回
			if(!isdigit(*tok)){
				strcpy(token,NumError);
				strcat(token,":");
				strcat(token,eMsg);
				return;
			}
            for(;isdigit(*tok);tok++){
                val = val * 10 + (*tok) - '0';
                e --;
				strappend(eMsg,*tok);
            }
        }
		//科学计数法
        if(*tok == 'e' || *tok == 'E'){
			strappend(eMsg,*tok);
            tok ++;

            int i = 0;
            if(*tok == '+'){
                sign = 1;
				strappend(eMsg,*tok);
                tok ++;
            }
            else if(*tok == '-'){
                sign = -1;
				strappend(eMsg,*tok);
                tok ++;
            }

			if(!isdigit(*tok)){//如果不是数字,错误
				syn = -1;
				strcpy(token,NumError);
				strcat(token,":");
				strcat(token,eMsg);
				return;
			}
            for(;isdigit(*tok);tok++){
                i = i * 10 + (*tok) - '0';
            }
            e += sign * i;
        }
		
		//计算出数字的值
        while(e > 0){
            val *= 10.0;
            e --;
        }
        while(e < 0){
            val *= 0.1;
            e ++;
        }
        val *= flag;
        syn=20;
/*
        似乎是语法分析的内容
		数字后出现字母
        if(isalpha(*tok)){
			ErrorType = NumError;
			syn=-1;
			//跳过数字后的所以字母
			skiperror();
			return;
		}
*/
    }
    else switch(*tok){
        case'<':strappend(token,*tok);tok++;
            switch(*tok){
//              case '>':syn = 21; strappend(token,*tok);tok++;break;
                case '=':syn = 35; strappend(token,*tok);tok++;break;
                default: syn = 34; break;
            }
            break;
        case'>':strappend(token,*tok);tok++;
            switch(*tok){
                case '=': syn = 33; strappend(token,*tok);tok++;break;
                default:  syn = 32; break;
            }
            break;
/*木有冒号了,T_T
        case':':strappend(token,*tok);tok++;
            switch(*tok){
                case '=': syn = 18; strappend(token,*tok);tok++;break;
                default:  syn = 17; ;break;
            }
            break;
*/
		case'!':
			strappend(token,*tok);tok++;
			switch(*tok){
				case '=': syn = 37; strappend(token,*tok);tok++;break;
				default:  syn = -1; break;
			}
			break;
		case '=':
			strappend(token,*tok);tok++;
			switch(*tok){
				case '=':syn=36;strappend(token,*tok);tok++;break;
				default: syn=21;break;
			}
			break;
        case'+':syn=22;token[0]=*tok++;break;
        case'-':syn=23;token[0]=*tok++;break;
        case'*':syn=24;token[0]=*tok++;break;
        case'/':syn=25;token[0]=*tok++;break;
//      case'=':syn=21;token[0]=*tok++;break;
        case';':syn=31;token[0]=*tok++;break;
        case'(':syn=26;token[0]=*tok++;break;
        case')':syn=27;token[0]=*tok++;break;
        case',':syn=30;token[0]=*tok++;break;
		case'#':syn=0 ;token[0]=*tok++;break;
		case'{':syn=28;token[0]=*tok++;break;
		case'}':syn=29;token[0]=*tok++;break;
		case'[':syn=40;token[0]=*tok++;break;
		case']':syn=41;token[0]=*tok++;break;
		default: syn=-1;tok++;strcpy(token,UnknownTok);strcat(token,":");strappend(token,*(tok-1));break;
    }
}

//向字符串添加字符
void strappend(char* des,char c){
    int pos = strlen(des);
    *(des + pos) = c;
    *(des + pos + 1) = '\0';
}

//有符号数字
int isnumber(char *s){
	//如果上个单词是数字或变量,+—当作运算符,否则按符号
	if(syn == 11 || syn == 20){
		return isdigit(*tok);
	}
    return (*s=='+' || *s =='-') && isdigit(*(tok+1)) || isdigit(*s);
}

//空格字符
int isspace(char c){
    return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f' || c == '\0');
}

//字母
int isalpha(char c){
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}


//数字
int isdigit(char c){
	return c >= '0' && c <= '9';
}

//跳过错误字符
//此方法不使用
void skiperror(){
	for(;isdigit(*tok) || isalpha(*tok) || *tok == '.' || *tok == '_';tok++){}
}

//跳过注释
void skipcomment(){
	if(*tok=='/' && *(tok+1)=='*'){
		tok+=2;
		while(*tok!='\0' && *tok!='#'){
			if(*tok=='*' && *(tok+1)=='/'){
				tok+=2;
				return;
			}
			tok++;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值