📄 wording.cpp
字号:
#include "StdAfx.h"
#include ".\wording.h"
#include "pl0.h"
#include "errors.h"
#include <string.h>
CWording::CWording(CPl0 *p)
{
wt=new word_table[16];
strcpy(wt[0].word,"begin");
//初始化保留字表
wt[0].sym=beginsym;
//保留字符号列表,在上面的保留字表中找到保留字后可以本表中相应位置该保留字的类型
strcpy(wt[1].word,"call");
wt[1].sym=callsym;
strcpy(wt[2].word,"const");
wt[2].sym=constsym;
strcpy(wt[3].word,"do");
wt[3].sym=dosym;
strcpy(wt[4].word,"end");
wt[4].sym=endsym;
strcpy(wt[5].word,"if");
wt[5].sym=ifsym;
strcpy(wt[6].word,"odd");
wt[6].sym=oddsym;
strcpy(wt[7].word,"procedure");
wt[7].sym=procsym;
strcpy(wt[8].word,"read");
wt[8].sym=readsym;
strcpy(wt[9].word,"then");
wt[9].sym=thensym;
strcpy(wt[10].word,"var");
wt[10].sym=varsym;
strcpy(wt[11].word,"while");
wt[11].sym=whilesym;
strcpy(wt[12].word,"write");
wt[12].sym=writesym;
strcpy(wt[13].word,"else");
wt[13].sym=elsesym;
strcpy(wt[14].word,"repeat");
wt[14].sym=repeatsym;
strcpy(wt[15].word,"until");
wt[15].sym=untilsym;
Create_ht(); //创建关键字的hash表
ch=' ';
line=1;
pl=p;
}
symbol CWording::GetSym()
{
FILE *fs = pl->fp;
CErrors *err = pl->errors;
int cc,pp; //cc表示读取到的字符数,pp指示是否为保留字及保留字号
symbol sym;
//跳过空格与换行
while (ch==' '||ch=='\t'||ch=='\n')
{
if (ch=='\n') line++;
ch = getc(fs);
}
//如果读出的字符是一个字母,说明是保留字或标识符
if (('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z'))
{
cc = 0;
do{
if (cc < IDENT_LENGTH) //如果标识符长度没有超过最大标识符长度(如果超过,就取前面一部分,把多余的抛弃)
id[cc++] = ch; //(如果超过,就取前面一部分,把多余的抛弃)
ch = getc(fs);
}while (('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z') || ('0'<=ch && ch<='9'));
//直到读出的不是字母或数字,由此可知PL/0的标识符构成规则是:以字母开头,后面跟若干个字母或数字
id[cc] = 0; //将最后一个字符设为0,作为标记
pp = HushScan(id); //查找保留字hush表,判断是否在其中,否则为标志符
sym = (pp>=0) ? wt[pp].sym : ident; //根据序号判断保留字号,pp为零时置为ident
}
//如果读出字符是数字
else if ('0'<=ch && ch<='9')
{
cc = 0;
num = 0;
sym = number;
do{
num = num*10+ch-'0'; //num * 10加上最近读出的字符ASCII减'0'的ASCII得到相应的数值
cc++;
ch=getc(fs);
}while ('0'<=ch && ch<='9');
if (cc > NUMBER_LENGTH) //如果组成的数字位数大于最大允许的数字位数
err->Add(30); //发出30号错误
if (num > MAX_NUMBER) //如果组成的数字大于最大允许的数字
{
err->Add(31); //发送31号错误
num=0;
}
}
//others
else if (ch == ':') //如果读出的不字母也不是数字而是冒号
{
ch = getc(fs);
if (ch=='=') //如果读到的是等号,正好可以与冒号构成赋值号
{
sym=becomes;
ch=getc(fs);
}
else
sym=nul;
}
else if (ch=='<') //如果读到小于号
{
ch=getc(fs);
if (ch=='=')
{
sym=leq;
ch=getc(fs); //购成一个小于等于号
}else if(ch == '>')
{
sym = neq;
ch = getc(fs); //构成不等号
}
else
sym=lss;
}
else if (ch=='>') //如果读到大于号,处理过程类似于处理小于号
{
ch=getc(fs);
if (ch == '=')
{
sym=geq;
ch=getc(fs);
}
else
sym=gtr;
}
else //说明它不是标识符/保留字,也不是复杂的双字节操作符,应该是一个普通的符号
{
switch (ch) //直接从符号表中查到它的类型,赋给sym
{
case '+':
sym=plus;
break;
case '-':
sym=minus;
break;
case '*':
sym=times;
break;
case '/':
sym=slash;
break;
case '(':
sym=lparen;
break;
case ')':
sym=rparen;
break;
case '=':
sym=eql;
break;
case ',':
sym=comma;
break;
case '.':
sym=period;
break;
case ';':
sym=semicolon;
break;
case EOF:
sym=endfile;
break;
default:
sym=nul;
}
ch=getc(fs);
}
return sym;
}
//以下是保留字的查找表处理的相关函数
void CWording::Create_ht()
{
for (int i=0; i<20; i++)
ht[i]=-1;
for (int i=0;i<16;i++)
ht[Hush(wt[i].word)]=i;
}
int CWording::Hush(char *s)
{
int a=s[1],b=s[2];
if (a>='a') a-='a'-'A';
if (b>='a') b-='a'-'A';
int h=a*2+b-100;
if (h==40) h=0;
else if(h==103) h=2;
h%=21;
if (h==20) h=3;
return h;
}
int CWording::HushScan(char *word)
{
int p=ht[Hush(word)];
if (p==-1) return -1;
if (stricmp(word,wt[p].word)!=0)
return -1;
return p;
}
CWording::~CWording(void)
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -