📄 tinyc.c
字号:
//=========================================//// Tiny C Implementation "tinyC.C" ////=========================================//// Tan Watanabe, UEC (tan@cs.uec.ac.jp)// modified by Mitsugu G. Suzuki (gian@cs.uec.ac.jp)// with some advice with Mr. Musaraki#include "sub.h"#include "arm.h"#include "mips.h"//-- Global variables --// FILE *inFile, *prtFile, *objFile; SymbolP subCurrent; // Current subprogram name int returnStmt; // 1 if return stmt, 0 if other executable stmt.//-- Forward declarations --// void DeclStatement(SymbolP pTypeName); void VarDecl (SymbolP pTypeName, SymbolP pSymName); void FuncDecl (SymbolP pTypeName, SymbolP lSymName); int ExecStatement(SymbolP pSymp); void Block (); Reg_symP Variable (SymbolP pSymp, Reg_symP pRegCand, Ac_lrT pType); Reg_symP Factor (Reg_symP pRegCand); Reg_symP Term (Reg_symP pRegCand); Reg_symP Expression (Reg_symP pRegCand); void Condition (SymbolP pFalseLab); int IfStatement (); Reg_symP SubCall (SymbolP pSymp); void WhileStatement(); void Expect (SymbolP pSymp);//-------- Main program of the Tiny C compiler --------//int main( int pCount, // Command parameter count. char *pArg[]) // Command parameter (source program file name).{ SymbolP lSymbolP, lSymName, lTypeName; char lObjFile[TKN_lim]; // Object file name. int i; if (pCount > 1) { // Make object file name by replacing the strcpy(&lObjFile[0], pArg[1]); // extension name (.c) of source to ".s" for (i = 0; (lObjFile[i] != '\0')&&(lObjFile[i] != '.'); i++); lObjFile[i+1] = 's'; lObjFile[i+2] = '\0'; printf("Compile %s (object file %s)\n", pArg[1], lObjFile); } inFile = fopen(pArg[1], "r"); if (inFile == NULL) { printf("Source file %s can not be opened.\n", pArg[1]); return 1; } prtFile = stdout; objFile = fopen(lObjFile, "w"); sym_string.Initiation(); // String table class StringT. tkn_curr.Initiation(); // Token class Token. sym_tbl.Initiation(); // Symbol table class SymbolT. reg_tbl.Initiation(); // Register information class RegInf. ac_head.Initiation(); // Abstract register machine code Rcode. mrg_reg.Initiation(); // Machine register class MachineReg. sym_curr = NULL; sym_tempVar = 0; // Reset the number of generated temporal variables. GenCode(acS, opProg, NULL, NULL, NULL, NULL, 0); // Heading part. while (sym_curr != sym_eof) { // Loop until EOF. sym_curr = sym_tbl.Get('?'); // Get the next symbol. if ((sym_curr->Kind() == tknType)) // Should begin with type key word. DeclStatement(sym_curr); // Process the declaration. } GenCode(acN, opPend, NULL, NULL, NULL, NULL, 0); // Trailing part. sym_tbl.PrintAll(); // Print the symbol table. fclose(inFile); fclose(objFile); return 0;} //---- main end ----////--------------------//void DeclStatement( // Process a declaration statement. SymbolP pTypeName) // Type name. // At entry, type name or type key word or Id is read. // At exit, ';' or '{' is read.{ SymbolP lSymName, lTypeName, lTypeKey; int lSymNameProcessed; // true: name part is already processed. sym_curr = sym_tbl.Get('?'); // Get the next symbol. if (sym_curr != sym_scolon) { lSymName = sym_curr; // Variable or function name. sym_curr = sym_tbl.Get('?'); // Get the next symbol. } if (sym_curr == sym_lpar) { // '('. Function decl. FuncDecl(pTypeName, lSymName); }else if ((sym_curr == sym_comma)||(sym_curr == sym_lbracket)|| (sym_curr == sym_scolon)) { lSymNameProcessed = false; GenCode(acC, opSect, NULL, NULL, NULL, NULL, acSectData); if (sym_curr != sym_scolon) do { // VariableDecl::= TypeName VarSpec {"," VarSpec} ...";" VarDecl(pTypeName, lSymName); // Variable declaration. lSymNameProcessed = true; if (sym_curr == sym_comma) { lSymName = sym_tbl.Get('a'); sym_curr = sym_tbl.Get('?'); lSymNameProcessed = false; } } while ((sym_curr == sym_comma)||(sym_curr == sym_lbracket)); if (sym_curr == sym_scolon) { if ((lSymNameProcessed == false)&&(lSymName != NULL)&& (lSymName->Kind() == tknId)) VarDecl(pTypeName, lSymName); } Expect(sym_scolon); // Semicolon is expected. } // else-end (variable decl)} //---- DeclStatement end ----////--------------------// // Process a variable declaration.void VarDecl( // VarSpec::= VarName {"[" ArraySize "]"} SymbolP pTypeName, // Type name symbol pointer. SymbolP pSymName) // Variable name. // At entry, '[' or ',' or ';' next to variable name is read. // At exit , ',' or ';' is read.{ SymbolP lVarName, lArraySizep; VarInfP lVar; lVarName = pSymName; if (lVarName->IsIdentifier()) { // Process Variable name part. lVarName->KindSet(tknVar); lVarName->VTypeSet(pTypeName); lVarName->SizeSet(pTypeName->Size()); lVar = new VarInf; lVarName->VarPSet(lVar); lVar->ElemCountSet(1); } // end-if (tknId) else lVarName->Error(100, "Id expected \n"); if (sym_curr == sym_lbracket) { // Array variable with '['. lArraySizep = sym_tbl.Get('0'); lVar->ElemCountSet(lArraySizep->IValue()); lVarName->SizeSet((lVarName->Size())*(lVar->ElemCount())); sym_curr = sym_tbl.Get(']'); sym_curr = sym_tbl.Get('?'); // Read comma or semicolon. } // end-if (array var) GenCode(acS, opLabel, NULL, NULL, NULL, lVarName, 0); GenCode(acC, opDword, NULL, NULL, NULL, NULL, lVarName->Size());} //---- VarDecl end ----////--------------------//void FuncDecl( // Process a function declaration. SymbolP pTypeName, // Type name pointer. SymbolP pFuncName) // Function name pointer. // Return the parent node under which opSubp is attached. // At entry, '(' is read. At exit, '}' or ';' is read. // FunctionDef::= TypeName FuncName "(" TypeName ParamSpec // {{"," TypeName ParamSpec} ... } ")" [Block|";"] // ParamSpec ::= ParamName {"[" ArraySize "]"}{ SymbolP lParamList, lParamType, lParamName, lDim; FuncInfP lFunc; VarInfP lParamInf; int lParamC; int lArrSiz; lFunc = new FuncInf; subCurrent = pFuncName; subCurrent->KindSet(tknFunc); subCurrent->VTypeSet(pTypeName); subCurrent->FuncPSet(lFunc); GenCode(acS, opSubp, NULL, NULL, NULL, subCurrent, 0); lParamC = 0; lParamList = subCurrent; sym_curr = sym_tbl.Get('?'); // Read parameter type or ')'. while (sym_curr->Kind() == tknType) { // If parameter type. lParamType = sym_curr; // Get paramter name. sym_curr->Get('a'); if (sym_curr->Kind() == tknId) { // sym_curr is a parameter name. lParamC++; lParamName = sym_curr; if (lParamC == 1) lParamList->FuncP()->ParamChainSet(lParamName); else lParamList->VarP()->ParamChainSet(lParamName); lParamName->KindSet(tknParam); lParamName->VTypeSet(lParamType); lParamName->SizeSet(lParamType->Size()); lParamInf = new VarInf; lParamName->VarPSet(lParamInf); lParamInf->IndexSet(lParamC); lParamInf->ElemCountSet(1); // Set default. sym_curr = sym_tbl.Get('?'); // Read the next. if (sym_curr == sym_lbracket) { // Array parameter. lDim = sym_tbl.Get('?'); // Array size or ']' if (lDim->Kind() == tknIntC) { lArrSiz = lDim->IValue(); if (lArrSiz == 1) lArrSiz = 2; sym_curr = sym_tbl.Get(']'); } else if (lDim == sym_rbracket) { lArrSiz = 0x7fffffff; } else { lDim->Error(120, "IntConst or ] expected."); } lParamInf->ElemCountSet(lArrSiz); lParamName->SizeSet((lParamName->Size())* lArrSiz); sym_curr = sym_tbl.Get('?'); // Read comma or semicolon. } //---- end-if (array var) GenCode(acS, opLabel, NULL, NULL, NULL, lParamName, 0); GenCode(acC, opDparam, NULL, NULL, NULL, NULL, lParamName->Size()); lParamList = lParamName; } //---- Param name end if (sym_curr == sym_comma) sym_curr = sym_tbl.Get('a'); // Read the next. }; subCurrent->FuncP()->ParamCountSet(lParamC); Expect(sym_rpar); // ')' is expected. sym_curr = sym_tbl.Get('?'); // Read '{'. if (sym_curr == sym_lbrace) { // Function body is given. reg_tbl.RegFreeAll(); GenCode(acS, opExport, NULL, NULL, NULL, subCurrent, 0); GenCode(acC, opSect, NULL, NULL, NULL, NULL, acSectText); GenCode(acS, opProlog, NULL, NULL, NULL, subCurrent, 0); returnStmt = 0; // Reset return flag. Block(); // Process the function body. if (returnStmt == 0) { // If previous statement is not "return" GenCode(acS, opEpilog, NULL, NULL, NULL, subCurrent, 0); GenCode(acRs, opReturn, NULL, NULL, NULL, subCurrent, 0); } GenCode(acS, opEnd, NULL, NULL, NULL, subCurrent, 0); Expect(sym_rbrace); // '}' is expected. }} //---- FuncDecl end ----////--------------------//void Expect( // Expect pSym as current or next input token. SymbolP pSym) // Symbol pointer of the expected symbol. // If unexpected symbol appears, skip symbols until pSym appears.{ if (sym_curr == pSym) return; sym_curr = sym_tbl.Get('?'); if (sym_curr != pSym) { sym_curr->Error(110, " encountered. "); fprintf(prtFile, " %s expected.\n", pSym->NameStr()); while ((sym_curr != pSym)&&(sym_curr != sym_eof)) sym_curr = sym_tbl.Get('?'); }} //---- Expect end ----////--------------------// // Process a block.void Block() // Block::= "{" Statement ... "}" // At entry, '{' is read. At exit, '}' is read.{ Reg_symP lRegCond; int lNextRead; sym_curr = sym_tbl.Get('?'); // First token of the first statement. while ((sym_curr->Kind() != tknEof)&&(sym_curr != sym_rbrace)) { lNextRead = ExecStatement(sym_curr); if (lNextRead == 0) sym_curr = sym_tbl.Get('?'); } Expect(sym_rbrace);} //---- Block end ----////--------------------//int ExecStatement( // Process an executable statement. SymbolP pSymp) // First symbol of the statement. // At entry, 1st symbol is read.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -