📄 pass1.cpp
字号:
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ +
+ pass1.c - process directives to build symbol table +
+ +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ macros +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*#define PASS1_DEBUG 1*/
#ifdef PASS1_DEBUG
#define PASS1_DEBUG0(arg); printf(arg);
#define PASS1_DEBUG1(arg1,arg2); printf(arg1,arg2);
#define PASS1_DEBUG2(arg1,arg2,arg3); printf(arg1,arg2,arg3);
#else
#define PASS1_DEBUG0(arg);
#define PASS1_DEBUG1(arg1,arg2);
#define PASS1_DEBUG2(arg1,arg2,arg3);
#endif
#define OUTSIDE_PROC_PASS1 -1
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ declaration +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
class Pass1
{
StringTable *strTbl; /*pointers to symbol repository structures*/
SymbolTable *symTbl;
HashTable *hashTbl;
U4 currentProcPass1; /*index into symTbl of current procedure*/
U8 bytePosPass1; /*current index of bytecode being generated*/
U8 globalTotal; /*current total size of globals*/
void processDirective(struct Token *tptr, LineTokenizer *ptr);
void processGDirective(struct Token *tptr, LineTokenizer *ptr);
void processPDirective(struct Token *tptr, LineTokenizer *ptr);
void processInstruction(struct Token *tptr);
public:
Pass1(StringTable *st, SymbolTable *syt, HashTable *ht);
void parseLine(struct Line *line);
};
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ definitions +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
Pass1::Pass1(StringTable *st, SymbolTable *syt, HashTable *ht)
{
strTbl = st;
symTbl = syt;
hashTbl = ht;
currentProcPass1 = OUTSIDE_PROC_PASS1;
bytePosPass1 = 0;
globalTotal = 0;
return;
}/*end constructor*/
/*-----------------------------------------------------------------*/
void Pass1::parseLine(struct Line *line)
{
struct Token token;
PASS1_DEBUG2("Pass1::parseLine(): line->(%d)\t text->(%s)\n",(*line).line,(*line).src);
/*
line can be
i) a directive ( starts with a period, i.e. .IP )
ii) an instruction ( opcode operand(s) )
iii) a comment ( starts with # )
*/
LineTokenizer toker(line);
token = toker.getNextLineToken();
if(token.type==TOK_NO_MORE){ return; }
switch(token.text[0])
{
case '.' :{ processDirective(&token,&toker); }break;
case '#' :{ /*comment, ignore line*/ }break;
default:{ processInstruction(&token); }
}
return;
}/*end parseLine*/
/*-----------------------------------------------------------------*/
/*
Directives:
.GB identifier [ integer ] define global variable
( same for .GW, .GD, .GQ )
.PB identifier procedure begin
.PR identifier +n procedure return value
.PA identifier +n procedure argument
.PV identifier -n procedure local variable
.PL identifier procedure label
.PE procedure end
*/
void Pass1::processDirective(struct Token *tptr, LineTokenizer *ptr)
{
if((*tptr).type==TOK_IDENTIFIER)
{
switch((*tptr).text[1])
{
case 'G':{ processGDirective(tptr,ptr); }break;
case 'P':{ processPDirective(tptr,ptr); }break;
default:
{
ERROR2("Pass1::processDirective(): %s not directive, line %lu\n",(*tptr).text,(*tptr).line);
}
}
}
else
{
ERROR2("Pass1::processDirective(): %s not directive, line %lu\n",(*tptr).text,(*tptr).line);
}
return;
}/*end processDirective*/
/*-----------------------------------------------------------------*/
/*
.GB identifier [ integer ] define global variable
( same for .GW, .GD, .GQ )
*/
void Pass1::processGDirective(struct Token *tptr, LineTokenizer *ptr)
{
struct Token t;
struct HashTbl *hptr; /*returned from hash table*/
U1 bret;
/*global variable metadata*/
char id[ID_SIZE];
U1 dtype;
U8 length;
U8 size;
U8 offset;
U4 line;
switch((*tptr).text[2]) /*.GB identifier [ integer ]*/
{
/*third char, text[2], gives datatype*/
case 'B':{ dtype = SZ_BYTE; }break;
case 'W':{ dtype = SZ_WORD; }break;
case 'D':{ dtype = SZ_DWORD; }break;
case 'Q':{ dtype = SZ_QWORD; }break;
default:
{
ERROR2("Pass1::processGDirective(): line %d, invalid global data type (%s)\n",(*tptr).line,(*tptr).text);
return;
}
}
/*set some defaults*/
length = 1;
size = dtype*length;
offset = 0;
line = (*tptr).line;
bret = (*ptr).match(&t,TOK_IDENTIFIER);
if(bret!=TRUE)
{
ERROR1("Pass1::processGDirective(): line %d, global missing identifier\n",(*tptr).line);
return;
}
strcpy(id,t.text);
PASS1_DEBUG2("Pass1::processGDirective(): .GX %s=%s\n",TokStr[t.type],t.text);
/*
the [integer] modifiers is optional
so we cannot use match() because there are 2 correct ways
i) .GX identifier integer EOL
ii) .GX identifier EOL
*/
t = (*ptr).getNextLineToken();
/* .GX identifier integer EOL */
if(t.type==TOK_INT_CONST)
{
PASS1_DEBUG2("Pass1::processGDirective(): nElements %s=%lu\n",TokStr[t.type],t.val);
length = (U8)t.val;
size = dtype*length;
globalTotal = globalTotal + size;
offset = globalTotal;
bret = (*ptr).match(&t,TOK_NO_MORE);
if(bret==FALSE)
{
ERROR1("Pass1::processGDirective(): line %d, bad global declaration\n",(*tptr).line);
return;
}
}
/*.GX identifier EOL*/
else if(t.type==TOK_NO_MORE)
{
size = dtype;
globalTotal = globalTotal + size;
offset = globalTotal;
}
/*.GX identifer XXXX */
else
{
ERROR1("Pass1::processGDirective(): line %d, bad global declaration\n",(*tptr).line);
return;
}
/*if evade all errors, add .GB entry*/
PASS1_DEBUG0("Pass1::processGDirective(): adding .GX to symbol table\n");
hptr = (*hashTbl).queryHashTbl(id);
if(hptr!=NULL)
{
ERROR2("Pass1::processGDirective(): line %d, %s re-defined\n",line,id);
return;
}
else
{
struct GlobalVariable gv;
gv.text = (*strTbl).iStr;
gv.dType = dtype;
gv.len = length;
gv.size = size;
gv.offset = offset;
gv.line= line;
(*strTbl).addStrTbl(id);
(*symTbl).addGlobVar(&gv);
(*hashTbl).addHashTblEntry(id,gv.text,GLOBAL_VAR,((*symTbl).iGlobVar-1),0,line);
}
return;
}/*end processGDirective*/
/*-----------------------------------------------------------------*/
/*
.PB identifier procedure begin
.PR identifier +n procedure return value
.PA identifier +n procedure argument
.PV identifier -n procedure local variable
.PL identifier procedure label
.PE procedure end
*/
void Pass1::processPDirective(struct Token *tptr, LineTokenizer *ptr)
{
struct Token t;
U1 bret;
if(strcmp((*tptr).text,".PB")==0) /*.PB identifier EOL*/
{
char id[ID_SIZE];
U8 address;
U4 line;
struct HashTbl *hptr;
/*set some defaults*/
address = 0;
line = 0;
bret = (*ptr).match(&t,TOK_IDENTIFIER);
if(bret!=TRUE)
{
ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
return;
}
strcpy(id,t.text);
line = t.line;
address = bytePosPass1;
PASS1_DEBUG2("Pass1::processPDirective(): .PB identifier %s=%s\n",TokStr[t.type],t.text);
bret = (*ptr).match(&t,TOK_NO_MORE);
if(bret==FALSE)
{
ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
return;
}
PASS1_DEBUG0("Pass1::processPDirective(): adding .PB to symbol table\n");
hptr = (*hashTbl).queryHashTbl(id);
if(hptr!=NULL)
{
ERROR2("Pass1::processPDirective(): line %d, %s re-definition\n",line,id);
return;
}
else if(currentProcPass1!=OUTSIDE_PROC_PASS1)
{
ERROR2("Pass1::processPDirective(): line %d, %s, cannot nest procedures\n",line,id);
return;
}
else
{
struct Procedure p;
p.text = (*strTbl).iStr;
p.address = address;
p.line= line;
(*strTbl).addStrTbl(id);
(*symTbl).addProc(&p);
(*hashTbl).addHashTblEntry(id,p.text,PROC,((*symTbl).iProc-1),0,line);
currentProcPass1 = (*symTbl).iProc-1;
}
}/*end .PB*/
else if(strcmp((*tptr).text,".PR")==0) /*.PR identifier +n */
{
char name[ID_SIZE];
S4 offset;
U4 line;
struct HashTbl *hptr;
line = (*tptr).line;
bret = (*ptr).match(&t,TOK_IDENTIFIER);
if(bret!=TRUE)
{
ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
return;
}
strcpy(name,t.text);
bret = (*ptr).match(&t,TOK_INT_CONST);
if(bret!=TRUE)
{
ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
return;
}
offset = (S4)t.val;
bret = (*ptr).match(&t,TOK_NO_MORE);
if(bret!=TRUE)
{
ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
return;
}
PASS1_DEBUG0("processPDirective(): adding .PR to symbol table\n");
hptr = (*hashTbl).queryHashTbl(name);
if(hptr!=NULL)
{
ERROR2("processPDirective(): line %d, %s re-defined\n",line,name);
return;
}
else
{
struct StackFrame sf;
sf.text = (*strTbl).iStr;
sf.fpOffset = offset;
sf.line = line;
(*strTbl).addStrTbl(name);
(*symTbl).setProcRetHL(&sf);
(*hashTbl).addHashTblEntry(name,sf.text,PROC_RET,((*symTbl).iProc-1),0,line);
}
}/*end .PR*/
else if(strcmp((*tptr).text,".PA")==0) /*.PA identifier +n*/
{
char name[ID_SIZE];
S4 offset;
U4 line;
struct HashTbl *hptr;
bret = (*ptr).match(&t,TOK_IDENTIFIER);
if(bret!=TRUE)
{
ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
return;
}
strcpy(name,t.text);
line = t.line;
bret = (*ptr).match(&t,TOK_INT_CONST);
if(bret!=TRUE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -