c++词法分析器

来源:互联网 发布:mysql如何查看 编辑:程序博客网 时间:2024/05/16 18:22

将词法分析结果放入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++;}}}