/* @@@@ @@@@@@ @ @ @@@@ @ @ @@ @@ @ @ @@@@ @@@@@ @ @@ @ @ @ @ @ @ @@@ @ @ @ @ @ @ @@@ @ @ @@@@ @@@@@@ @ @ @@@ @@@@ * sem.c - build an abstract syntax tree representation of the program */ #include #include /* stdarg.h allows the routine CheckStack to have a variables number of parameters - see man stdarg for details */ #include #include "astdef.h" #include "booldef.h" #define SEM_LOCAL #include "sem.h" #define SEMSTACK_LOCAL #include "semstack.h" #include "symtab.h" #include "tracing.h" #include "y-tab.h" static void SemDebug (char *semname); static BOOLEAN CheckStack (int numentries, ...); static void ConstReduce(void); /* -------------------------------------------------------------------------- */ /* ----------- PUSHID: Push an identifier onto semantic stack ---------- */ /* -------------------------------------------------------------------------- */ /* SEMANTIC STACK MANIPULATION: * | | | IdEntry |<- top * ----------- ------------ * top ->| ? | | ? | * */ void PushId(char *s) { if (PtraceSem) Entering("PushId"); SemTop++; Semstack[SemTop].type = IdEntry; Semstack[SemTop].se.id = (char *) malloc( strlen(s) + 1); /* add space for eol */ strcpy( Semstack[SemTop].se.id, s); SemDebug("PushId"); if (PtraceSem) Leaving("PushId"); } /* PushId */ /* -------------------------------------------------------------------------- */ /* ----------- PUSHINT: Push an integer onto the semantic stack ---------- */ /* -------------------------------------------------------------------------- */ /* SEMANTIC STACK MANIPULATION: * | | >>> |IconstEntry|<- top * ----------- ------------ * top ->| ? | | ? | * */ void PushInt(i) int i; { if (PtraceSem) Entering("PushInt"); SemTop++; Semstack[SemTop].type = IconstEntry; Semstack[SemTop].se.iconst = i; SemDebug("PushInt"); if (PtraceSem) Leaving("PushInt"); } /* PushId */ /* -------------------------------------------------------------------------- */ /* -------- INITSEMANTICS: INITIALIZATION FOR THE SEMANTIC ROUTINES -------- */ /* -------------------------------------------------------------------------- */ int InitSemantics(void) { if (PtraceSem) Entering("InitSemantics"); InitSymtab(); SemTop = 0; CurProcLevel = 0; Prog.const_listptr = NULL; if (PtraceSem) Leaving("INITSemantics"); return(OK); } /* InitSemantics */ /* -------------------------------------------------------------------------- */ /* ----------------- CHECKSTACK: CHECK THE SEMANTIC STACK ------------------ */ /* -------------------------------------------------------------------------- */ /* return false if there are error entries on the stack; otherwise * return true (if the top entries match) */ static BOOLEAN CheckStack(int numentries, ...) { va_list ap; int i; SEMSTACKTAG checktag; if (PtraceSem) Entering("CheckStack"); va_start(ap, numentries); if(SemTop+1 < numentries) { /* This should not occur under any circumstance */ fprintf(stderr, "Fatal: CheckStack-Semantic stack underflow !\n"); exit(1); } for(i=0 ; i < numentries ; i++){ checktag = va_arg(ap, SEMSTACKTAG); if(Semstack[SemTop-i].type == ErrorEntry) { if (PtraceSem) Leaving("CheckStack"); va_end(ap); return(FALSE); } else if(Semstack[SemTop-i].type != checktag) { /* This will occur when adding new grammar rules */ fprintf(stderr, "ERROR: CheckStack-Semantic stack inconsistency !\n"); va_end(ap); return(FALSE); /* exit(1); TOO DRASTIC */ } } va_end(ap); if (PtraceSem) Leaving("CheckStack"); return(TRUE); } /* CheckStack */ /* -------------------------------------------------------------------------- */ /* ---------------- DONE: PARSING COMPLETED, TIE UP LOSE ENDS -------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * pgm ::= stmtlist #done */ /* SEMANTIC STACK MANIPULATION: * top ->|StLstEntry| * ------------ <- bottom of stack */ void Done(void) { VARLIST GetVars(); if (PtraceSem) Entering("Done"); if( !CheckStack(1, StLstEntry)){ SemDebug("Done - error on stack"); if (PtraceSem) Leaving("DONE"); return; /* It already has an error entry */ } /* NORMAL PROCESSING */ Prog.main = Semstack[SemTop].se.slist.first; Prog.vars = GetVars(); /* assign storage to variables */ if(SymRoot == NULL) printf("Warning: symbol table is empty (in done)\n"); if(Prog.vars == NULL) printf("Warning: var list is empty (in done)\n"); SemTop = SemTop - 1; /* Semstack should be empty */ SemDebug("Done"); if (PtraceSem) Leaving("Done"); } /* done */ /* -------------------------------------------------------------------------- */ /* ---------------------- PERFORMOP: BINARY OPERATIONS --------------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * expr ::= expr addop term #DoArithOp * term ::= term multop fact #DoArithOp */ /* SEMANTIC STACK MANIPULATION: * top ->|ExprEntry| * ----------- * |OperEntry| * ----------- * |ExprEntry| >>> |ExprEntry|<- top * ----------- ----------- * | ? | | ? | */ void DoArithOp(void) { EXPRTREE curexpr; EXPRTREE expr1, expr2; BOOLEAN const1, const2; int ival1, ival2; if (PtraceSem) Entering("DoArithOp"); if(!CheckStack(3, ExprEntry, OperEntry, ExprEntry)){ /* replace the top 3 items with an error entry */ SemTop = SemTop - 2; Semstack[SemTop].type = ErrorEntry; SemDebug("DoArithOp - error on stack"); if (PtraceSem) Leaving("PERFORMOP"); return; } /* NORMAL PROCESSING */ expr1 = Semstack[SemTop-2].se.expr; expr2 = Semstack[SemTop].se.expr; /* determine if both operands are constant Values */ const1 = FALSE; if( expr1->op == Fetch ){ if( expr1->ee.addr->type == Immediate ){ const1 = TRUE; ival1 = expr1->ee.addr->ae.i; } } const2 = FALSE; if( expr2->op == Fetch ){ if( expr2->ee.addr->type == Immediate ){ const2 = TRUE; /* fixed old error in project */ ival2 = expr2->ee.addr->ae.i; } } if( const1 && const2 ){ /* both operands are constant Values, do constant folding */ switch(Semstack[SemTop-1].se.oper){ case AddOp: expr1->ee.addr->ae.i = ival1 + ival2; break; case SubOp: expr1->ee.addr->ae.i = ival1 - ival2; break; case MpyOp: expr1->ee.addr->ae.i = ival1 * ival2; break; case DivOp: expr1->ee.addr->ae.i = ival1 / ival2; } /* height field is correct at 1 */ SemTop = SemTop - 2; } else { /* build a new root for the expression tree */ curexpr = expr_alloc(); curexpr->op = Semstack[SemTop-1].se.oper; /* get the children for this new root */ curexpr->ee.atree.left = expr1; curexpr->ee.atree.right = expr2; /* keep track of heights */ if( expr1->height >= expr2->height ) curexpr->height = expr1->height + 1; else curexpr->height = expr2->height + 1; /* fix up the semantic stack */ SemTop = SemTop - 2; Semstack[SemTop].type = ExprEntry; /* actually reset to same value */ Semstack[SemTop].se.expr = curexpr; } SemDebug("DoArithOp"); if (PtraceSem) Leaving("PERFORMOP"); } /* DoArithOp */ /* -------------------------------------------------------------------------- */ /* ------- IfTest : ONLY EQUALITY RELATION - use DoArithOp as model -------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * boolexpr ::= expr eqop expr #IfTest */ /* SEMANTIC STACK MANIPULATION: we don't push eqop since only 1 boolean op now * top ->|ExprEntry| * ----------- * |ExprEntry| >>> |BexprEntry|<- top * ----------- ------------ * | ? | | ? | */ void IfTest(void) { EXPRTREE curexpr; EXPRTREE expr1, expr2; BOOLEAN const1, const2; int ival1, ival2; if (PtraceSem) Entering("IfTest"); if(!CheckStack(2, ExprEntry, ExprEntry)){ /* replace the top 2 items with an error entry */ SemTop = SemTop - 1; Semstack[SemTop].type = ErrorEntry; SemDebug("IfTest - error on stack"); if (PtraceSem) Leaving("IfTest"); return; } /* NORMAL PROCESSING */ expr1 = Semstack[SemTop-1].se.expr; expr2 = Semstack[SemTop].se.expr; /* determine if both operands are constant Values */ const1 = FALSE; if( expr1->op == Fetch ){ if( expr1->ee.addr->type == Immediate ){ const1 = TRUE; ival1 = expr1->ee.addr->ae.i; } } const2 = FALSE; if( expr2->op == Fetch ){ if( expr2->ee.addr->type == Immediate ){ const2 = TRUE; /* fixed old error in project */ ival2 = expr2->ee.addr->ae.i; } } if( const1 && const2 ){ /* both operands are constant Values, do constant folding */ if (ival1 == ival2) expr1->ee.addr->ae.i = TRUE; else expr1->ee.addr->ae.i = FALSE; /* height field is correct at 1 */ SemTop -- ; } else { /* build a new root for the expression tree */ curexpr = expr_alloc(); curexpr->op = EqOp; /* only one boolean op available now */ /* get the children for this new root */ curexpr->ee.btree.left = expr1; curexpr->ee.btree.right = expr2; /* keep track of heights */ if( expr1->height >= expr2->height ) curexpr->height = expr1->height + 1; else curexpr->height = expr2->height + 1; /* fix up the semantic stack */ SemTop --; Semstack[SemTop].type = BexprEntry; Semstack[SemTop].se.expr = curexpr; } SemDebug("IfTest"); if (PtraceSem) Leaving("IfTest"); } /* IfTest*/ /* ------------------------------------------------------------------------ */ /* -------------------- PerformUnary: UNARY OPERATIONS ------------------- */ /* ------------------------------------------------------------------------ */ /* PRODUCTIONS: * fact ::= unarylist primary #PerformUnary */ /* SEMANTIC STACK MANIPULATION: * top ->|ExprEntry| * ----------- * |OperEntry| >>> |ExprEntry|<- top * ----------- ----------- * | ? | | ? | */ void PerformUnary(void) { EXPRTREE curexpr; BOOLEAN constantfold; if (PtraceSem) Entering("PerformUnary"); if(!CheckStack(2, ExprEntry, OperEntry)){ /* Replace the top 2 items with an error entry */ SemTop = SemTop - 1; Semstack[SemTop].type = ErrorEntry; SemDebug("PerformUnary - error on stack"); if (PtraceSem) Leaving("PerformUnary"); return; } /* NORMAL PROCESSING */ /* if the operator is '-' then build a new tree */ if( Semstack[SemTop-1].se.oper == SubOp ) { /* check for constant folding */ constantfold = FALSE; if( Semstack[SemTop].se.expr->op == Fetch ){ if( Semstack[SemTop].se.expr->ee.addr->type == Immediate ) { curexpr = Semstack[SemTop].se.expr; curexpr->ee.addr->ae.i = -curexpr->ee.addr->ae.i; constantfold = TRUE; } } if(!constantfold){ /* build a new tree */ curexpr = expr_alloc(); curexpr->op = UsubOp; curexpr->ee.child = Semstack[SemTop].se.expr; /* keep track of height */ curexpr->height = Semstack[SemTop].se.expr->height + 1; } } else curexpr = Semstack[SemTop].se.expr; /* throw away unary plus */ /* fix up the semantic stack */ SemTop = SemTop - 1; Semstack[SemTop].type = ExprEntry; Semstack[SemTop].se.expr = curexpr; SemDebug("PerformUnary"); if (PtraceSem) Leaving("PerformUnary"); } /* PerformUnary */ /* -------------------------------------------------------------------------- */ /* ----------- IdToAddr: TRANSFORM AN IDENTIFIER INTO AN ADDRESS ----------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * memref ::= Id #IdToAddr */ /* SEMANTIC STACK MANIPULATION: * top ->| IdEntry | >>> |AddrEntry|<- top * ----------- ----------- * | ? | | ? | */ void IdToAddr(void) { IDNAME id; ATTRPTR attr; ATTRPTR Lookup(); ADDRTREE curaddr; if (PtraceSem) Entering("IdToAddr"); if(!CheckStack(1, IdEntry)){ SemDebug("IdToAddr - error on stack"); Semstack[SemTop].type = ErrorEntry; if (PtraceSem) Leaving("IdToAddr"); return; } /* NORMAL PROCESSING */ id = Semstack[SemTop].se.id; attr = Lookup(id); if(attr == NULL){ /* Insert the identifier in the symbol table */ attr = attr_alloc(); attr->id = id; attr->level = CurProcLevel; /* MDM 07/23/90 */ /* Do not know the offset at this time. */ Insert(attr); } /* build an address tree */ curaddr = addr_alloc(); curaddr->type = Memory; curaddr->ae.attrs = attr; /* Point to symbol table entry, so that when address is assigned (before we walk the tree generating code/ we will be able to retrieve them easily. */ /* put the address on top of the stack */ Semstack[SemTop].type = AddrEntry; Semstack[SemTop].se.addr = curaddr; SemDebug("IdToAddr"); if (PtraceSem) Leaving("IdToAddr"); } /* IdToAddr */ /* -------------------------------------------------------------------------- */ /* ------------------- Operator: CREATE AN Operator ENTRY ------------------ */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * addop ::= Plussym #operator1 * addop ::= Minussym #operator2 * multop ::= Mpysym #operator3 * multop ::= Divsym #operator4 */ /* SEMANTIC STACK MANIPULATION: * | | >>> |OperEntry|<- top * ----------- ----------- * top ->| ? | | ? | */ void Operator(OPERATION op) { if (PtraceSem) Entering("Operator"); /* Semantic stack cannot overflow unless syntax stack overflows. */ SemTop++; Semstack[SemTop].type = OperEntry; Semstack[SemTop].se.oper = op; SemDebug("Operator "); if (PtraceSem) Leaving("Operator"); } /* Operator */ /* -------------------------------------------------------------------------- */ /* -------------------- NULLLIST: MAKE AN EMPTY STMTLIST ------------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * stmtlist ::= #NullList */ /* SEMANTIC STACK MANIPULATION: * >>> |StLstEntry|<- top * ----------- ------------ * top ->| ? | | ? | */ void NullList(void) { if (PtraceSem) Entering("NULLLIST"); /* Semantic stack cannot overflow unless syntax stack overflows. */ SemTop++; Semstack[SemTop].type = StLstEntry; Semstack[SemTop].se.slist.first = NULL; Semstack[SemTop].se.slist.last = NULL; SemDebug("NullList"); if (PtraceSem) Leaving("NULLLIST"); } /* NullList */ /* -------------------------------------------------------------------------- */ /* ---------------- MergeStmts: MERGE A STMT INTO A STMTLIST --------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * stmtlist ::= stmtlist stmt #MergeStmts */ /* SEMANTIC STACK MANIPULATION: * top ->|StmtEntry | * ------------ * |StLstEntry| >>> |StLstEntry|<- top * ------------ ------------ * | ? | | ? | */ void MergeStmts(void) { STMTPTR newstmt; if (PtraceSem) Entering("MergeStmts"); if(!CheckStack(2, StmtEntry, StLstEntry)) { /* Replace the top two items with an error entry */ SemTop = SemTop - 1; Semstack[SemTop].type = ErrorEntry; SemDebug("MergeStmts - error on stack"); if (PtraceSem) Leaving("MergeStmts"); return; } /* NORMAL PROCESSING */ newstmt = Semstack[SemTop].se.stmt; if(Semstack[SemTop-1].se.slist.first == NULL) Semstack[SemTop-1].se.slist.first = newstmt; else Semstack[SemTop-1].se.slist.last->next = newstmt; Semstack[SemTop-1].se.slist.last = newstmt; /* fix up the semantic stack */ SemTop--; /* Semantic stack entry is correct */ SemDebug("MergeStmts"); if (PtraceSem) Leaving("MergeStmts"); } /* MergeStmts */ /* -------------------------------------------------------------------------- */ /* --------------------- Assign: MAKE AN AssignMENT NODE ------------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * AssignStmt ::= memref Assignop expr #assign */ /* SEMANTIC STACK MANIPULATION: * top ->|ExprEntry| * ----------- * |AddrEntry| >>> |StmtEntry|<- top * ----------- ----------- * | ? | | ? | */ void Assign(void) { STMTPTR curstmt; if (PtraceSem) Entering("Assign"); if(!CheckStack(2, ExprEntry, AddrEntry)){ /* Replace the top two items with an error entry */ SemTop = SemTop - 1; Semstack[SemTop].type = ErrorEntry; SemDebug("Assign - error on stack"); if (PtraceSem) Leaving("Assign"); return; } /* NORMAL PROCESSING */ curstmt = stmt_alloc(); curstmt->next = NULL; /* 9-21-93 */ /* save the information about this statement */ curstmt->type = AssignStmt; curstmt->se.assign.lhs = Semstack[SemTop-1].se.addr; curstmt->se.assign.rhs = Semstack[SemTop].se.expr; /* fix up the semantic stack */ SemTop--; Semstack[SemTop].type = StmtEntry; Semstack[SemTop].se.stmt = curstmt; SemDebug("Assign"); if (PtraceSem) Leaving("Assign"); } /* Assign */ /* -------------------------------------------------------------------------- */ /* ------- MakeIf : MAKE AN IFSTMT NODE - use assign as model -------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * ifstmt ::= If boolexpr Then stmtlist End If #MakeIf */ /* SEMANTIC STACK MANIPULATION: * top ->|StLstEntry| * ----------- * |BexprEntry| >>> |StmtEntry|<- top * ----------- ----------- * | ? | | ? | */ void MakeIf(void) { STMTPTR curstmt; if (PtraceSem) Entering("MakeIf"); /* temp fix of ExprEntry */ if(!CheckStack(2, StLstEntry, BexprEntry)){ /* Replace the top two items with an error entry */ SemTop = SemTop - 1; Semstack[SemTop].type = ErrorEntry; SemDebug("MakeIf - error on stack"); if (PtraceSem) Leaving("MakeIf"); return; } /* NORMAL PROCESSING */ curstmt = stmt_alloc(); curstmt->next = NULL; /* 9-21-93 */ /* save the information about this statement */ curstmt->type = IfThenStmt ; curstmt->se.ifthen.bexpr = Semstack[SemTop-1].se.expr; /* use mergestmt as model - we can just stick the list on because even if the body of the if-then is entry, the NullList was initialized */ curstmt->se.ifthen.slist = Semstack[SemTop].se.slist.first; /* fix up the semantic stack */ SemTop--; Semstack[SemTop].type = StmtEntry; Semstack[SemTop].se.stmt = curstmt; SemDebug("MakeIf"); if (PtraceSem) Leaving("MakeIf"); } /* MakeIf*/ /* -------------------------------------------------------------------------- */ /* ------------------- AddrToPrimary: ADDRESS TO PRIMARY -------------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * primary ::= memref #AddrToPrimary . */ /* SEMANTIC STACK MANIPULATION: * top ->|AddrEntry| >>> |ExprEntry|<- top * ----------- ----------- * | ? | | ? | */ void AddrToPrimary(void) { EXPRTREE expr; if (PtraceSem) Entering("AddrToPrimary"); if(!CheckStack(1, AddrEntry)){ SemDebug("AddrToPrimary - error on stack"); Semstack[SemTop].type = ErrorEntry; if (PtraceSem) Leaving("AddrToPrimary"); return; } /* NORMAL PROCESSING */ /* build the trivial expression tree */ expr = expr_alloc(); expr->op = Fetch; /* "Fetch operand" is a leaf */ expr->height = 1; expr->ee.addr = Semstack[SemTop].se.addr; /* put the expression tree on the semantic stack */ Semstack[SemTop].type = ExprEntry; Semstack[SemTop].se.expr = expr; SemDebug("AddrToPrimary"); if (PtraceSem) Leaving("AddrToPrimary"); } /* AddrToPrimary */ /* -------------------------------------------------------------------------- */ /* ------------- Call: MAKE A PROCEDURE Call NODE AND LINK IT IN ----------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * readstmt ::= Read Lparen memreflist Rparen #call1 * readstmt ::= Readln Lparen memreflist Rparen #Call2 * writestmt ::= Write Lparen actparamlist Rparen #call3 * writestmt ::= Writeln Lparen actparamlist Rparen #call4 */ /* SEMANTIC STACK MANIPULATION: * top ->|ParmEntry| >>> |StmtEntry|<- top * ----------- ----------- * | ? | | ? | */ void Call(PROCEDURETYPE name) { STMTPTR newstmt; if (PtraceSem) Entering("Call"); if(!CheckStack(1, ParmEntry)){ SemDebug("Call - error on stack"); Semstack[SemTop].type = ErrorEntry; if (PtraceSem) Leaving("Call"); return; } /* NORMAL PROCESSING */ newstmt = stmt_alloc(); newstmt->next = NULL; /* 9-21-93 */ newstmt->type = StdProcCall; newstmt->se.procall.type = name; newstmt->se.procall.params = Semstack[SemTop].se.plist.first; /* fix up the semantic stack */ Semstack[SemTop].type = StmtEntry; Semstack[SemTop].se.stmt = newstmt; SemDebug("Call"); if (PtraceSem) Leaving("Call"); } /* call */ /* -------------------------------------------------------------------------- */ /* ------------- Call: MAKE A PROCEDURE Call NODE AND LINK IT IN ----------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * readstmt ::= Readln #Call2a * writestmt ::= Writeln #call4a NOTE: without parameters */ /* SEMANTIC STACK MANIPULATION: * >>> |StmtEntry|<- top * ----------- ----------- * top ->| ? | | ? | */ void Call2(PROCEDURETYPE name) { STMTPTR newstmt; if (PtraceSem) Entering("Call2"); /* Semantic stack cannot overflow unless syntax stack overflows. */ SemTop++; newstmt = stmt_alloc(); newstmt->next = NULL; /* 9-21-93 */ newstmt->type = StdProcCall; newstmt->se.procall.type = name; newstmt->se.procall.params = NULL; /* no parameters */ /* fix up the semantic stack */ Semstack[SemTop].type = StmtEntry; Semstack[SemTop].se.stmt = newstmt; SemDebug("Call2"); if (PtraceSem) Leaving("Call2"); } /* Call2 */ /* -------------------------------------------------------------------------- */ /* ------------- CreateActParam: CREATE AN ACTUAL PARAMETER LIST ----------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * actparam ::= expr #CreateActParam */ /* SEMANTIC STACK MANIPULATION: * top ->|ExprEntry| >>> |ParmEntry|<- top * ----------- ----------- * | ? | | ? | */ /* set up with first,last pointing to same new parameter entry */ void CreateActParam(void) { PARAMPTR param; if (PtraceSem) Entering("CreateActParam"); if(!CheckStack(1, ExprEntry)){ SemDebug("CreateActParam - error on stack"); Semstack[SemTop].type = ErrorEntry; if (PtraceSem) Leaving("CreateActParam"); return; } /* NORMAL PROCESSING */ param = param_alloc(); param->next = NULL; /* the parameter is passed by Value */ param->type = Value; param->pe.val = Semstack[SemTop].se.expr; /* fix up the semantic stack */ Semstack[SemTop].type = ParmEntry; Semstack[SemTop].se.plist.first = param; Semstack[SemTop].se.plist.last = param; SemDebug("CreateActParam"); if (PtraceSem) Leaving("CreateActParam"); } /* CreateActParam */ /* -------------------------------------------------------------------------- */ /* --------------- MergeActParam: LINK IN AN ACTUAL PARAMETER -------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * actparamlist ::= actparamlist Commasym actparam #MergeActParam */ /* add to the end of the list of parameters - fifo ordering of the queue */ /* SEMANTIC STACK MANIPULATION: * top ->|ParmEntry| * ----------- * |ParmEntry| >>> |ParmEntry|<- top * ----------- ----------- * | ? | | ? | */ void MergeActParam(void) { PARAMPTR param; if (PtraceSem) Entering("MergeActParam"); if(!CheckStack(2, ParmEntry, ParmEntry)){ /* Replace the top two items with an error entry */ SemTop = SemTop - 1; Semstack[SemTop].type = ErrorEntry; SemDebug("MergeActParam - error on stack"); if (PtraceSem) Leaving("MergeActParam"); return; } /* NORMAL PROCESSING */ param = Semstack[SemTop].se.plist.first; /* 9-21-93 */ SemTop--; Semstack[SemTop].se.plist.last->next = param; Semstack[SemTop].se.plist.last = param; SemDebug("MergeActParam"); if (PtraceSem) Leaving("MergeActParam"); } /* MergeActParam */ /* -------------------------------------------------------------------------- */ /* ------------ CreateMemParam: CREATE AN ACTUAL PARAMETER LIST ------------ */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * memreflist ::= memref #CreateMemParam */ /* set up with first,last pointing to same parameter node */ /* SEMANTIC STACK MANIPULATION: * top ->|AddrEntry| >>> |ParmEntry|<- top * ----------- ----------- * | ? | | ? | */ void CreateMemParam(void) { PARAMPTR curparam; if (PtraceSem) Entering("CreateMemParam"); if(!CheckStack(1, AddrEntry)){ SemDebug("CreateMemParam - error on stack"); Semstack[SemTop].type = ErrorEntry; if (PtraceSem) Leaving("CreateMemParam"); return; } /* NORMAL PROCESSING */ curparam = param_alloc(); curparam->next = NULL; /* the parameter is passed by reference */ curparam->type = Reference; curparam->pe.loc = Semstack[SemTop].se.addr; /* fix up the semantic stack */ Semstack[SemTop].type = ParmEntry; Semstack[SemTop].se.plist.first = curparam; Semstack[SemTop].se.plist.last = curparam; SemDebug("CreateMemParam"); if (PtraceSem) Leaving("CreateMemParam"); } /* CreateMemParam */ /* -------------------------------------------------------------------------- */ /* -------------- MergeMemParam: LINK IN AN ACTUAL PARAMETER --------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * memreflist ::= memreflist Commasym memref #MergeMemParam */ /* fifo ordering of queue - insert at end of linked list */ /* SEMANTIC STACK MANIPULATION: * top ->|AddrEntry| * ----------- * |ParmEntry| >>> |ParmEntry|<- top * ----------- ----------- * | ? | | ? | */ void MergeMemParam(void) { PARAMPTR curparam; if (PtraceSem) Entering("MergeMemParam"); if(!CheckStack(2, AddrEntry, ParmEntry)){ /* Replace the top two items with an error entry */ SemTop = SemTop - 1; Semstack[SemTop].type = ErrorEntry; SemDebug("MergeMemParam - error on stack"); if (PtraceSem) Leaving("MergeMemParam"); return; } /* NORMAL PROCESSING */ curparam = param_alloc(); curparam->next = NULL; /* the parameter is passed by Value */ curparam->type = Reference; curparam->pe.loc = Semstack[SemTop].se.addr; SemTop--; Semstack[SemTop].se.plist.last->next = curparam; Semstack[SemTop].se.plist.last = curparam; SemDebug("MergeMemParam"); if (PtraceSem) Leaving("MergeMemParam"); } /* MergeMemParam */ /* -------------------------------------------------------------------------- */ /* ------------- IconstReduce: CONVERT CONSTANT TO EXPRESSION -------------- */ /* -------------------------------------------------------------------------- */ /* PRODUCTIONS: * primary ::= Iconst #IconstReduce */ /* SEMANTIC STACK MANIPULATION: * top ->|IconstEntry| >>> |ExprEntry|<- top * ------------- ----------- * | ? | | ? | */ void IconstReduce(void) { EXPRTREE curexpr; if (PtraceSem) Entering("IconstReduce"); if(!CheckStack(1, IconstEntry)){ SemDebug("IconstReduce - error on stack"); Semstack[SemTop].type = ErrorEntry; if (PtraceSem) Leaving("IconstReduce"); return; } /* NORMAL PROCESSING */ curexpr = expr_alloc(); curexpr->op = Fetch; /* "Fetch operand" is a leaf */ curexpr->height = 1; curexpr->ee.addr = addr_alloc(); curexpr->ee.addr->type = Immediate; curexpr->ee.addr->ae.i = Semstack[SemTop].se.iconst; Semstack[SemTop].type = ExprEntry; Semstack[SemTop].se.expr = curexpr; SemDebug("IconstReduce"); if (PtraceSem) Leaving("IconstReduce"); } /* IconstReduce */ /* ---------------------------------------------------------------- */ /* ---------------------- PRINT_SEMSTACK -------------------------- */ /* ---------------------------------------------------------------- */ /* the parameter semname is a character string of the name of the */ /* semantic action which just altered the semantic stack */ void PrintSemstack(char *semname) { /*register-fall91 */ int i; printf("After : %s Semstack is:\n",semname); /* SemTop initialized to 0 when Semstack is empty - print entries */ for(i=SemTop ;i>0 ; i--) { /* Case thru all possible types that could be on * * semantic stack. */ switch(Semstack[i].type){ case NoEntry: printf("\t NoEntry "); break; case ErrorEntry: printf("\t ErrorEntry"); break; case AddrEntry: printf("\t AddrEntry "); break; case ExprEntry: printf("\t ExprEntry "); break; case BexprEntry: printf("\t BexprEntry"); break; case IdEntry: printf("\t IdEntry (%s)",Semstack[SemTop].se.id); break; case IconstEntry: printf("\t IconstEntry"); break; case OperEntry: printf("\t OperEntry "); break; case StmtEntry: printf("\t StmtEntry "); break; case StLstEntry: printf("\t StLstEntry"); break; case ParmEntry: printf("\t ParmEntry "); break; } /* switch */ /* Display stack pointer */ if(i == SemTop) printf("\t<+ SemTop\n"); else printf("\n"); } /* for loop thru semantic stack array */ if (SemTop == 0) printf("\t\tEMPTY\n"); } /* PrintSemstack() */ /* -------------------------------------------------------------------------- */ /* -------- AddStringConstant: Add a given string to constant list -------- */ /* -------------------------------------------------------------------------- */ /* This procedure adds the given string to the global linked list of string * * constants. This routine creates a new node of type constlist and inserts * * it at the beginning of the linked list(FIFO). After setting the pointers, * * it sets the Prog.const_listptr to the new node, the beginning of the list. * * * * * * ---------- ---------- * *Prog. const_listptr --> |"Hi" | | --> |"Bye" | | * * ---------- ---------- * * * * AddStringConstant("One"); * * * * ---------- ---------- ---------- * *Prog.const_listptr --> |"One" | | --> |"Hi" | | --> |"Bye" | | * * ---------- ---------- ---------- * * * ******************************************************************************/ void AddStringConstant(char *s) { struct constlist *new_node; if (PtraceSem) Entering("AddStringConstant"); /* Give me space for the structure */ new_node = (struct constlist *) malloc( sizeof ( struct constlist )); /* Give me space for the structure */ new_node->info = (char *) malloc( strlen( s ) + 3); /* Keep a copy for myself */ strcpy(new_node->info, s); /* Stick new string at beginning of constant list */ new_node->next = Prog.const_listptr; /* Make this new_node the beginning of list */ Prog.const_listptr = new_node; if (PtraceSem) Leaving("AddStringConstant"); } /* AddStringConstant() */ /* -------------------------------------------------------------------------- */ /* ------------------ SEM_DEBUG: Semantic debugging module ------------------ */ /* -------------------------------------------------------------------------- */ /* If the proper flag(s) are set, call the proper routines to display some * * useful information for the user. */ void SemDebug(char *semname) { if ( Semstacktrace ) PrintSemstack(semname); } /* SemDebug() */