📄 scanner.cpp
字号:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h> //定义屏幕操作函数
enum M{INT10,INT8,INT16,REAL10,REAL8,REAL16,IDN,ASG,ADD,SUB,MUL,DIV,EQ,GT,LT,LP,RP,SEMI,ERR,WHILE,IF,ELSE,DO,THEN};
//定义十进制、八进制、十六进制的整型和浮点型等数值的种别;以及变量、赋值符号、加减乘除、等于、大于、小于、左括号、右括号、分号以及出错
//函数声明
int scan(); //词扫描函数
void printToken(int kind); //最后的输出函数
int isdigit(char ch); //判断是否是数字
int isalpha(char ch); //判断是否是字母
int isKeyword(char *a); //判断是否是关键字
int isRight(char ch); //检查输入是否合法
void SaveSymbolList(char *a); //将标识符存入符号表symbolList
int isDEC(char *a); //判断是否为十进制整数
int isOCT(char *a); //判断是否为八进制整数
int isHEX(char *a); //判断是否为十六进制整数
int isRealDEC(char *a); //判断是否为十进制浮点数
int isRealOCT(char *a); //判断是否为八进制浮点数
int isRealHEX(char *a); //判断是否为十六进制浮点数
void clearToken(); //清空Token[]
void Reverse10(char *a); //将其他进制转换成整型,并转为十进制数,存入整数表intList
void ReverseReal10(char *a); //将其他进制转换成转为十进制数,存入浮点表floatList
//宏定义
char token[20];
char empty[20];
char symbolList[20][20]; //符号表
int intList[50]={0}; //存储整数,初值均为0
int i=-1; //控制token[]的数组下标变量
int input[100]; //存放输入的各种符号的单词种别
float floatList[50]={0}; //存储浮点数,初值均为0
int s=-1,n=-1; //n为整数表的下标量
int m=-1; // m为浮点数表的下标量
int en; //控制词法分析循环的使能变量
int iorf=0; //标定是浮点型还是整型
int t=0;
main() {
char yn=' ';
int kind;
int num;
while(1) {
en=1;
printf("\n");
printf("******************<Scanner for a tiny programming language>****************\n");
printf("please enter:\n");
while(en){
clearToken();
kind = scan(); //扫描词
input[t]=kind;
t++;
printToken(kind);
}
i=-1; //将i再次初始化
for(num=0;num<t;num++)
input[num]=0;
t=0;
printf("\n\n");
}
return 0;
}
int scan() {
char ch;
int key;
while(1) {
ch=getchar(); //读取一个字符
while(ch==' ') //若为空格,则跳过
ch=getchar(); //继续读取下一个
if(isRight(ch)==0&&ch!='\n') {
return ERR; //如果输入字符不合法,出错
}
else if(isdigit(ch)) { //如果第一个字符是数字
i++;
token[i]=ch; //将读入的字符存入暂存表
ch=getchar();
i++;
while(isdigit(ch)||ch=='x'||ch=='X'||(ch>='a'&&ch<='f')||(ch>='A'&&ch<='F')||ch=='.') { //继续读入后续的整数字符
token[i]=ch; //继续存入token
ch=getchar();
i++;
}
token[i]='\0'; //该词的结束
ungetc(ch,stdin); //把一个字符退回到输入流中
if(isDEC(token)) { //为十进制的数的输入格式
iorf=0;
n++;
Reverse10(token); //转化为真正的十进制数
if(ch=='\n') en=0;
return INT10;
}
else if(isOCT(token)) { //为八进制数的输入格式
iorf=0;
n++;
Reverse10(token); //转化为十进制数
if(ch=='\n') en=0;
return INT8;
}
else if(isHEX(token)){ //为十六进制的输入格式
n++;
iorf=0;
Reverse10(token); //转化为十进制数
if(ch=='\n') en=0;
return INT16;
}
else if(isRealDEC(token)) { //为十进制的浮点数的输入格式
iorf=1;
m++;
ReverseReal10(token); //转化为真正的十进制数
if(ch=='\n') en=0;
return REAL10;
}
else if(isRealOCT(token)) { //为八进制浮点数的输入格式
m++;
iorf=1;
ReverseReal10(token); //转化为十进制数
if(ch=='\n') en=0;
return REAL8;
}
else if(isRealHEX(token)){ //为十六进制的浮点数输入格式
m++;
iorf=1;
ReverseReal10(token); //转化为十进制数
if(ch=='\n') en=0;
return REAL16;
}
else { //出错
if(ch=='\n') en=0;
return ERR;
}
}
else if(isalpha(ch)) { //如果第一个字符是字母
i++;
s++;
token[i]=ch;
ch=getchar();
i++;
while(isalpha(ch) || isdigit(ch)) {
token[i]=ch;
ch=getchar();
i++;
}
token[i]='\0';
ungetc(ch,stdin);
key = isKeyword(token); //看是否为关键字
if(key==WHILE) {
if(ch=='\n') en=0;
return WHILE; //是关键字,则返回WHILE
}
if(key==DO) {
if(ch=='\n') en=0;
return DO; //是关键字,则返回DO
}
if(key==ELSE) {
if(ch=='\n') en=0;
return ELSE; //是关键字,则返回ELSE
}
if(key==IF) {
if(ch=='\n') en=0;
return IF; //是关键字,则返回IF
}
if(key==THEN) {
if(ch=='\n') en=0;
return THEN; //是关键字,则返回THEN
}
else {
SaveSymbolList(token); //将token存入符号表
if(ch=='\n') en=0;
return IDN; //返回标识符
}
}
else if(ch==':') { //如果第一个字符是冒号
i++;
token[i]=ch;
ch=getchar();
i++;
if(ch=='=') {
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return ASG; //返回付值号
}
else {
if(ch=='\n') en=0;
return ERR; //出错
}
}
else if(ch=='+') { //加号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return ADD;
}
else if(ch=='-') { //减号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return SUB;
}
else if(ch=='*') { //星号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return MUL;
}
else if(ch=='/') { //除号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return DIV;
}
else if(ch=='=') { //等于号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return EQ;
}
else if(ch=='>') { //大于号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return GT;
}
else if(ch=='<') { //小于号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return LT;
}
else if(ch=='(') { //左括号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return LP;
}
else if(ch==')') { //右括号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return RP;
}
else if(ch==';') { //分号
i++;
token[i]=ch;
i++;
token[i]='\0';
if(ch=='\n') en=0;
return SEMI;
}
}
}
void printToken(int kind) { //打印
printf("\n");
switch(kind) {
case INT10:printf("%s: < INT10, %d >",token,intList[n]);
break;
case INT8: printf("%s: < INT8, %d >",token,intList[n]);
break;
case INT16:printf("%s: < INT16, %d >",token,intList[n]);
break;
case REAL10:printf("%s: < REAL10, %f >",token,floatList[m]);
break;
case REAL8: printf("%s: < REAL8, %f >",token,floatList[m]);
break;
case REAL16:printf("%s: < REAL16, %f >",token,floatList[m]);
break;
case WHILE: printf("%s: < WHILE, - > ",token);
break;
case DO: printf("%s: < DO, - > ",token);
break;
case IF: printf("%s: < IF, - > ",token);
break;
case ELSE: printf("%s: < ELSE, - > ",token);
break;
case THEN: printf("%s: < THEN, - > ",token);
break;
case IDN: printf("%s: < IDN, %s >",symbolList[s],symbolList[s]);
break;
case ASG: printf("%s: < %s, - >",token,token);
break;
case ADD: printf("%s: < %s, - >",token,token);
break;
case SUB: printf("%s: < %s, - >",token,token);
break;
case MUL: printf("%s: < %s, - >",token,token);
break;
case DIV: printf("%s: < %s, - >",token,token);
break;
case EQ: printf("%s: < %s, - >",token,token);
break;
case GT: printf("%s: < %s, - >",token,token);
break;
case LT:printf("%s: < %s, - >",token,token);
break;
case LP: printf("%s: < %s, - >",token,token);
break;
case RP: printf("%s: < %s, - >",token,token);
break;
case SEMI: printf("%s: < %s, - >",token,token);
break;
case ERR: printf("ERROR!");
break;
default: break;
}
printf("\n");
}
int isRight(char ch) { //判断是否出错
if(((ch>='0')&&(ch<='9'))||((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||(ch=='+')||(ch=='-')||(ch=='*')||(ch=='/')||(ch=='=')||(ch=='<')||(ch=='>')||(ch=='(')||(ch==')')||(ch==':')||(ch==';'))
return 1;
else return 0;
}
int isdigit(char ch) { //判断是否为数字
if((ch>='0')&&(ch<='9'))
return 1;
else return 0;
}
int isDEC(char *a) { //判断是否为十进制整数
int x=0;
do {
if((a[0]=='0'&&a[1]=='\0')||(a[0]>'0'&&isdigit(a[x]))) {
x++;
continue;
}
else break;
} while(a[x]!='\0');
if(a[x]=='\0') return 1;
else return 0;
}
int isOCT(char *a) { //判断是否为八进制整数
int x=0;
do {
if(a[0]=='0'&&(a[x]>='0'&&a[x]<='7')) {
x++;
continue;
}
else break;
} while(a[x]!='\0');
if(a[x]=='\0'&&a[0]=='0') return 1;
else return 0;
}
int isHEX(char *a) { //判断是否为十六进制整数
int x=2;
do {
if((a[0]=='0')&&(a[1]=='x'||a[1]=='X')&&(isdigit(a[x])||(a[x]>='a'&&a[x]<='f')||(a[x]>='A'&&a[x]<='F'))) {
x++;
continue;
}
else break;
} while(a[x]!='\0');
if(a[x]=='\0'&&a[0]=='0'&&(a[1]=='x'||a[1]=='X')&&a[2]!='\0') return 1;
else return 0;
}
int isRealDEC(char *a) { //判断是否为十进制浮点数
int x=0;
do {
if((a[0]=='0'&&a[1]=='\0')||(a[0]=='0'&&a[1]=='.')||(a[0]>'0'&&(isdigit(a[x])||a[x]=='.'))) {
x++;
continue;
}
else break;
} while(a[x]!='\0');
if(a[x]=='\0') return 1;
else return 0;
}
int isRealOCT(char *a) { //判断是否为八进制浮点数
int x=0;
do {
if(a[0]=='0'&&a[1]!='.'&&((a[x]>='0'&&a[x]<='7')||a[x]=='.')) {
x++;
continue;
}
else break;
} while(a[x]!='\0');
if(a[x]=='\0'&&a[0]=='0') return 1;
else return 0;
}
int isRealHEX(char *a) { //判断是否为十六进制浮点数
int x=2;
do {
if((a[0]=='0')&&(a[1]=='x'||a[1]=='X')&&(isdigit(a[x])||(a[x]>='a'&&a[x]<='f')||(a[x]>='A'&&a[x]<='F')||a[x]=='.')) {
x++;
continue;
}
else break;
} while(a[x]!='\0');
if(a[x]=='\0'&&a[0]=='0'&&(a[1]=='x'||a[1]=='X')&&a[2]!='\0') return 1;
else return 0;
}
void Reverse10(char *a) { //将其他进制转换成整型,并转为十进制数,存入整数表intList[n]
int x=0;
int temp[80];
if(a[0]=='0'&&(a[1]=='x'||a[1]=='X')) { //如果为十六进制
while(a[x]!='\0') {
if(a[x]>='a'&&a[x]<='f') { //小写a-f,转为相应整型
temp[x]=a[x]-87;
x++;
}
else if(a[x]>='A'&&a[x]<='F') { //大写A-F,转为相应整型
temp[x]=a[x]-55;
x++;
}
else {
temp[x]=a[x]-48; //'0'-'9',转为整型
x++;
}
}
temp[x]=11111;
x=2;
while(temp[x]!=11111) {
intList[n]=intList[n]*16+temp[x]; //转为十进制
x++;
}
}
else if(a[0]=='0') { //如果为八进制
while(a[x]!='\0') {
temp[x]=a[x]-'0'; //转为整型
x++;
}
temp[x]=11111;
x=1;
while(temp[x]!=11111) {
intList[n]=intList[n]*8+temp[x]; //转为十进制
x++;
}
}
else { //为十进制
while(a[x]!='\0') {
temp[x]=a[x]-'0'; //转为整型
x++;
}
temp[x]=11111;
x=0;
while(temp[x]!=11111) {
intList[n]=intList[n]*10+temp[x];
x++;
}
}
}
void ReverseReal10(char *a) { //将其他进制整型转换成整型,并转为十进制数,存入整数表intList[n]
int x=0;
int point=0; //指明第几个字符是小数点
float p=0.1; //小数部分各位的级数
float pp=0.08;
float ppp=0.0625;
int temp[80];
if(a[0]=='0'&&(a[1]=='x'||a[1]=='X')) { //如果为十六进制
while(a[x]!='\0') {
if(a[x]=='.'){
point=x;
temp[x]=100; //因为十进制数的各个位上不可能出现10,所以用10来表示小数点所在的位置
x++;
}
else if(a[x]>='a'&&a[x]<='f') { //小写a-f,转为相应整型
temp[x]=a[x]-87;
x++;
}
else if(a[x]>='A'&&a[x]<='F') { //大写A-F,转为相应整型
temp[x]=a[x]-55;
x++;
}
else {
temp[x]=a[x]-48; //'0'-'9',转为整型
x++;
}
}
temp[x]=11111;
x=2;
while(temp[x]!=11111&&temp[x]!=100) { //整数部分的处理
floatList[m]=floatList[m]*16+temp[x];
x++;
}
if(temp[x]==100)
x++;
while(temp[x]!=11111){
floatList[m]=floatList[m]+temp[x]*ppp;
ppp=ppp/16;
x++;
}
}
else if(a[0]=='0'&&a[1]!='.') { //如果为八进制
while(a[x]!='\0') {
if(a[x]=='.'){
point=x;
temp[x]=10; //因为十进制数的各个位上不可能出现10,所以用10来表示小数点所在的位置
}
else
temp[x]=a[x]-'0'; //转为整型
x++;
}
temp[x]=11111;
x=1;
while(temp[x]!=11111&&temp[x]!=10) { //整数部分的处理
floatList[m]=floatList[m]*8+temp[x];
x++;
}
if(temp[x]==10)
x++;
while(temp[x]!=11111){
floatList[m]=floatList[m]+temp[x]*pp;
pp=pp*0.08;
x++;
}
}
else { //为十进制
while(a[x]!='\0') {
if(a[x]=='.'){
point=x;
temp[x]=10; //因为十进制数的各个位上不可能出现10,所以用10来表示小数点所在的位置
}
else
temp[x]=a[x]-'0'; //转为整型
x++;
}
temp[x]=11111;
x=0;
while(temp[x]!=11111&&temp[x]!=10) { //整数部分的处理
floatList[m]=floatList[m]*10+temp[x];
x++;
}
if(temp[x]==10)
x++;
while(temp[x]!=11111){
floatList[m]=floatList[m]+temp[x]*p;
p=p*0.1;
x++;
}
}
}
int isalpha(char ch) { //判断是否为字符
if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||ch=='_'||ch=='.')
return 1;
else return 0;
}
int isKeyword(char *a) { //关键字 if then else while do
if ((a[0]=='i')&&(a[1]=='f')&&(a[2]=='\0'))
return IF;
if ((a[0]=='t')&&(a[1]=='h')&&(a[2]=='e')&&(a[3]=='n')&&(a[4]=='\0'))
return THEN;
if ((a[0]=='e')&&(a[1]=='l')&&(a[2]=='s')&&(a[3]=='e')&&(a[4]=='\0'))
return ELSE;
if ((a[0]=='w')&&(a[1]=='h')&&(a[2]=='i')&&(a[3]=='l')&&(a[4]=='e')&&(a[5]=='\0'))
return WHILE;
if ((a[0]=='d')&&(a[1]=='o')&&(a[2]=='\0'))
return DO;
return 0;
}
void SaveSymbolList(char *a) { //存入符号表symbolList
int x=0;
do {
symbolList[s][x]=a[x];
x++;
}while(a[x-1]!='\0');
}
void clearToken(){
int t;
i=-1;
for(t=0;t<=19;t++)
token[t]=empty[t];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -