📄 pl0.cpp
字号:
#include "Pl0.h"
//////////////////////////////////////////////////////////
Pl0::Pl0(char *fileName, bool debugOn, bool outputOn){
// must declaration before DEBUG is called.
if (outputOn == true)
#define OUTPUT OUTPUT //output信息
if (debugOn == true)
#define DEBUG DEBUG //调试信息
#ifdef OUTPUT
out.open("output.txt");
#endif
#ifdef DEBUG
debugOut.open("debug.txt"); //, ios_base::out
#endif
counter = 0;
DEBUG(1, "->Pl0();");
fin.open(fileName);
lineNum = 0;
lineLen = 0;
charCount =0;
number =0;
sourceEnd = false;
ch = ' ';
token[0] = '\0';
lastIdentLen = identMaxLen;
codeIndex = 0;
errorCount=0;
/////////////////////////
strcpy(word[1],"begin");//13个关键字
strcpy(word[2],"call");
strcpy(word[3],"const");
strcpy(word[4],"do");
strcpy(word[5],"end");
strcpy(word[6],"if");
strcpy(word[7],"odd");
strcpy(word[8],"procedure");
strcpy(word[9],"read");
strcpy(word[10],"then");
strcpy(word[11],"var");
strcpy(word[12],"while");
strcpy(word[13],"write");
wsym[1]= BEGINSYM;//13个关键字所对应的类型
wsym[2]=CALLSYM;
wsym[3]= CONSTSYM;
wsym[4]=DOSYM;
wsym[5]=ENDSYM;
wsym[6]=IFSYM;
wsym[7]=ODDSYM;
wsym[8]=PROCSYM;
wsym[9]=READSYM;
wsym[10]=THENSYM;
wsym[11]=VARSYM;
wsym[12]=WHILESYM;
wsym[13]=WRITESYM;
ssym['+'] = PLUS;
ssym['-'] = MINUS;
ssym['*'] = TIMES;
ssym['/'] = SLASH;
ssym['('] = LPAREN;
ssym[')'] = RPAREN;
ssym['='] = EQL;
ssym[','] = COMMA;
ssym['.'] = PERIOD;
ssym['<'] = LSS;
ssym['>'] = GTR;
ssym[';'] = SEMICOLON;
ssym['#']=NEQ;
declbegsys.insert(CONSTSYM);//分程序的first集
declbegsys.insert(VARSYM);
declbegsys.insert(PROCSYM);
statbegsys.insert(BEGINSYM);//语句的first集
statbegsys.insert(CALLSYM);
statbegsys.insert(IFSYM);
statbegsys.insert(WHILESYM);
statbegsys.insert(READSYM);
statbegsys.insert(WRITESYM);
statbegsys.insert(IDENT);
facbegsys.insert(IDENT);//因子的first集
facbegsys.insert(NUMBER);
facbegsys.insert(LPAREN);
//目标代码的8种类型
strcpy(mnemonic[LIT], "LIT"); //LIT 0,a 取常量a放到数据栈顶
strcpy(mnemonic[OPR], "OPR"); //OPR 0,a 执行运算,a表示执行何种运算
strcpy(mnemonic[LOD], "LOD"); //LOD l,a 取变量(相对地址为a,层次差为l)放到数据栈栈顶
strcpy(mnemonic[STO], "STO"); //STO l,a 将数据栈顶内容存入变量()
strcpy(mnemonic[CAL], "CAL"); //CAL l,a 调用过程(入口指令地下为a,层次差为l)
strcpy(mnemonic[INT], "INT"); //INT 0,a 数据栈栈顶指针加a
strcpy(mnemonic[JMP], "JMP"); //JMP 0,a 无条件转移到a
strcpy(mnemonic[JPC], "JPC"); //JPC 0,a 条件转移
getsym();
DEBUG(-1, "->Pl0();");
}
Pl0::~Pl0() { //close file
DEBUG(1, "->~Pl0();");
fin.close();
debugOut.close();
out.close();
DEBUG(-1, "->~Pl0();");
}
void Pl0::getch()
{
// DEBUG(1, "->Getch();");
if (charCount >= lineLen) {
if (fin.eof()) {
sourceEnd = true;
return;
}
charCount = 0;
fin.getline(lineBuffer,lineMaxLen);
cout << lineNum+1 << " " << lineBuffer << endl;
OUTPUT(lineBuffer, lineNum+1);
DEBUG(0, lineBuffer);
lineLen = strlen(lineBuffer);
lineNum++;
}
ch = lineBuffer[charCount];
if (ch >= 'A' && ch <= 'Z') //转化为小写字母
ch = tolower(ch);
charCount++;
// DEBUG(-1, "->Getch();");
}
void Pl0::getsym () {//保证ch中始终有一个字符
if (sourceEnd == true)
return;
DEBUG(1, "<-getsym ();");
while ( ch == ' ' || ch == 9 || ch == 0) //'\0' 是空格
getch(); //skip space and tab
//////////////////////////////////////////
if ( isalpha(ch) ) {
int k;
for (k=0; isalpha(ch) || isdigit(ch); k++) {
token[k] = ch;
getch();
}
token[k] = '\0';
/* if (k > lastIdentLen)
lastIdentLen = k;
else {
for (; k< lastIdentLen; k++)
token[k]= '*';
token[k] = '\0';
}
*/
strcpy(id, token);
DEBUG(0, token,lineNum);
sym = IDENT; //未用二分法查找
for (k =1; k < numReservedWord+1; k++) {
if (strcmp (word[k],token) == 0) {
sym = wsym[k];
}
}
}
////////////////////////////////////////
else if ( isdigit(ch) ) {
int k = 0;
number = 0;
sym = NUMBER;
while ( isdigit(ch) ) {
number = number*10 + (int)ch - (int)('0');
getch();
k++;
}
if (k > numMaxLen)
error(29); //数的位数多于14位
DEBUG(0, "number = ",number);
}
//////////////////////////////////////////
else if ( ch == ':') {
getch();
if (ch == '=') {
sym = BECOMES;
getch();
}
else
error(28);
}
else if ( ch == '<' ) {
getch();
if (ch == '=') {
sym = LEQ;
getch();
}
else sym = LSS;
}
else if ( ch == '>' ) {
getch();
if (ch == '=') {
sym = GEQ;
getch();
}
else sym = GTR;
}
else {
switch(ch){
case '#':
sym=NEQ;
break;
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;
default:
error(27);
}
getch();
}
//cout<<"<----"<<lineNum<<"------"<<sym<<endl;
DEBUG(0, "sym=",(int)sym);
DEBUG(-1, ">-getsym ();");
}
///////////////////////////////////////////////
void Pl0::gen(fct x, int y, int z)//生成目标代码
{
DEBUG(1, "<-gen();");
if (codeIndex > cxMax) {
cout << "Program too long." << endl;
DEBUG(-1, "Program too long.");
return;
}
code[codeIndex].func = x;
code[codeIndex].lev = y;
code[codeIndex].addr = z;
codeIndex++;
DEBUG(0, mnemonic[x], y, z);
DEBUG(-1, ">-gen();");
}
//////////////////////////////////////////////
void Pl0::error(int i)
{
DEBUG(1, "<-error();");
cout << "****Line <" << lineNum -1//<<"----"<<charCount<<"---"<<ch
<< "> "
<< errorInfo[i]
<< endl;
DEBUG(0, "******************************Line: ", lineNum);
// DEBUG(0, errorInfo[i]); //不是数组,是字符串
#ifdef DEBUG
debugOut << errorInfo[i] <<endl;
#endif
errorCount++;
DEBUG(-1, ">-error();");
}
void Pl0::printTable()
{
int i;
for(i=1;i<=tablenum;i++){
cout<<"table表的第"<<i<<"行为: NAME: "<<table[i].name<<" KIND: ";
switch((int)table[i].kind){
case 0:
cout<<"CONSTANT";
break;
case 1:
cout<<"VARIABLE";
break;
case 2:
cout<<"PROCEDURE";
break;
default:
break;
}
cout<<" VAL: "<<table[i].val<<" LEV: "<<table[i].level<<" ADR: "<<table[i].addr<<endl;
cout<<endl;
}
}
void Pl0::enter(object kind, int &tableIndex,int &dataIndex, int &lev)//登记标识符
{
DEBUG(1, "<-enter();");
tableIndex++;
strcpy(table[tableIndex].name, id);
table[tableIndex].kind = kind; //所有类型都有名字和属性
switch(kind) {
case CONSTANT:
if (number > numMax) {
error(31);//超过所允许的最大数
number = 0;
}
table[tableIndex].val = number; //常量必须是数字,具有数值
table[tableIndex].addr=-1; //-1代表没有
table[tableIndex].level = -1;
break;
case VARIABLE:
table[tableIndex].level = lev; //变量有值和地址
table[tableIndex].addr = dataIndex;
table[tableIndex].val =-1;
dataIndex++; //需要增加分配的空间
break;
case PROCEDURE:
table[tableIndex].level = lev; //过程有层,地址后面再补上
table[tableIndex].val = -1;
break;
default:
break;
}
DEBUG(-1, ">-enter();");
}
int Pl0::getError()
{
return errorCount;
}
int Pl0::position(char *id, int tableIndex) //查找变量
{
DEBUG(1, "<-position();");
int i;
strcpy(table[0].name, id); //第一个为空,用于终止循环查找
i = tableIndex;
while (strcmp(table[i].name, id) != 0) //strcmp(),相等返回0
i--;
DEBUG(-1, ">-position();");
return i;
}
void Pl0::test(symset s1, symset s2, int n)
{
if (sourceEnd == true)
return;
DEBUG(1, "<-test();");
if (s1.find(sym) == s1.end()) { // sym 不在 s1
error(n);
symset::iterator it_s2;
for (it_s2 = s2.begin(); it_s2 != s2.end(); it_s2++)
s1.insert(*it_s2); // s1 += s2;
while (s1.find(sym) == s1.end()) { //sym 不在 s1
getsym();
if (sourceEnd == true) //
return;
}
}
DEBUG(-1, ">-test();");
}
void Pl0::block1(symset fsys, int tableIndex, int lev)//代码生成、语法分析、语义分析模块 分程序
{
if (sourceEnd == true)
return;
DEBUG(1, "<-block();");
int dataIndex=3; //地址分配下标, 从 3开始
int tableIndex0 = tableIndex; //初始化table表下标
int codeIndex0 = 0; //initial code index //初始化为0
table[tableIndex].addr = codeIndex;
gen(JMP,0,0); //跳转到操作部分
if (lev > levMax)
error(30);
symset follow;
follow.insert(SEMICOLON);
follow.insert(PERIOD);
test(fsys,follow,37);
do {
//常量处理部分
if (sym == CONSTSYM) {
getsym();
do {
constDeclaration(tableIndex, dataIndex, lev);
while(sym == COMMA) {
getsym();
constDeclaration(tableIndex, dataIndex, lev);
}
if (sym == SEMICOLON) { //常量声明部分结束
getsym();
}
else {
error(5);
}
} while(sym == IDENT);
}
//变量处理部分
if (sym == VARSYM) {
getsym();
do {
varDeclaration(tableIndex, dataIndex, lev); //与常量声明类似
while(sym == COMMA) {
getsym();
varDeclaration(tableIndex, dataIndex, lev);
}
if (sym == SEMICOLON) {
getsym();
}
else {
error(5);
}
} while(sym == IDENT);
}
//过程处理部分
while(sym == PROCSYM) {
getsym();
if (sym == IDENT) {
enter(PROCEDURE, tableIndex, dataIndex, lev); //过程的层没变
getsym();
}
else error(4);
if (sym == SEMICOLON)
getsym();
else error(5);
block1(fsys, tableIndex,lev+1);
}
} while(declbegsys.find(sym) != declbegsys.end());//检测是否还有常量、变量、过程声明
code[table[tableIndex0].addr].addr = codeIndex; //跳转到语句代码操作区
table[tableIndex0].addr = codeIndex; //代码操作开始地址
codeIndex0 = codeIndex;
gen(INT, 0, dataIndex); //申请的数据区
statement(statbegsys, tableIndex, lev);
if(lev>0)
{
if(sym!=SEMICOLON&&sym!=PERIOD)
error(38);
else{
getsym();
}
}
gen(OPR, 0, 0);
//test(follow,fsys,38);
tablenum=tableIndex;
//listCode(codeIndex0);
DEBUG(-1, ">-block();");
}
void Pl0::block(symset fsys,int tableIndex, int lev)
{
fsys.insert(IDENT);//语句的首符集
fsys.insert(IFSYM);
fsys.insert(CALLSYM);
fsys.insert(WHILESYM);
fsys.insert(READSYM);
fsys.insert(WRITESYM);
fsys.insert(CONSTSYM);
fsys.insert(VARSYM);
fsys.insert(PROCSYM);
fsys.insert(BEGINSYM);
block1(fsys,tableIndex, lev);
if(sym!=PERIOD)//检测主程序结束字符
error(38);
}
void Pl0::constDeclaration(int &tableIndex, int &dataIndex, int &lev)//常量定义
{
DEBUG(1, "<-constDeclaration();");
if (sym == IDENT) {
getsym();
if (sym >= EQL && sym <= BECOMES) {
if (sym == BECOMES)
error(1);
getsym();
if (sym == NUMBER) {
enter(CONSTANT, tableIndex, dataIndex, lev);
getsym();
}
else error(2);
}
else error(3);
}
else error(4);
DEBUG(-1, ">-constDeclaration();");
}
void Pl0::varDeclaration(int &tableIndex, int &dataIndex, int &lev)//变量定义
{
DEBUG(1, "<-varDeclaration();");
if (sym == IDENT) { //检测是否是标识符
enter(VARIABLE, tableIndex, dataIndex, lev);
getsym();
}
else error(4);
DEBUG(-1, ">-varDeclaration();");
}
void Pl0::listCode(int codeIndex0)
{
DEBUG(1, "<-listCode();");
for (int i = codeIndex0; i <= codeIndex - 1; i++) {
cout << "-->" << i
<< " " << mnemonic[code[i].func]
<< " " << code[i].lev
<< " " << code[i].addr
<< endl;
OUTPUT("-->", mnemonic[code[i].func], i, code[i].lev, code[i].addr);
DEBUG(0, mnemonic[code[i].func], code[i].lev, code[i].addr);
}
DEBUG(-1, ">-listCode();");
}
void Pl0::statement(symset fsys, int tableIndex, int lev) //语句处理部分
{
if (sourceEnd == true)
return;
DEBUG(1, "<-statement()");
int i;
int codeIndex1;
int codeIndex2;
symset follow;
follow.insert(PERIOD);
follow.insert(SEMICOLON);
follow.insert(ENDSYM);
test(fsys,follow,7);
if (sym == IDENT) {
i = position(id, tableIndex);
if (i == 0) //could not find
error(11);
else if (table[i].kind != VARIABLE) {
error(12);
i = 0;
}
getsym();
if (sym == BECOMES)
getsym();
else error(13);
symset tempsys;
tempsys.insert(PLUS);
tempsys.insert(MINUS);
tempsys.insert(LPAREN);
tempsys.insert(IDENT);
tempsys.insert(NUMBER);
expression(tempsys, tableIndex, lev);
if (i != 0)
gen(STO, lev - table[i].level, table[i].addr);
}
else if (sym == CALLSYM) {//调用模块
getsym();
if (sym != IDENT)
error(14);
else {
i = position(id, tableIndex);
if (i == 0)
error(11);
else if (table[tableIndex].kind == PROCEDURE){
gen(CAL, lev - table[i].level, table[i].addr);
getsym();
}
else
error(15);
}
}
else if (sym == IFSYM) {
getsym();
symset tempsys;
tempsys.insert(ODDSYM);
tempsys.insert(PLUS);
tempsys.insert(MINUS);
tempsys.insert(LPAREN);
tempsys.insert(IDENT);
tempsys.insert(NUMBER);
condition(tempsys, tableIndex, lev);
if (sym == THENSYM)
getsym();
else
error(16);
codeIndex1 = codeIndex;
gen(JPC, 0, 0);
statement(fsys, tableIndex, lev);
code[codeIndex1].addr = codeIndex;
}
else if (sym == BEGINSYM) {
getsym();
statement(fsys, tableIndex, lev);
symset tempsys;
tempsys.insert(PERIOD);
tempsys.insert(SEMICOLON);
tempsys.insert(ENDSYM);
if(sym!=ENDSYM){
if(sym== SEMICOLON) {
getsym();
statement(fsys, tableIndex, lev);
while(sym!=ENDSYM)
{
if(sym== SEMICOLON)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -