?? pl0parser.cpp
字號:
// Pl0Parser.cpp: implementation of the CPl0Parser class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "pl0.h"
#include "Pl0Parser.h"
#include "InputData.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPl0Parser::CPl0Parser()
{
}
CPl0Parser::~CPl0Parser()
{
}
static SymbolTable keys[]={
"const",MCONST,0,0,-2,0,
"var",VAR,0,0,-2,0,
"procedure",PROCEDURE,0,0,-2,0,
"call",CALL,0,0,-2,0,
"begin",BEGIN,0,0,-2,0,
"end",END,0,0,-2,0,
"if",IF,0,0,-2,0,
"then",THEN,0,0,-2,0,
"while",WHILE,0,0,-2,0,
"do",DO,0,0,-2,0,
"read",READ,0,0,-2,0,
"write",WRITE,0,0,-2,0,
0,0,0,0,-2,0
};
void CPl0Parser::pl0(const char *p)
//編譯器主程序,p指向待編譯的源程序,以'\0'結束
{
//編譯器初始化
pCurPosition=p; //置讀位置
pStrBuf=stringBuf; //取單詞緩沖區
for(int ix=0;ix<STRBUFLEN;ix++) stringBuf[ix]=0; //清字符串緩沖區
lineNo=1; //源程序行號
curLev=-1; //置當前層數
curParent=-1; //置當前外層
errOp=ERR_NUN; //錯誤標志
errStr=""; //錯誤信息
for(int i=0;keys[i].pName;i++) //填寫關鍵字于符號表中
table[i]=keys[i];
table[i]=keys[i];
code.intit(this); //初始化輸出的目標代碼表
code.gen("j",0,0); //生成第一條轉移指令
//編譯開始
NextToken(); //預取一個單詞,詞法分析子程序
program(); //分析“分程序”
match(DOT); //匹配符號"."
code.modify(0,stCode); //修改第一條指令轉移到程序的第一條語句
if(!errStr.IsEmpty())
MessageBox(0,errStr,"錯誤信息",0);
}
void CPl0Parser::NextToken()
//詞法分析
{
char ch=Getch(); //取一個有效字符
if(isalpha(ch))
getID(); //標識符處理
else if(isdigit(ch))
getNum(); //整型常數處理
else
switch(ch) //識別分隔符、運算符等
{
case ',':
tokKind=COMMA;
return;
case ';':
tokKind=SEMICOLON;
return;
case '=':
tokKind=EQ;
return;
case '(':
tokKind=LPAREN;
return;
case ')':
tokKind=RPAREN;
return;
case ':':
ch=Getch();
if(ch!='=')
{
errOp=ERR_UNGETC;
error("賦值語句缺少“=”!");
}
tokKind=ASSIGNOP;
return;
case '<':
ch=Getch();
if(ch=='=')
tokKind=LE;
else
{
tokKind=LT;
unGetch();
}
return;
case '>':
ch=Getch();
if(ch=='=')
tokKind=GE;
else
{
unGetch();
tokKind=GT;
}
return;
case '#':
tokKind=NE;
return;
case '+':
tokKind=PLUSOP;
return;
case '-':
tokKind=MINUSOP;
return;
case '*':
tokKind=MULTOP;
return;
case '/':
tokKind=DIVOP;
return;
case '.':
tokKind=DOT;
return;
}
}
char CPl0Parser::Getch()
{
while(1)
{
switch(*pCurPosition)
{
case '\n':
lineNo++;
case '\r':
case ' ':
case '\t':
pCurPosition++;
continue;
case '\0':
return ENDF;
default:
return *pCurPosition++;
}
}
return ' ';
}
void CPl0Parser::unGetch()
{
pCurPosition--;
}
void CPl0Parser::match(int kind)
//匹配指定類型的單詞,然后取下一個單詞
{
if(kind!=tokKind)
{
errOp=ERR_NE;
error(kind);
}
else
NextToken();
}
void CPl0Parser::getID()
{
//讀取一個單詞于單詞緩沖區中
pCurPosition--;
char *p=pStrBuf;
while(isalnum(*pCurPosition))
{
*p++=*pCurPosition++;
}
*p='\0';
//查填空填符號表
tokVal=lookUp(pStrBuf);
//置單詞的類型
tokKind=table[tokVal].kind;
}
void CPl0Parser::getNum()
//取常數
{
pCurPosition--;
tokVal=0;
while(isdigit(*pCurPosition))
{
tokVal=10*tokVal+*pCurPosition++-'0';
}
tokKind=NUMBER;
}
int CPl0Parser::lookUp(const char *p)
//如果符號不在符號表中,將符號插入到符號表中,返回單詞在符號表中的位置
{
int *parents=new int[curLev+2];
int *pos=new int[curLev+2];
int lev=curLev+1,par=curParent;
//構造直接外層鏈,最外層之外層為保留字
for(;lev>0;lev--,par=table[par].parent)
{
parents[lev]=par;
pos[lev]=-1;
}
parents[0]=-2;pos[0]=-1;
//查找出現在外層鏈中的相同符號,返回最近外層位置
int i,b=-1;
for(i=0;table[i].pName!=0;i++)
{
if(strcmp(table[i].pName,p)==0)
{
b=i; //符號已出現
if(table[i].parent==-2)
pos[0]=i; //保留字
lev=table[i].level+1; //查找到的符號所在層數
if(parents[lev]==table[i].parent)
pos[lev]=i; //查找符號在某個外層中定義
}
}
//確定符號在符號堆中的位置
if(b>=0)
token=table[b].pName;
else
{
pStrBuf+=strlen(p)+1;
token=p;
}
for(b=curLev+1;b>=0;b--)
{
if(pos[b]>=0)
{
b=pos[b];
delete parents;
delete pos;
return b;
}
}
table[i].kind=IDENT;
table[i].level=curLev;
table[i].pName=token;
table[i].parent=curParent;
table[i+1].pName=0;
delete parents;
delete pos;
return i;
}
void CPl0Parser::error(const char *errMsg)
{
static int n=1;
switch(errOp)
{
case ERR_UNGETC:
unGetch();
break;
}
char buf[512];
sprintf(buf,"第%d行錯誤:%s\n",lineNo,errMsg);
errStr+=buf;
}
void CPl0Parser::error(int kind)
{
CString s;
switch(kind)
{
case SERVERKEY:
error("不應該出現保留字!");
break;
case CONSTANT:
error("常量定義錯誤!");
while(tokKind!=SEMICOLON)
NextToken();
break;
case VARIABLE:
error("變量定義錯誤!");
while(tokKind!=SEMICOLON)
NextToken();
break;
case PROCEDURE:
error("非法過程名或變量重定義!");
break;
case FACTOR:
if(tokKind==IDENT)
{
s="變量";
s=s+token+"未定義錯誤!";
error(s);
}
else
error("需要常量、變量或(!");
break;
case ROP:
case RPAREN:
error("括號不匹配,缺少“)”!");
break;
case DOT:
error("程序非法結束!");
break;
case THEN:
error("IF語句缺少THEN!");
break;
case DO:
error("WHILE語句缺少DO!");
break;
case END:
error("缺少END!");
break;
case SEMICOLON:
error("缺少“;”!");
break;
}
}
void CPl0Parser::program()
{
curLev++;
addr=3;
constPart();
varPart();
int taddr=addr;
procedure();
stCode=code.getCodeAddr();
if(curParent>=0)
{
int t,pos=table[curParent].val;
while(pos>=0)
{
t=pos;
pos=code.codes[t].addr;
code.codes[t].addr=stCode;
}
table[curParent].val=stCode;
table[curParent].size=taddr;
}
int n=code.gen("int",0,taddr);
word();
code.gen("opr",0,0);
curLev--;
}
void CPl0Parser::word()
{
switch(tokKind)
{
case VARIABLE:
assignWord();
break;
case CALL:
callWord();
break;
case BEGIN:
beginWord();
break;
case IF:
ifWord();
break;
case WHILE:
whileWord();
break;
case READ:
readWord();
break;
case WRITE:
writeWord();
break;
}
}
void CPl0Parser::constPart()
{
bookMark();
match(tokKind);
match(tokKind);
if(tokKind!=EQ)
{
retMark();
return;
}
retMark();
int n;
if(tokKind!=MCONST)
{
error("常量說明,需要以const開始!");
match(tokKind);
}
else
match(MCONST);
while(1){
if(tokKind==IDENT)
{
tokKind=table[n=tokVal].kind=CONSTANT;
}
else
{
if(table[tokVal].parent==-2)
error("保留字不能是常量名!");
else
if(getParent())
error("非法標識符或標識符已定義!");
else
n=fillTable(CONSTANT);
tokKind=CONSTANT;
}
match(CONSTANT);
match(EQ);
table[n].val=tokVal;
match(NUMBER);
if(tokKind!=COMMA)
break;
match(COMMA);
}
match(SEMICOLON);
}
void CPl0Parser::varPart()
{
switch(tokKind)
{
case VAR:
break;
case PROCEDURE:
case BEGIN:
return;
default:
bookMark();
match(tokKind);
match(tokKind);
if(tokKind==COMMA)
{
retMark();
break;
}
else
{
retMark();
return;
}
}
int n;
if(tokKind!=VAR)
{
error("變量定義應該以var開始!");
tokKind=VAR;
}
match(VAR);
while(1){
if(tokKind==IDENT)
{
tokKind=table[n=tokVal].kind=VARIABLE;
}
else
{
if(table[tokVal].parent==-2)
error("保留字不能是變量名!");
else
if(getParent())
error("非法標識符或標識符已定義!");
else
n=fillTable(VARIABLE);
tokKind=VARIABLE;
}
match(VARIABLE);
table[n].val=addr++;
if(tokKind!=COMMA)
break;
match(COMMA);
}
match(SEMICOLON);
}
void CPl0Parser::procedure()
{
while(1)
//while(tokKind==PROCEDURE)
{
bookMark();
match(tokKind);
match(tokKind);
if(tokKind!=SEMICOLON)
{
retMark();
return;
}
retMark();
int n;
if(tokKind!=PROCEDURE)
{
error("過程定義應該以procedure開始!");
tokKind=PROCEDURE;
}
match(PROCEDURE);
if(tokKind==IDENT)
{
tokKind=table[n=tokVal].kind=PROCEDURE;
}
else
{
if(table[n=tokVal].parent==-2)
error(SERVERKEY);
else
if(getParent())
error(PROCEDURE);
else
n=fillTable(PROCEDURE);
tokKind=PROCEDURE;
}
match(PROCEDURE);
match(SEMICOLON);
table[n].size=-1;
table[n].val=-1;
curParent=n;
program();
match(SEMICOLON);
curParent=table[curParent].parent;
}
}
int CPl0Parser::getParent()
{
for(int i=0;table[i].pName;i++)
if(strcmp(table[i].pName,token)==0 && curParent==table[i].parent)
return 1;
return 0;
}
int CPl0Parser::fillTable(int kind)
{
for(int i=0;table[i].pName;i++);
table[i].pName=token;
tokKind=table[i].kind=kind;
table[i].level=curLev;
table[i].parent=curParent;
table[i+1].pName=0;
return i;
}
void CPl0Parser::assignWord()
{
int n=tokVal;
int err=0;
match(VARIABLE);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -