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