├── AST.h ├── README.md ├── compiler.l ├── compiler.y ├── input.txt ├── makefile ├── traverseTree.c └── traverseTree.h /AST.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2017 ARCS lab - All Rights Reserved 3 | * You may use, distribute and modify this code under the 4 | * terms of the ARCS license 5 | * 6 | * You should have received a copy of the ARCS license with 7 | * this file. If not, please write to: jhpark@arcs.skku.edu 8 | * 9 | * Freely use this source code, but not allowed for any 10 | * commercial uses. 11 | */ 12 | 13 | #ifndef AST_H 14 | #define AST_H 15 | 16 | typedef char bool; 17 | #define true 1 18 | #define false 0 19 | 20 | /** 21 | * Before you started.. 22 | * 23 | * This file is a header file to implement the Abstract Syntax Tree(AST). 24 | * You have to use the following structs as the nodes of the tree. 25 | * This file will be included in bison implementation and tree walker. 26 | * There are some informations that helps you using this header easly. 27 | * So we recommend you to read carefully not olny this comment, 28 | * but also those written in each line. 29 | * 30 | * First of all, all nodes are designed to target the visitor model. 31 | * There are two models of tree walkers; visitor and listener. 32 | * In visitor model, the developer controls the order of tree walks one by one. 33 | * You are developer in this case. 34 | * For example, when the tree walker program meets "Expr - Expr", 35 | * you have to make the program visit the right-hand side first at this time. 36 | * 37 | * The next information is how to implement "List" structs. 38 | * All structs of List is implemented in linked list. 39 | * The variable named "prev" connect between node. 40 | * The reason not using "next" variable is related to the execution model of Bison. 41 | * Bison tool is designed for visiting leaf node first. 42 | * It means that the parser will stack the nodes up while generating AST. 43 | */ 44 | 45 | typedef enum 46 | {eInt, eFloat, eClass} Type_e; 47 | typedef enum 48 | {eExpr, eAssign, eRet, eWhile, eDo, eFor, eIf, eCompound, eSemi} Stmt_e; 49 | typedef enum 50 | {eOper, eRef, eIntnum, eFloatnum} Expr_e; 51 | typedef enum 52 | {eUn, eAddi, eMult, eRela, eEqlt, eBracket} Oper_e; 53 | typedef enum 54 | {eVar, eCall} Ref_e; 55 | typedef enum 56 | {eNegative} Unop_e; 57 | typedef enum 58 | {ePlus, eMinus} Addi_e; 59 | typedef enum 60 | {eMul, eDiv} Mult_e; 61 | typedef enum 62 | {eLT, eGT, eLE, eGE} Rela_e; 63 | typedef enum 64 | {eEQ, eNE} Eqlt_e; 65 | typedef enum 66 | {eNon, eAsInt, eAsFloat} Assign_e; 67 | 68 | // Program := (ClassList)? (ClassMethod)? MainFunc 69 | struct Program { 70 | struct Class *_class; 71 | struct ClassMethodDef *classMethodDef; 72 | struct MainFunc *mainFunc; 73 | }; 74 | 75 | // ClassList := (Class)+ 76 | // Class := class id { (private : Member)? (public : Member)? } 77 | struct Class { 78 | char *id; 79 | struct Member *priMember; 80 | struct Member *pubMember; 81 | struct Class *prev; 82 | }; 83 | 84 | // Member := (VarDeclList)? (MethodDeclList)? (MethodDefList)? 85 | struct Member { 86 | struct VarDecl *varDecl; 87 | struct MethodDecl *methodDecl; 88 | struct MethodDef *methodDef; 89 | }; 90 | 91 | // VarDeclList := (VarDecl)+ 92 | // VarDecl := Type Ident (= (intnum|floatnum))? ; 93 | struct VarDecl { 94 | struct Type *type; 95 | struct Ident *ident; 96 | Assign_e assignType; 97 | union { 98 | int intnum; 99 | float floatnum; 100 | } assigner; 101 | struct VarDecl *prev; 102 | }; 103 | 104 | // MethodDeclList := (MethodDecl)+ 105 | // MethodDecl := Type id ( (ParamList)? ) ; 106 | struct MethodDecl { 107 | char *id; 108 | struct Type *type; 109 | struct Param *param; 110 | struct MethodDecl *prev; 111 | }; 112 | 113 | // MethodDefList := (MethodDef)+ 114 | // MethodDef := Type id ( (ParamList)? ) CompoundStmt 115 | struct MethodDef { 116 | char *id; 117 | struct Type *type; 118 | struct Param *param; 119 | struct CompoundStmt *compoundStmt; 120 | struct MethodDef *prev; 121 | }; 122 | 123 | // ClassMethodList := (ClassMethodDef)+ 124 | // ClassMethodDef := Type id :: id ( (ParamList)? ) CompoundStmt 125 | struct ClassMethodDef { 126 | struct Type *type; 127 | char *className; 128 | char *methodName; 129 | struct Param *param; 130 | struct CompoundStmt *compoundStmt; 131 | struct ClassMethodDef *prev; 132 | }; 133 | 134 | // MainFunc := int main ( ) CompoundStmt 135 | struct MainFunc { 136 | struct CompoundStmt *compoundStmt; 137 | }; 138 | 139 | // ParamList := Param (, Param)* 140 | // Param := Type Ident 141 | struct Param { 142 | struct Type *type; 143 | struct Ident *ident; 144 | struct Param *prev; 145 | }; 146 | 147 | // Ident := id 148 | // | id [ intnum ] 149 | struct Ident { 150 | char *id; 151 | int len; // 0 if scalar 152 | }; 153 | 154 | // Type := int 155 | // | float 156 | // | id 157 | struct Type { 158 | char *id; // NULL unless class type 159 | Type_e e; 160 | }; 161 | 162 | // CompoundStmt := { (VarDeclList)? (StmtList)? } 163 | struct CompoundStmt { 164 | struct VarDecl *varDecl; 165 | struct Stmt *stmt; 166 | }; 167 | 168 | // StmtList := (Stmt)+ 169 | // Stmt := ExprStmt 170 | // | AssignStmt 171 | // | RetStmt 172 | // | WhileStmt 173 | // | DoStmt 174 | // | ForStmt 175 | // | IfStmt 176 | // | CompoundStmt 177 | // | ; 178 | struct Stmt { 179 | Stmt_e e; 180 | union { 181 | struct ExprStmt *exprStmt; 182 | struct AssignStmt *assignStmt; 183 | struct RetStmt *retStmt; 184 | struct WhileStmt *whileStmt; 185 | struct DoStmt *doStmt; 186 | struct ForStmt *forStmt; 187 | struct IfStmt *ifStmt; 188 | struct CompoundStmt *compoundStmt; 189 | } type; 190 | struct Stmt *prev; 191 | }; 192 | 193 | // ExprStmt := Expr ; 194 | struct ExprStmt { 195 | struct Expr *expr; 196 | }; 197 | 198 | // AssignStmt := RefVarExpr = Expr ; 199 | struct AssignStmt { 200 | struct RefVarExpr *refVarExpr; 201 | struct Expr *expr; 202 | }; 203 | 204 | // RetStmt := return (Expr)? ; 205 | struct RetStmt { 206 | struct Expr *expr; 207 | }; 208 | 209 | // WhileStmt := while ( Expr ) Stmt 210 | struct WhileStmt { 211 | struct Expr *cond; 212 | struct Stmt *body; 213 | }; 214 | 215 | // DoStmt := do Stmt while ( Expr ) ; 216 | struct DoStmt { 217 | struct Expr *cond; 218 | struct Stmt *body; 219 | }; 220 | 221 | // ForStmt := for ( Expr ; Expr ; Expr ) Stmt 222 | struct ForStmt { 223 | struct Expr *init, *cond, *incr; 224 | struct Stmt *body; 225 | }; 226 | 227 | // IfStmt := if ( Expr ) Stmt (else Stmt)? 228 | struct IfStmt { 229 | struct Expr *cond; 230 | struct Stmt *ifBody; 231 | struct Stmt *elseBody; 232 | }; 233 | 234 | // Expr := OperExpr 235 | // | RefExpr 236 | // | intnum 237 | // | floatnum 238 | struct Expr { 239 | Expr_e e; 240 | union { 241 | struct OperExpr *operExpr; 242 | struct RefExpr *refExpr; 243 | int intnum; 244 | float floatnum; 245 | } type; 246 | }; 247 | 248 | // OperExpr := unop Expr 249 | // | Expr addiop Expr 250 | // | Expr multop Expr 251 | // | Expr relaop Expr 252 | // | Expr eqltop Expr 253 | // | ( Expr ) 254 | struct OperExpr { 255 | Oper_e e; 256 | union { 257 | struct UnOp *un; 258 | struct AddiOp *addi; 259 | struct MultOp *mult; 260 | struct RelaOp *rela; 261 | struct EqltOp *eqlt; 262 | struct Expr *bracket; 263 | } type; 264 | }; 265 | 266 | // RefExpr := RefVarExpr 267 | // | RefCallExpr 268 | struct RefExpr { 269 | Ref_e e; 270 | union { 271 | struct RefVarExpr *refVarExpr; 272 | struct RefCallExpr *refCallExpr; 273 | } type; 274 | }; 275 | 276 | // RefVarExpr := (RefExpr .)? IdentExpr 277 | struct RefVarExpr { 278 | struct RefExpr *refExpr; 279 | struct IdentExpr *identExpr; 280 | }; 281 | 282 | // RefCallExpr := (RefExpr .)? CallExpr 283 | struct RefCallExpr { 284 | struct RefExpr *refExpr; 285 | struct CallExpr *callExpr; 286 | }; 287 | 288 | // IdentExpr := id [ Expr ] 289 | // | id 290 | struct IdentExpr { 291 | char *id; 292 | struct Expr *expr; // NULL if scalar 293 | }; 294 | 295 | // CallExpr := id ( (ArgList)? ) 296 | struct CallExpr { 297 | char *id; 298 | struct Arg *arg; 299 | }; 300 | 301 | // ArgList := Expr (, Expr)* 302 | struct Arg { 303 | struct Expr *expr; 304 | struct Arg *prev; 305 | }; 306 | 307 | /** Following definitions are additional structs for OperExpr. **/ 308 | struct UnOp { 309 | Unop_e e; 310 | struct Expr *expr; 311 | }; 312 | 313 | struct AddiOp { 314 | Addi_e e; 315 | struct Expr *lhs; 316 | struct Expr *rhs; 317 | }; 318 | 319 | struct MultOp { 320 | Mult_e e; 321 | struct Expr *lhs; 322 | struct Expr *rhs; 323 | }; 324 | 325 | struct RelaOp { 326 | Rela_e e; 327 | struct Expr *lhs; 328 | struct Expr *rhs; 329 | }; 330 | 331 | struct EqltOp { 332 | Eqlt_e e; 333 | struct Expr *lhs; 334 | struct Expr *rhs; 335 | }; 336 | 337 | #endif 338 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Building the Abstract Syntax Tree and Symbol Table 2 | 3 | ## Objectives 4 | This project is to create a parser which builds an abstract syntax tree(AST) and symbol tables from reading a miniC++ program. In the process of parsing, we will build an AST and symbol table. At the end of parsing, it will print out an AST and symbol tables in 2 different text files. When printing out the AST, it will print out C++ like format code 5 | 6 | ## miniC++ grammar 7 | //(a)+ : one or more repetition of a 8 | 9 | //(a)* : zero or more repetition of a 10 | 11 | //(a)? : a optionally exists 12 | 13 | //unop : - 14 | 15 | //addiop : +, - 16 | 17 | //multop : *, / 18 | 19 | //relaop : <, >, <=, >= 20 | 21 | //eqltop : ==, != 22 | 23 | //id : [A-Za-z_][A-Za-z0-9_]* 24 | 25 | //intnum : [0-9]+ 26 | 27 | //floatnum : [0-9]+.[0-9]+ 28 | 29 | 30 | 31 | Program := (ClassList)? (ClassMethodList)? MainFunc 32 | 33 | 34 | 35 | ClassList := (Class)+ 36 | 37 | Class := class id { (private : Member)? (public : Member)? } Member := (VarDeclList)? (MethodDeclList)? (MethodDefList)? 38 | 39 | VarDeclList := (VarDecl)+ 40 | MethodDeclList := (FuncDecl)+ 41 | 42 | MethodDefList := (FuncDef)+ 43 | 44 | VarDecl := Type Ident (= (int | float))? ; FuncDecl := Type id ( (ParamList)? ) ; 45 | 46 | FuncDef := Type id ( (ParamList)? ) CompoundStmt 47 | 48 | ClassMethodList := (ClassMethodDef)+ 49 | 50 | ClassMethodDef := Type id :: id ( (ParamList)? ) CompoundStmt 51 | 52 | MainFunc := int main ( ) CompoundStmt 53 | 54 | ParamList := Param (, Param)* 55 | 56 | Param := Type Ident 57 | 58 | Ident := id | id [ intnum ] 59 | 60 | Type := int | float | id 61 | 62 | 63 | CompoundStmt := { (VarDeclList)? (StmtList)? } 64 | 65 | StmtList := (Stmt)+ 66 | 67 | Stmt := ExprStmt 68 | 69 | | AssignStmt | RetStmt 70 | 71 | | WhileStmt | DoStmt 72 | 73 | | ForStmt 74 | | IfStmt 75 | 76 | | CompoundStmt | ; 77 | 78 | ExprStmt := Expr ; 79 | 80 | AssignStmt := RefVarExpr = Expr ; 81 | 82 | RetStmt := return (Expr)? ; 83 | 84 | WhileStmt := while ( Expr ) Stmt 85 | 86 | DoStmt := do Stmt while ( Expr ) ; 87 | 88 | ForStmt := for ( Expr ; Expr ; Expr ) Stmt 89 | 90 | IfStmt := if ( Expr ) Stmt (else Stmt)? 91 | 92 | Expr := OperExpr 93 | 94 | | RefExpr | intnum | floatnum 95 | 96 | OperExpr := unop Expr 97 | | Expr addiop Expr 98 | | Expr multop Expr 99 | | Expr relaop Expr 100 | | Expr eqltop Expr 101 | | ( Expr ) 102 | 103 | RefExpr := RefVarExpr | RefCallExpr 104 | 105 | RefVarExpr := (RefExpr .)? IdentExpr 106 | 107 | RefCallExpr := (RefExpr .)? CallExpr 108 | 109 | IdentExpr := id [ Expr ] 110 | 111 | | id 112 | 113 | CallExpr := id ( (ArgList)? ) 114 | 115 | ArgList := Expr (, Expr)* 116 | 117 | ## Operator Precedence and Associativity 118 | Precedence Operator Description Associativity
119 | 1 ( ) Function call Left-to-right
120 | 2 - Unary minus Right-to-left
121 | 3 *, / Multiplication and division Left-to-right
122 | 4 +, - Addition and subtraction Left-to-right
123 | 5 <, >, <=, >= Relational operators Left-to-right
124 | 6 ==, != Equality operators Left-to-right
125 | 7 = Assignment Right-to-left
126 | 127 | ### 1. The structure of the project 128 | 129 | AST.h : the data structure of miniC++ grammar 130 | input.txt: the input C++ standard format program used to build AST and SymbolTable(source code) 131 | makefile: use "make" command to execute flex+bison command and link them into a executable program, also provide make clean to clear all the generated files 132 | compiler.l: flex file 133 | compiler.y: bison file 134 | traverseTree.h: a header file used to declare some function to traverse the AST 135 | traverseTree.c: the implementation of the .h file 136 | 137 | ### 2. How to run the program 138 | 139 | STEP 1: enter the root directory of the all the files i mentioned above in the linux terminal 140 | STEP 2: use the command: "make", then will generate all the files 141 | STEP 3: use the command: "./compiler 4 | #include 5 | #include 6 | #include "AST.h" 7 | #include "compiler.tab.h" 8 | %} 9 | 10 | 11 | /* Regular Expression Units */ 12 | INTNUM [0-9]+ 13 | FLOATNUM [0-9]+\.[0-9]+ 14 | ID [A-Za-z][A-Za-z0-9_]* 15 | SPACE [ \t\r\n] 16 | 17 | /* Rules */ 18 | /* return tokens by Regular Expression(RE) */ 19 | %% 20 | int return INT; 21 | float return FLOAT; 22 | main return MAIN; 23 | private return PRIVATE; 24 | public return PUBLIC; 25 | return return RETURN; 26 | while return WHILE; 27 | do return DO; 28 | if return IF; 29 | else return ELSE; 30 | for return FOR; 31 | 32 | ":" return yytext[0]; 33 | ";" return yytext[0]; 34 | "." return yytext[0]; 35 | "," return yytext[0]; 36 | "=" return yytext[0]; 37 | "!" return yytext[0]; 38 | "[" return yytext[0]; 39 | "]" return yytext[0]; 40 | "{" return yytext[0]; 41 | "}" return yytext[0]; 42 | "(" return yytext[0]; 43 | ")" return yytext[0]; 44 | "\"" {return DOUBLE_QUO;} 45 | "\'" {return SINGLE_QUO;} 46 | "\&" {return AND;} 47 | "\|" {return OR;} 48 | "+" return PLUS; 49 | "-" return MINUS; 50 | "*" return MULT; 51 | "/" return DIV; 52 | ">" return GT; 53 | "<" return LT; 54 | "<=" return LE; 55 | ">=" return GE; 56 | "==" return EQ; 57 | "!=" return NE; 58 | 59 | {INTNUM} { 60 | yylval.intnum = atoi(yytext); 61 | return INTNUM; 62 | } 63 | 64 | {FLOATNUM} { 65 | yylval.floatnum = atof(yytext); 66 | return FLOATNUM; 67 | } 68 | 69 | {ID} { 70 | yylval.id = strndup(yytext, yyleng); 71 | return ID; 72 | } 73 | 74 | {SPACE} {/*do nothing here*/} 75 | %% 76 | 77 | /* User Code */ -------------------------------------------------------------------------------- /compiler.y: -------------------------------------------------------------------------------- 1 | /* Definitions */ 2 | %{ 3 | #include 4 | #include 5 | #include 6 | #include "AST.h" 7 | #include "traverseTree.h" 8 | /* global variables which can be used in other .c .h */ 9 | struct Program *head; 10 | 11 | FILE *fp1; // FILE pointer to write AST to file 12 | FILE *fp2; // FILE pointer to write symbol tree to file 13 | /* yyerror function */ 14 | void yyerror(char* text) { 15 | fprintf(stderr, "%s\n", text); 16 | } 17 | %} 18 | 19 | /* definitions of tokens and types passed by FLEX */ 20 | %union { 21 | /* pointers for the AST struct nodes */ 22 | struct Program *Program_ptr; 23 | struct Class *Class_ptr; 24 | struct Member *Member_ptr; 25 | struct VarDecl *VarDecl_ptr; 26 | struct MethodDecl *MethodDecl_ptr; 27 | struct MethodDef *MethodDef_ptr; 28 | struct ClassMethodDef *ClassMethodDef_ptr; 29 | struct MainFunc *MainFunc_ptr; 30 | struct Param *Param_ptr; 31 | struct Ident *Ident_ptr; 32 | struct Type *Type_ptr; 33 | struct CompoundStmt *CompoundStmt_ptr; 34 | struct Stmt *Stmt_ptr; 35 | struct ExprStmt *ExprStmt_ptr; 36 | struct AssignStmt *AssignStmt_ptr; 37 | struct RetStmt *RetStmt_ptr; 38 | struct WhileStmt *WhileStmt_ptr; 39 | struct DoStmt *DoStmt_ptr; 40 | struct ForStmt *ForStmt_ptr; 41 | struct IfStmt *IfStmt_ptr; 42 | struct Expr *Expr_ptr; 43 | struct OperExpr *OperExpr_ptr; 44 | struct RefExpr *RefExpr_ptr; 45 | struct RefVarExpr *RefVarExpr_ptr; 46 | struct RefCallExpr *RefCallExpr_ptr; 47 | struct IdentExpr *IdentExpr_ptr; 48 | struct CallExpr *CallExpr_ptr; 49 | struct Arg *Arg_ptr; 50 | /* int, float to char* */ 51 | int intnum; 52 | float floatnum; 53 | char *id; 54 | } 55 | 56 | /* token definitions */ 57 | %token INTNUM 58 | %token FLOATNUM 59 | %token ID 60 | %token INT FLOAT MAIN PRIVATE PUBLIC 61 | %token IF ELSE FOR WHILE DO RETURN 62 | %token DOUBLE_QUO SINGLE_QUO AND OR PLUS MINUS MULT DIV GT LT LE GE EQ NE 63 | 64 | /* type(non-terminal) definitions */ 65 | %type PROGRAM 66 | %type CLASS CLASSLIST 67 | %type MEMBER 68 | %type VARDECL VARDECLLIST 69 | %type METHODDECL METHODDECLLIST 70 | %type METHODDEF METHODDEFLIST 71 | %type CLASSMETHODDEF CLASSMETHODDEFLIST 72 | %type MAINFUNC 73 | %type PARAM PARAMLIST 74 | %type IDENT 75 | %type TYPE 76 | %type COMPOUNDSTMT 77 | %type STMT STMTLIST 78 | %type EXPRSTMT 79 | %type ASSIGNSTMT 80 | %type RETSTMT 81 | %type WHILESTMT 82 | %type DOSTMT 83 | %type FORSTMT 84 | %type IFSTMT 85 | %type EXPR 86 | %type OPEREXPR 87 | %type REFEXPR 88 | %type REFVAREXPR 89 | %type REFCALLEXPR 90 | %type IDENTEXPR 91 | %type CALLEXPR 92 | %type ARG ARGLIST 93 | 94 | /* priority definitions from top to down, the priority becomes higher */ 95 | %right '=' 96 | %left EQ NE 97 | %left LE GE GT LT 98 | %left PLUS MINUS 99 | %left MULT DIV 100 | %right UNARY 101 | %left '(' ')' 102 | 103 | /*no associativity symbols */ 104 | %nonassoc IF_THEN 105 | %nonassoc ELSE 106 | 107 | /* the start token */ 108 | %start PROGRAM 109 | 110 | 111 | 112 | 113 | /* C++ Program Grammar Rules */ 114 | %% 115 | // Program := (ClassList)? (ClassMethod)? MainFunc 116 | PROGRAM: CLASSLIST CLASSMETHODDEFLIST MAINFUNC { 117 | struct Program *p = (struct Program*)malloc(sizeof(struct Program)); // create a new node and allocate the space 118 | p->_class = $1; 119 | p->classMethodDef = $2; 120 | p->mainFunc = $3; 121 | head = p; 122 | $$ = p; 123 | } 124 | | CLASSLIST MAINFUNC { 125 | struct Program *p = (struct Program*)malloc(sizeof(struct Program)); 126 | p->_class = $1; 127 | p->classMethodDef = NULL; 128 | p->mainFunc = $2; 129 | head = p; 130 | $$ = p; 131 | } 132 | | CLASSMETHODDEFLIST MAINFUNC { 133 | struct Program *p = (struct Program*)malloc(sizeof(struct Program)); 134 | p->_class = NULL; 135 | p->classMethodDef = $1; 136 | p->mainFunc = $2; 137 | head = p; 138 | $$ = p; 139 | } 140 | | MAINFUNC { 141 | struct Program *p = (struct Program*)malloc(sizeof(struct Program)); 142 | p->_class = NULL; 143 | p->classMethodDef = NULL; 144 | p->mainFunc = $1; 145 | head = p; 146 | $$ = p; 147 | } 148 | ; 149 | 150 | // ClassList := (Class)+ 151 | // Class := class id { (private : Member)? (public : Member)? } 152 | CLASSLIST: CLASS { 153 | struct Class *c; 154 | c = $1; 155 | c->prev = NULL; 156 | $$ = c; 157 | } 158 | | CLASSLIST CLASS { 159 | struct Class *c; 160 | c = $2; 161 | c->prev = $1; 162 | $$ = c; 163 | } 164 | ; 165 | 166 | CLASS: TYPE ID '{' PRIVATE ':' MEMBER PUBLIC ':' MEMBER '}' ';' { 167 | struct Class *c = (struct Class*)malloc(sizeof(struct Class)); 168 | c->id = $2; 169 | c->priMember = $6; 170 | c->pubMember = $9; 171 | $$ = c; 172 | } 173 | | TYPE ID '{' PRIVATE ':' MEMBER '}' ';' { 174 | struct Class *c = (struct Class*)malloc(sizeof(struct Class)); 175 | c->id = $2; 176 | c->priMember = $6; 177 | c->pubMember = NULL; 178 | $$ = c; 179 | } 180 | | TYPE ID '{' PUBLIC ':' MEMBER '}' ';' { 181 | struct Class *c = (struct Class*)malloc(sizeof(struct Class)); 182 | c->id = $2; 183 | c->priMember = NULL; 184 | c->pubMember = $6; 185 | $$ = c; 186 | } 187 | | TYPE ID '{' '}' ';' { 188 | struct Class *c = (struct Class*)malloc(sizeof(struct Class)); 189 | c->id = $2; 190 | c->priMember = NULL; 191 | c->pubMember = NULL; 192 | $$ = c; 193 | } 194 | ; 195 | 196 | // Member := (VarDeclList)? (MethodDeclList)? (MethodDefList)? 197 | MEMBER: VARDECLLIST METHODDECLLIST METHODDEFLIST { 198 | struct Member *m = (struct Member*)malloc(sizeof(struct Member)); 199 | m->varDecl = $1; 200 | m->methodDecl = $2; 201 | m->methodDef = $3; 202 | $$ = m; 203 | } 204 | | VARDECLLIST METHODDECLLIST { 205 | struct Member *m = (struct Member*)malloc(sizeof(struct Member)); 206 | m->varDecl = $1; 207 | m->methodDecl = $2; 208 | m->methodDef = NULL; 209 | $$ = m; 210 | } 211 | | VARDECLLIST METHODDEFLIST { 212 | struct Member *m = (struct Member*)malloc(sizeof(struct Member)); 213 | m->varDecl = $1; 214 | m->methodDecl = NULL; 215 | m->methodDef = $2; 216 | $$ = m; 217 | } 218 | | METHODDECLLIST METHODDEFLIST { 219 | struct Member *m = (struct Member*)malloc(sizeof(struct Member)); 220 | m->varDecl = NULL; 221 | m->methodDecl = $1; 222 | m->methodDef = $2; 223 | $$ = m; 224 | } 225 | | VARDECLLIST { 226 | struct Member *m = (struct Member*)malloc(sizeof(struct Member)); 227 | m->varDecl = $1; 228 | m->methodDecl = NULL; 229 | m->methodDef = NULL; 230 | $$ = m; 231 | } 232 | | METHODDECLLIST { 233 | struct Member *m = (struct Member*)malloc(sizeof(struct Member)); 234 | m->varDecl = NULL; 235 | m->methodDecl = $1; 236 | m->methodDef = NULL; 237 | $$ = m; 238 | } 239 | | METHODDEFLIST { 240 | struct Member *m = (struct Member*)malloc(sizeof(struct Member)); 241 | m->varDecl = NULL; 242 | m->methodDecl = NULL; 243 | m->methodDef = $1; 244 | $$ = m; 245 | } 246 | ; 247 | 248 | // VarDeclList := (VarDecl)+ 249 | // VarDecl := Type Ident (= (intnum|floatnum))?; 250 | VARDECLLIST: VARDECL { 251 | struct VarDecl *v; 252 | v = $1; 253 | v->prev = NULL; 254 | $$ = v; 255 | } 256 | | VARDECLLIST VARDECL { 257 | struct VarDecl *v; 258 | v = $2; 259 | v->prev = $1; 260 | $$ = v; 261 | } 262 | ; 263 | 264 | VARDECL: TYPE IDENT '=' INTNUM ';' { 265 | struct VarDecl *v = (struct VarDecl*)malloc(sizeof(struct VarDecl)); 266 | v->type = $1; 267 | v->ident = $2; 268 | v->assignType = eAsInt; 269 | v->assigner.intnum = $4; 270 | $$ = v; 271 | } 272 | | TYPE IDENT '=' FLOATNUM ';' { 273 | struct VarDecl *v = (struct VarDecl*)malloc(sizeof(struct VarDecl)); 274 | v->type = $1; 275 | v->ident = $2; 276 | v->assignType = eAsFloat; 277 | v->assigner.floatnum = $4; 278 | $$ = v; 279 | } 280 | | TYPE IDENT ';' { 281 | struct VarDecl *v = (struct VarDecl*)malloc(sizeof(struct VarDecl)); 282 | v->type = $1; 283 | v->ident = $2; 284 | v->assignType = eNon; 285 | $$ = v; 286 | } 287 | ; 288 | 289 | // MethodDeclList := (MethodDecl)+ 290 | // MethodDecl := Type id ( (ParamList)? ) ; 291 | METHODDECLLIST: METHODDECL { 292 | struct MethodDecl *m; 293 | m = $1; 294 | m->prev = NULL; 295 | $$ = m; 296 | } 297 | | METHODDECLLIST METHODDECL { 298 | struct MethodDecl *m; 299 | m = $2; 300 | m->prev = $1; 301 | $$ = m; 302 | } 303 | ; 304 | 305 | METHODDECL: TYPE ID '(' PARAMLIST ')' ';' { 306 | struct MethodDecl *m = (struct MethodDecl*)malloc(sizeof(struct MethodDecl)); 307 | m->type = $1; 308 | m->id = $2; 309 | m->param = $4; 310 | $$ = m; 311 | } 312 | | TYPE ID '(' ')' ';' { 313 | struct MethodDecl *m = (struct MethodDecl*)malloc(sizeof(struct MethodDecl)); 314 | m->type = $1; 315 | m->id = $2; 316 | m->param = NULL; 317 | $$ = m; 318 | } 319 | ; 320 | 321 | // MethodDefList := (MethodDef)+ 322 | // MethodDef := Type id ( (ParamList)? ) CompoundStmt 323 | METHODDEFLIST: METHODDEF { 324 | struct MethodDef *m; 325 | m = $1; 326 | m->prev = NULL; 327 | $$ = m; 328 | } 329 | | METHODDEFLIST METHODDEF { 330 | struct MethodDef *m; 331 | m = $2; 332 | m->prev = $1; 333 | $$ = m; 334 | } 335 | ; 336 | 337 | METHODDEF: TYPE ID '(' PARAMLIST ')' COMPOUNDSTMT { 338 | struct MethodDef *m = (struct MethodDef*)malloc(sizeof(struct MethodDef)); 339 | m->type = $1; 340 | m->id = $2; 341 | m->param = $4; 342 | m->compoundStmt = $6; 343 | $$ = m; 344 | } 345 | | TYPE ID '(' ')' COMPOUNDSTMT { 346 | struct MethodDef *m = (struct MethodDef*)malloc(sizeof(struct MethodDef)); 347 | m->type = $1; 348 | m->id = $2; 349 | m->param = NULL; 350 | m->compoundStmt = $5; 351 | $$ = m; 352 | } 353 | ; 354 | 355 | // ClassMethodList := (ClassMethodDef)+ 356 | // ClassMethodDef := Type id :: id ( (ParamList)? ) CompoundStmt 357 | CLASSMETHODDEFLIST: CLASSMETHODDEF { 358 | struct ClassMethodDef *c; 359 | c = $1; 360 | c->prev = NULL; 361 | $$ = c; 362 | } 363 | | CLASSMETHODDEFLIST CLASSMETHODDEF { 364 | struct ClassMethodDef *c; 365 | c = $2; 366 | c->prev = $1; 367 | $$ = c; 368 | } 369 | ; 370 | 371 | CLASSMETHODDEF: TYPE ID ':' ':' ID '(' PARAMLIST ')' COMPOUNDSTMT { 372 | struct ClassMethodDef *c = (struct ClassMethodDef*)malloc(sizeof(struct ClassMethodDef)); 373 | c->type = $1; 374 | c->className = $2; 375 | c->methodName = $5; 376 | c->param = $7; 377 | c->compoundStmt = $9; 378 | $$ = c; 379 | } 380 | | TYPE ID ':' ':' ID '(' ')' COMPOUNDSTMT { 381 | struct ClassMethodDef *c = (struct ClassMethodDef*)malloc(sizeof(struct ClassMethodDef)); 382 | c->type = $1; 383 | c->className = $2; 384 | c->methodName = $5; 385 | c->param = NULL; 386 | c->compoundStmt = $8; 387 | $$ = c; 388 | } 389 | ; 390 | 391 | // MainFunc := int main ( ) CompoundStmt 392 | MAINFUNC: INT MAIN '(' ')' COMPOUNDSTMT { 393 | struct MainFunc *m = (struct MainFunc*)malloc(sizeof(struct MainFunc)); 394 | m->compoundStmt = $5; 395 | $$ = m; 396 | } 397 | ; 398 | 399 | // ParamList := Param (, Param)* 400 | // Param := Type Ident 401 | PARAMLIST: PARAM { 402 | struct Param* p; 403 | p = $1; 404 | p->prev = NULL; 405 | $$ = p; 406 | } 407 | | PARAMLIST ',' PARAM { 408 | struct Param* p; 409 | p = $3; 410 | p->prev = $1; 411 | $$ = p; 412 | } 413 | ; 414 | 415 | PARAM: TYPE IDENT { 416 | struct Param *p = (struct Param*)malloc(sizeof(struct Param)); 417 | p->type = $1; 418 | p->ident = $2; 419 | p->prev = NULL; 420 | $$ = p; 421 | } 422 | ; 423 | 424 | // Ident := id 425 | // | id [ intnum ] 426 | IDENT: ID { 427 | struct Ident *i = (struct Ident*)malloc(sizeof(struct Ident)); 428 | i->id = $1; 429 | i->len = 0; 430 | $$ = i; 431 | } 432 | | ID '[' INTNUM ']' { 433 | struct Ident *i = (struct Ident*)malloc(sizeof(struct Ident)); 434 | i->id = $1; 435 | i->len = $3; 436 | $$ = i; 437 | } 438 | ; 439 | 440 | // Type := int 441 | // | float 442 | // | id 443 | TYPE: INT { 444 | struct Type *t = (struct Type*)malloc(sizeof(struct Type)); 445 | t->id = NULL; 446 | t->e = eInt; 447 | $$ = t; 448 | } 449 | | FLOAT { 450 | struct Type *t = (struct Type*)malloc(sizeof(struct Type)); 451 | t->id = NULL; 452 | t->e = eFloat; 453 | $$ = t; 454 | } 455 | | ID { 456 | struct Type *t = (struct Type*)malloc(sizeof(struct Type)); 457 | t->id = $1; 458 | t->e = eClass; 459 | $$ = t; 460 | } 461 | 462 | // CompoundStmt := { (VarDeclList)? (StmtList)? } 463 | COMPOUNDSTMT: '{' '}' { 464 | struct CompoundStmt *comp = (struct CompoundStmt*)malloc(sizeof(struct CompoundStmt)); 465 | comp->varDecl = NULL; 466 | comp->stmt = NULL; 467 | $$ = comp; 468 | 469 | } 470 | | '{' STMTLIST '}' { 471 | struct CompoundStmt *comp = (struct CompoundStmt*)malloc(sizeof(struct CompoundStmt)); 472 | comp->varDecl = NULL; 473 | comp->stmt = $2; 474 | $$ = comp; 475 | } 476 | | '{' VARDECLLIST STMTLIST '}' { 477 | struct CompoundStmt *comp = (struct CompoundStmt*)malloc(sizeof(struct CompoundStmt)); 478 | comp->varDecl = $2; 479 | comp->stmt = $3; 480 | $$ = comp; 481 | } 482 | | '{' VARDECLLIST '}' { 483 | struct CompoundStmt *comp = (struct CompoundStmt*)malloc(sizeof(struct CompoundStmt)); 484 | comp->varDecl = $2; 485 | comp->stmt = NULL; 486 | $$ = comp; 487 | } 488 | ; 489 | 490 | // StmtList := (Stmt)+ 491 | // Stmt := ExprStmt 492 | // | AssignStmt 493 | // | RetStmt 494 | // | WhileStmt 495 | // | DoStmt 496 | // | ForStmt 497 | // | IfStmt 498 | // | CompoundStmt 499 | // | ; 500 | STMTLIST: STMT { 501 | struct Stmt *stmt; 502 | stmt = $1; 503 | stmt->prev = NULL; 504 | $$ = stmt; 505 | } 506 | | STMTLIST STMT { 507 | struct Stmt *stmt; 508 | stmt = $2; 509 | stmt->prev = $1; 510 | $$ = stmt; 511 | } 512 | ; 513 | 514 | STMT: EXPRSTMT { 515 | struct Stmt *stmt = (struct Stmt*)malloc(sizeof(struct Stmt)); 516 | stmt->e = eExpr; 517 | stmt->type.exprStmt = $1; 518 | $$ = stmt; 519 | } 520 | | ASSIGNSTMT { 521 | struct Stmt *stmt = (struct Stmt*)malloc(sizeof(struct Stmt)); 522 | stmt->e = eAssign; 523 | stmt->type.assignStmt = $1; 524 | $$ = stmt; 525 | } 526 | | RETSTMT { 527 | struct Stmt *stmt = (struct Stmt*)malloc(sizeof(struct Stmt)); 528 | stmt->e = eRet; 529 | stmt->type.retStmt = $1; 530 | $$ = stmt; 531 | } 532 | | WHILESTMT { 533 | struct Stmt *stmt = (struct Stmt*)malloc(sizeof(struct Stmt)); 534 | stmt->e = eWhile; 535 | stmt->type.whileStmt = $1; 536 | $$ = stmt; 537 | } 538 | | DOSTMT { 539 | struct Stmt *stmt = (struct Stmt*)malloc(sizeof(struct Stmt)); 540 | stmt->e = eDo; 541 | stmt->type.doStmt = $1; 542 | $$ = stmt; 543 | } 544 | | FORSTMT { 545 | struct Stmt *stmt = (struct Stmt*)malloc(sizeof(struct Stmt)); 546 | stmt->e = eFor; 547 | stmt->type.forStmt = $1; 548 | $$ = stmt; 549 | } 550 | | IFSTMT { 551 | struct Stmt *stmt = (struct Stmt*)malloc(sizeof(struct Stmt)); 552 | stmt->e = eIf; 553 | stmt->type.ifStmt = $1; 554 | $$ = stmt; 555 | } 556 | | COMPOUNDSTMT { 557 | struct Stmt *stmt = (struct Stmt*)malloc(sizeof(struct Stmt)); 558 | stmt->e = eCompound; 559 | stmt->type.compoundStmt = $1; 560 | $$ = stmt; 561 | } 562 | | ';' { 563 | struct Stmt *stmt = (struct Stmt*)malloc(sizeof(struct Stmt)); 564 | stmt->e = eSemi; 565 | $$ = stmt; 566 | } 567 | ; 568 | 569 | // ExprStmt := Expr ; 570 | EXPRSTMT: EXPR ';' { 571 | struct ExprStmt *e = (struct ExprStmt*)malloc(sizeof(struct ExprStmt)); 572 | e->expr = $1; 573 | $$ = e; 574 | } 575 | ; 576 | 577 | // AssignStmt := RefVarExpr = Expr ; 578 | ASSIGNSTMT: REFVAREXPR '=' EXPR ';' { 579 | struct AssignStmt *a = (struct AssignStmt*)malloc(sizeof(struct AssignStmt)); 580 | a->refVarExpr = $1; 581 | a->expr = $3; 582 | $$ = a; 583 | } 584 | ; 585 | 586 | // RetStmt := return (Expr)? ; 587 | RETSTMT: RETURN ';' { 588 | struct RetStmt *r = (struct RetStmt*)malloc(sizeof(struct RetStmt)); 589 | r->expr = NULL; 590 | $$ = r; 591 | } 592 | | RETURN EXPR ';' { 593 | struct RetStmt *r = (struct RetStmt*)malloc(sizeof(struct RetStmt)); 594 | r->expr = $2; 595 | $$ = r; 596 | } 597 | ; 598 | 599 | // WhileStmt := while ( Expr ) Stmt 600 | WHILESTMT: WHILE '(' EXPR ')' STMT { 601 | struct WhileStmt *w = (struct WhileStmt*)malloc(sizeof(struct WhileStmt)); 602 | w->cond = $3; 603 | w->body = $5; 604 | $$ = w; 605 | } 606 | ; 607 | 608 | // DoStmt := do Stmt while ( Expr ) ; 609 | DOSTMT: DO STMT WHILE '(' EXPR ')' ';' { 610 | struct DoStmt *d = (struct DoStmt*)malloc(sizeof(struct DoStmt)); 611 | d->cond = $5; 612 | d->body = $2; 613 | $$ = d; 614 | } 615 | ; 616 | 617 | // ForStmt := for ( Expr ; Expr ; Expr ) Stmt 618 | FORSTMT: FOR '(' EXPR ';' EXPR ';' EXPR ')' STMT { 619 | struct ForStmt *f = (struct ForStmt*)malloc(sizeof(struct ForStmt)); 620 | f->init = $3; 621 | f->cond = $5; 622 | f->incr = $7; 623 | f->body = $9; 624 | $$ = f; 625 | } 626 | ; 627 | 628 | /* priority and conflict by using %prec */ 629 | // IfStmt := if ( Expr ) Stmt (else Stmt)? 630 | IFSTMT: IF '(' EXPR ')' STMT %prec IF_THEN { 631 | struct IfStmt *i = (struct IfStmt*)malloc(sizeof(struct IfStmt)); 632 | i->cond = $3; 633 | i->ifBody = $5; 634 | i->elseBody = NULL; 635 | $$ = i; 636 | } 637 | | IF '(' EXPR ')' STMT ELSE STMT { 638 | struct IfStmt *i = (struct IfStmt*)malloc(sizeof(struct IfStmt)); 639 | i->cond = $3; 640 | i->ifBody = $5; 641 | i->elseBody = $7; 642 | $$ = i; 643 | } 644 | ; 645 | 646 | // Expr := OperExpr 647 | // | RefExpr 648 | // | intnum 649 | // | floatnum 650 | EXPR: OPEREXPR { 651 | struct Expr *expr = (struct Expr*)malloc(sizeof(struct Expr)); 652 | expr->e = eOper; 653 | expr->type.operExpr = $1; 654 | $$ = expr; 655 | } 656 | | REFEXPR { 657 | struct Expr *expr = (struct Expr*)malloc(sizeof(struct Expr)); 658 | expr->e = eRef; 659 | expr->type.refExpr = $1; 660 | $$ = expr; 661 | } 662 | | INTNUM { 663 | struct Expr *expr = (struct Expr*)malloc(sizeof(struct Expr)); 664 | expr->e = eIntnum; 665 | expr->type.intnum = $1; 666 | $$ = expr; 667 | } 668 | | FLOATNUM { 669 | struct Expr *expr = (struct Expr*)malloc(sizeof(struct Expr)); 670 | expr->e = eFloatnum; 671 | expr->type.floatnum = $1; 672 | $$ = expr; 673 | } 674 | ; 675 | 676 | // OperExpr := unop Expr 677 | // | Expr addiop Expr 678 | // | Expr multop Expr 679 | // | Expr relaop Expr 680 | // | Expr eqltop Expr 681 | // | ( Expr ) 682 | OPEREXPR: MINUS EXPR %prec UNARY { 683 | struct UnOp *unop = (struct UnOp*)malloc(sizeof(struct UnOp)); 684 | unop->e = eNegative; 685 | unop->expr = $2; 686 | 687 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 688 | operexpr->e = eUn; 689 | operexpr->type.un = unop; 690 | $$ = operexpr; 691 | } 692 | 693 | 694 | | EXPR PLUS EXPR { 695 | struct AddiOp *addiop = (struct AddiOp*)malloc(sizeof(struct AddiOp)); 696 | addiop->lhs = $1; 697 | addiop->rhs = $3; 698 | addiop->e = ePlus; 699 | 700 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 701 | operexpr->e = eAddi; 702 | operexpr->type.addi = addiop; 703 | $$ = operexpr; 704 | } 705 | | EXPR MINUS EXPR { 706 | struct AddiOp *addiop = (struct AddiOp*)malloc(sizeof(struct AddiOp)); 707 | addiop->lhs = $1; 708 | addiop->rhs = $3; 709 | addiop->e = eMinus; 710 | 711 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 712 | operexpr->e = eAddi; 713 | operexpr->type.addi = addiop; 714 | $$ = operexpr; 715 | } 716 | 717 | 718 | | EXPR MULT EXPR { 719 | struct MultOp *multop = (struct MultOp*)malloc(sizeof(struct MultOp)); 720 | multop->lhs = $1; 721 | multop->rhs = $3; 722 | multop->e = eMul; 723 | 724 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 725 | operexpr->e = eMult; 726 | operexpr->type.mult = multop; 727 | $$ = operexpr; 728 | } 729 | | EXPR DIV EXPR { 730 | struct MultOp *multop = (struct MultOp*)malloc(sizeof(struct MultOp)); 731 | multop->lhs = $1; 732 | multop->rhs = $3; 733 | multop->e = eDiv; 734 | 735 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 736 | operexpr->e = eMult; 737 | operexpr->type.mult = multop; 738 | $$ = operexpr; 739 | } 740 | 741 | 742 | | EXPR LT EXPR { 743 | struct RelaOp *relaop = (struct RelaOp*)malloc(sizeof(struct RelaOp)); 744 | relaop->lhs = $1; 745 | relaop->rhs = $3; 746 | relaop->e = eLT; 747 | 748 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 749 | operexpr->e = eRela; 750 | operexpr->type.rela = relaop; 751 | $$ = operexpr; 752 | } 753 | | EXPR GT EXPR { 754 | struct RelaOp *relaop = (struct RelaOp*)malloc(sizeof(struct RelaOp)); 755 | relaop->lhs = $1; 756 | relaop->rhs = $3; 757 | relaop->e = eGT; 758 | 759 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 760 | operexpr->e = eRela; 761 | operexpr->type.rela = relaop; 762 | $$ = operexpr; 763 | } 764 | | EXPR LE EXPR { 765 | struct RelaOp *relaop = (struct RelaOp*)malloc(sizeof(struct RelaOp)); 766 | relaop->lhs = $1; 767 | relaop->rhs = $3; 768 | relaop->e = eLE; 769 | 770 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 771 | operexpr->e = eRela; 772 | operexpr->type.rela = relaop; 773 | $$ = operexpr; 774 | } 775 | | EXPR GE EXPR { 776 | struct RelaOp *relaop = (struct RelaOp*)malloc(sizeof(struct RelaOp)); 777 | relaop->lhs = $1; 778 | relaop->rhs = $3; 779 | relaop->e = eGE; 780 | 781 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 782 | operexpr->e = eRela; 783 | operexpr->type.rela = relaop; 784 | $$ = operexpr; 785 | } 786 | 787 | 788 | | EXPR EQ EXPR { 789 | struct EqltOp *eqltop = (struct EqltOp*)malloc(sizeof(struct EqltOp));; 790 | eqltop->lhs = $1; 791 | eqltop->rhs = $3; 792 | eqltop->e = eEQ; 793 | 794 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 795 | operexpr->e = eEqlt; 796 | operexpr->type.eqlt = eqltop; 797 | $$ = operexpr; 798 | } 799 | | EXPR NE EXPR { 800 | struct EqltOp *eqltop = (struct EqltOp*)malloc(sizeof(struct EqltOp));; 801 | eqltop->lhs = $1; 802 | eqltop->rhs = $3; 803 | eqltop->e = eNE; 804 | 805 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 806 | operexpr->e = eEqlt; 807 | operexpr->type.eqlt = eqltop; 808 | $$ = operexpr; 809 | } 810 | 811 | 812 | | '(' EXPR ')' { 813 | struct OperExpr *operexpr = (struct OperExpr*)malloc(sizeof(struct OperExpr)); 814 | operexpr->e = eBracket; 815 | operexpr->type.bracket = $2; 816 | $$ = operexpr; 817 | } 818 | ; 819 | 820 | // RefExpr := RefVarExpr 821 | // | RefCallExpr 822 | REFEXPR: REFVAREXPR { 823 | struct RefExpr *r = (struct RefExpr*)malloc(sizeof(struct RefExpr)); 824 | r->e = eVar; 825 | r->type.refVarExpr = $1; 826 | $$ = r; 827 | } 828 | | REFCALLEXPR { 829 | struct RefExpr *r = (struct RefExpr*)malloc(sizeof(struct RefExpr)); 830 | r->e = eCall; 831 | r->type.refCallExpr = $1; 832 | $$ = r; 833 | } 834 | ; 835 | 836 | // RefVarExpr := (RefExpr .)? IdentExpr 837 | REFVAREXPR: REFEXPR '.' IDENTEXPR { 838 | struct RefVarExpr *r = (struct RefVarExpr*)malloc(sizeof(struct RefVarExpr)); 839 | r->refExpr = $1; 840 | r->identExpr = $3; 841 | $$ = r; 842 | } 843 | | IDENTEXPR { 844 | struct RefVarExpr *r = (struct RefVarExpr*)malloc(sizeof(struct RefVarExpr)); 845 | r->refExpr = NULL; 846 | r->identExpr = $1; 847 | $$ = r; 848 | } 849 | ; 850 | 851 | // RefCallExpr := (RefExpr .)? CallExpr 852 | REFCALLEXPR: REFEXPR '.' CALLEXPR { 853 | struct RefCallExpr *r = (struct RefCallExpr*)malloc(sizeof(struct RefCallExpr)); 854 | r->refExpr = $1; 855 | r->callExpr = $3; 856 | $$ = r; 857 | } 858 | | CALLEXPR { 859 | struct RefCallExpr *r = (struct RefCallExpr*)malloc(sizeof(struct RefCallExpr)); 860 | r->refExpr = NULL; 861 | r->callExpr = $1; 862 | $$ = r; 863 | } 864 | ; 865 | 866 | // IdentExpr := id [ Expr ] 867 | // | id 868 | IDENTEXPR: ID '[' EXPR ']' { 869 | struct IdentExpr* identexpr = (struct IdentExpr*)malloc(sizeof(struct IdentExpr)); 870 | identexpr->id = $1; 871 | identexpr->expr = $3; 872 | $$ = identexpr; 873 | } 874 | | ID { 875 | struct IdentExpr* identexpr = (struct IdentExpr*)malloc(sizeof(struct IdentExpr)); 876 | identexpr->id = $1; 877 | identexpr->expr = NULL; 878 | $$ = identexpr; 879 | } 880 | ; 881 | 882 | // CallExpr := id ( (ArgList)? ) 883 | CALLEXPR: ID '(' ARGLIST ')' { 884 | struct CallExpr *callexpr = (struct CallExpr*)malloc(sizeof(struct CallExpr)); 885 | callexpr->id = $1; 886 | callexpr->arg = $3; 887 | $$ = callexpr; 888 | } 889 | | ID '(' ')' { 890 | struct CallExpr *callexpr = (struct CallExpr*)malloc(sizeof(struct CallExpr)); 891 | callexpr->id = $1; 892 | callexpr->arg = NULL; 893 | $$ = callexpr; 894 | } 895 | ; 896 | 897 | // ArgList := Expr (, Expr)* 898 | ARGLIST: ARG { 899 | struct Arg* arg; 900 | arg = $1; 901 | arg->prev = NULL; 902 | $$ = arg; 903 | } 904 | | ARGLIST ',' ARG { 905 | struct Arg* arg; 906 | arg = $3; 907 | arg->prev = $1; 908 | $$ = arg; 909 | } 910 | ; 911 | 912 | ARG: EXPR { 913 | struct Arg *arg = (struct Arg*)malloc(sizeof(struct Arg)); 914 | arg->expr = $1; 915 | arg->prev = NULL; 916 | $$ = arg; 917 | } 918 | ; 919 | 920 | %% 921 | 922 | 923 | int main(int argc, char* argv[]) { 924 | fp1 = fopen("ASTtree.txt","w"); 925 | fp2 = fopen("symbolTable.txt","w"); 926 | /* initialize the start and end scope */ 927 | startScope = endScope = NULL; 928 | /* generate the AST tree in the process */ 929 | yyparse(); 930 | /* the start scope should be the GLOBAL means CLASS scope type */ 931 | startScope = createNewScope(CLASS_scope, NULL); 932 | /* same at the beginning */ 933 | endScope = startScope; 934 | /* traverse the AST generated by the yyparse() before */ 935 | visitProgram(head); 936 | 937 | fprintf(fp1, "\n"); 938 | fclose(fp1); 939 | fclose(fp2); 940 | return 0; 941 | } -------------------------------------------------------------------------------- /input.txt: -------------------------------------------------------------------------------- 1 | class test { 2 | private: 3 | int a; 4 | int b; 5 | float c; 6 | public: 7 | int Asia; 8 | int func1(int arg1, int arg2); 9 | float func2(float arg3, float arg4) { 10 | int array[10]; 11 | float temp = 0.456; 12 | if (temp != 4) { 13 | int super = 2; 14 | super = super * 7; 15 | return c; 16 | } 17 | } 18 | }; 19 | 20 | int test::func1(int arg1, int arg2) { 21 | int param = 10; 22 | for (param; param == 10; param + 1) { 23 | if (param == 10) { 24 | float var1 = 3.1415; 25 | } 26 | do { 27 | int star = 5; 28 | } while(var1 > 2.3); 29 | } 30 | return param; 31 | } 32 | 33 | int main() { 34 | test t1; 35 | int intnum = 99; 36 | float floatnum = 2.45; 37 | while (intnum <= 100) { 38 | test t2; 39 | int skku[999]; 40 | t2.c = 2.3333; 41 | intnum = t1.func1(2,4); 42 | floatnum = t1.func2(WEIMING, YANG); 43 | } 44 | return 0; 45 | } -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | all: 2 | flex compiler.l 3 | bison -d compiler.y 4 | gcc -o compiler compiler.tab.c traverseTree.c lex.yy.c -g -lfl 5 | 6 | clean: 7 | rm -rf lex.yy.c compiler.tab.c compiler.tab.h compiler ASTtree.txt symbolTable.txt -------------------------------------------------------------------------------- /traverseTree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "traverseTree.h" 4 | 5 | /* FILE pointers used to write the AST and symboltable into file */ 6 | extern FILE *fp1; 7 | extern FILE *fp2; 8 | 9 | //global variable for making symbol table 10 | int row_num; 11 | Type_e currentType; // used for distinguish the int and float and class type 12 | bool isParameter = false; //determine whether it is a parameter or a variable. 13 | bool printDeclaration = false; // print the variables and parameters in the symbol table 14 | bool printScopePathAndTitle = false; // print the location and title of the symbol table 15 | bool AnotherCompoundStmt = false; 16 | bool isCompoundStmt = false; 17 | 18 | //make scope, from bottom to top because the feature of bison, stack the nodes up 19 | struct Scope* createNewScope(SCOPETYPE type, struct Scope* parent) { 20 | struct Scope* scope = (struct Scope*)malloc(sizeof(struct Scope)); 21 | scope->type = type; 22 | scope->do_num = 0; 23 | scope->while_num = 0; 24 | scope->for_num = 0; 25 | scope->if_num = 0; 26 | scope->compound_num = 0; 27 | 28 | /* add the new scope to the end of the linked list */ 29 | if(parent != NULL) { 30 | scope->parent = parent; 31 | parent->child = scope; 32 | } else { 33 | scope->parent = NULL; 34 | } 35 | 36 | scope->child = NULL; 37 | return scope; 38 | } 39 | 40 | /* delete the last scope of the linked list */ 41 | void deleteScope(struct Scope** endScope) { 42 | struct Scope* currentScope = *endScope; 43 | struct Scope* parent = currentScope->parent; 44 | 45 | if(parent != NULL) { 46 | parent->child = NULL; 47 | (*endScope) = parent; 48 | free(currentScope); 49 | } 50 | } 51 | 52 | //returns the order of current node scope 53 | int getScopeNum(SCOPETYPE type, struct Scope* scope) { 54 | switch(type) { 55 | case DO_scope: 56 | return (scope->do_num); 57 | 58 | case WHILE_scope: 59 | return (scope->while_num); 60 | 61 | case FOR_scope: 62 | return (scope->for_num); 63 | 64 | case IF_scope: 65 | return (scope->if_num); 66 | 67 | case COMPOUND_scope: 68 | return (scope->compound_num); 69 | 70 | } 71 | } 72 | 73 | // print the symbol table to the tree.txt file according the node path 74 | void printScopePath() { 75 | //when printing global variable 76 | if(endScope->type == CLASS_scope) { 77 | fprintf(fp2, "Location: %s\n", currentClassName); 78 | return; //print nothing at "location" 79 | } 80 | else { 81 | fprintf(fp2, "\nLocation : "); 82 | 83 | fprintf(fp2, "%s", currentFuncName); 84 | 85 | struct Scope* curScope = startScope->child; //start from Function node 86 | while(curScope->child != NULL) { 87 | fprintf(fp2, " - "); 88 | switch(curScope->child->type) { 89 | case DO_scope: 90 | fprintf(fp2, "DO"); 91 | break; 92 | 93 | case WHILE_scope: 94 | fprintf(fp2, "WHILE"); 95 | break; 96 | 97 | case FOR_scope: 98 | fprintf(fp2, "FOR"); 99 | break; 100 | 101 | case IF_scope: 102 | fprintf(fp2, "IF"); 103 | break; 104 | 105 | case COMPOUND_scope: 106 | fprintf(fp2, "COMPOUND"); 107 | break; 108 | } 109 | fprintf(fp2, "(%d) ", getScopeNum(curScope->child->type, curScope)); 110 | curScope = curScope->child; 111 | } 112 | fprintf(fp2, "\n"); 113 | } 114 | } 115 | 116 | //print symboltable, called before entering visitDeclaration 117 | void printEachColumnTitle() { 118 | /* count the variable or parameter from number 1 */ 119 | row_num = 1; 120 | /* print the path of the current scope */ 121 | printScopePath(); 122 | /* print the title of each column in a neat way */ 123 | fprintf( fp2, "%10s%10s%10s%10s%10s\n", "Count","Type","Name","Array","Role"); 124 | } 125 | 126 | 127 | 128 | 129 | void visitProgram(struct Program* program) { 130 | if (program->_class != NULL) { 131 | visitClass(program->_class); 132 | fprintf(fp1, "\n"); 133 | } 134 | if (program->classMethodDef != NULL) { 135 | visitClassMethod(program->classMethodDef); 136 | fprintf(fp1, "\n"); 137 | } 138 | visitmainFunc(program->mainFunc); 139 | fprintf(fp1, "\n"); 140 | } 141 | 142 | void visitClass(struct Class* _class) { 143 | /* recursion to visit all the class */ 144 | if(_class->prev != NULL) { 145 | visitClass(_class->prev); 146 | } 147 | 148 | fprintf(fp1, "class %s {\n", _class->id); 149 | /* get the class name */ 150 | currentClassName = _class->id; 151 | 152 | if(_class->priMember != NULL) { 153 | fprintf(fp1, "private:\n"); 154 | visitMember(_class->priMember); 155 | } 156 | if(_class->pubMember != NULL) { 157 | fprintf(fp1, "public:\n"); 158 | visitMember(_class->pubMember); 159 | } 160 | fprintf(fp1, "};\n"); 161 | } 162 | 163 | void visitMember(struct Member* member) { 164 | if (member->varDecl != NULL) visitVarDecl(member->varDecl); 165 | if (member->methodDecl != NULL) visitMethodDecl(member->methodDecl); 166 | if (member->methodDef != NULL) visitMethodDef(member->methodDef); 167 | } 168 | 169 | void visitVarDecl(struct VarDecl* decl) { 170 | isParameter = false; 171 | 172 | if (decl->prev != NULL) { 173 | visitVarDecl(decl->prev); 174 | } 175 | 176 | visitType(decl->type); 177 | 178 | if (!printScopePathAndTitle) { 179 | printEachColumnTitle(); 180 | printScopePathAndTitle = true; 181 | } 182 | 183 | printDeclaration = true; 184 | visitIdent(decl->ident); 185 | printDeclaration = false; 186 | 187 | if (decl->assignType != eNon) { 188 | fprintf(fp1, "="); 189 | if (decl->assignType == eAsInt) fprintf(fp1, "%d;\n", decl->assigner.intnum); 190 | if (decl->assignType == eAsFloat) fprintf(fp1, "%f;\n", decl->assigner.floatnum); 191 | } else { 192 | fprintf(fp1, ";\n"); 193 | } 194 | } 195 | 196 | void visitMethodDecl(struct MethodDecl* decl) { 197 | if (decl->prev != NULL) { 198 | visitMethodDecl(decl->prev); 199 | } 200 | 201 | visitType(decl->type); 202 | fprintf(fp1, "%s(", decl->id); 203 | if (decl->param != NULL) { 204 | visitParam(decl->param); 205 | } 206 | fprintf(fp1, ");\n"); 207 | } 208 | 209 | void visitMethodDef(struct MethodDef* decl) { 210 | if (decl->prev != NULL) { 211 | visitMethodDef(decl->prev); 212 | } 213 | 214 | currentFuncName = decl->id; 215 | endScope = createNewScope(FUNC_scope, endScope); 216 | 217 | visitType(decl->type); 218 | fprintf(fp1, "%s(", decl->id); 219 | 220 | printScopePathAndTitle = false; 221 | 222 | if (decl->param != NULL) { 223 | printEachColumnTitle(); 224 | printScopePathAndTitle = true; 225 | visitParam(decl->param); 226 | } 227 | fprintf(fp1, ")"); 228 | visitCompoundStmt(decl->compoundStmt); 229 | 230 | deleteScope(&endScope); 231 | printScopePathAndTitle = false; 232 | } 233 | 234 | void visitClassMethod(struct ClassMethodDef* def) { 235 | if (def->prev != NULL) { 236 | visitClassMethod(def->prev); 237 | } 238 | 239 | currentFuncName = def->methodName; 240 | endScope = createNewScope(FUNC_scope, endScope); 241 | 242 | visitType(def->type); 243 | fprintf(fp1, "%s::%s(", def->className, def->methodName); 244 | 245 | printScopePathAndTitle = false; 246 | 247 | if (def->param != NULL) { 248 | printEachColumnTitle(); 249 | printScopePathAndTitle = true; 250 | visitParam(def->param); 251 | } 252 | fprintf(fp1, ")"); 253 | visitCompoundStmt(def->compoundStmt); 254 | 255 | deleteScope(&endScope); 256 | printScopePathAndTitle = false; 257 | } 258 | 259 | void visitmainFunc(struct MainFunc* mainfunc) { 260 | fprintf(fp1, "int main()"); 261 | 262 | currentFuncName = "mainFunc"; 263 | deleteScope(&endScope); 264 | endScope = createNewScope(FUNC_scope, endScope); 265 | 266 | printScopePathAndTitle = false; 267 | printEachColumnTitle(); 268 | printScopePathAndTitle = true; 269 | 270 | visitCompoundStmt(mainfunc->compoundStmt); 271 | 272 | deleteScope(&endScope); 273 | printScopePathAndTitle = false; 274 | } 275 | 276 | void visitParam(struct Param* param) { 277 | isParameter = true; 278 | 279 | if (param->prev != NULL) { 280 | visitParam(param->prev); 281 | fprintf(fp1, ","); 282 | } 283 | 284 | if (!printScopePathAndTitle) { 285 | printEachColumnTitle(); 286 | printScopePathAndTitle = true; 287 | } 288 | 289 | visitType(param->type); 290 | printDeclaration = true; 291 | visitIdent(param->ident); 292 | printDeclaration = false; 293 | } 294 | 295 | void visitIdent(struct Ident* ident) { 296 | if (ident->len == 0) { 297 | fprintf(fp1, "%s", ident->id); 298 | 299 | if (printDeclaration == true) { 300 | char* t; 301 | if (currentType == eInt) { 302 | t = "int"; 303 | } else if(currentType == eFloat) { 304 | t = "float"; 305 | } else { 306 | t = "class"; 307 | } 308 | fprintf(fp2, "%10d%10s%10s%10s%10s\n", row_num++ , t, ident->id, "", isParameter ? "parameter" : "variable"); 309 | } 310 | } else { 311 | fprintf(fp1, "%s[%d]", ident->id, ident->len); 312 | 313 | if (printDeclaration == true) { 314 | char* t; 315 | if (currentType == eInt) { 316 | t = "int"; 317 | } else if(currentType == eFloat) { 318 | t = "float"; 319 | } else { 320 | t = "class"; 321 | } 322 | fprintf(fp2, "%10d%10s%10s%10d%10s\n", row_num++ , t, ident->id, ident->len, isParameter ? "parameter" : "variable"); 323 | } 324 | } 325 | } 326 | 327 | void visitType(struct Type* type) { 328 | if (type->e == eInt) { 329 | fprintf(fp1, "int "); 330 | currentType = eInt; 331 | } 332 | if (type->e == eFloat) { 333 | fprintf(fp1, "float "); 334 | currentType = eFloat; 335 | } 336 | if (type->e == eClass) { 337 | fprintf(fp1, "%s ", type->id); 338 | currentType = eClass; 339 | } 340 | } 341 | 342 | void visitCompoundStmt(struct CompoundStmt* comp) { 343 | if (isCompoundStmt == true) { 344 | endScope = createNewScope(COMPOUND_scope, endScope); 345 | printScopePathAndTitle = false; 346 | endScope->parent->compound_num++; 347 | } 348 | 349 | AnotherCompoundStmt = false; 350 | 351 | fprintf(fp1, "{\n"); 352 | if (comp->varDecl != NULL) visitVarDecl(comp->varDecl); 353 | if (comp->stmt != NULL) visitStmt(comp->stmt); 354 | fprintf(fp1, "}\n"); 355 | 356 | if (isCompoundStmt == true) { 357 | deleteScope(&endScope); 358 | } 359 | isCompoundStmt = false; 360 | AnotherCompoundStmt =false; 361 | } 362 | 363 | void visitStmt(struct Stmt* stmt) { 364 | if (stmt->prev != NULL) { 365 | visitStmt(stmt->prev); 366 | } 367 | 368 | switch(stmt->e) { 369 | case eExpr: 370 | visitExprStmt(stmt->type.exprStmt); 371 | break; 372 | 373 | case eAssign: 374 | visitAssignStmt(stmt->type.assignStmt); 375 | break; 376 | 377 | case eRet: 378 | visitReturnStmt(stmt->type.retStmt); 379 | break; 380 | 381 | case eWhile: 382 | AnotherCompoundStmt = true; 383 | visitWhileStmt(stmt->type.whileStmt); 384 | break; 385 | 386 | case eDo: 387 | AnotherCompoundStmt = true; 388 | visitDoStmt(stmt->type.doStmt); 389 | break; 390 | 391 | case eFor: 392 | AnotherCompoundStmt = true; 393 | visitForStmt(stmt->type.forStmt); 394 | break; 395 | 396 | case eIf: 397 | AnotherCompoundStmt = true; 398 | visitIfStmt(stmt->type.ifStmt); 399 | break; 400 | 401 | case eCompound: 402 | if (AnotherCompoundStmt == false) isCompoundStmt = true; 403 | visitCompoundStmt(stmt->type.compoundStmt); 404 | break; 405 | 406 | case eSemi: 407 | fprintf(fp1, ";"); 408 | break; 409 | } 410 | //fprintf(fp1, "\n"); 411 | } 412 | 413 | void visitExprStmt(struct ExprStmt* exprstmt) { 414 | visitExpr(exprstmt->expr); 415 | fprintf(fp1, ";\n"); 416 | } 417 | 418 | void visitAssignStmt(struct AssignStmt* assign) { 419 | visitRefVarExpr(assign->refVarExpr); 420 | fprintf(fp1, "="); 421 | visitExpr(assign->expr); 422 | fprintf(fp1, ";\n"); 423 | } 424 | 425 | void visitReturnStmt(struct RetStmt* retstmt) { 426 | fprintf(fp1, "return"); 427 | if (retstmt->expr != NULL) { 428 | fprintf(fp1, " "); 429 | visitExpr(retstmt->expr); 430 | } 431 | fprintf(fp1, ";\n"); 432 | } 433 | 434 | void visitWhileStmt(struct WhileStmt* whilestmt) { 435 | endScope = createNewScope(WHILE_scope, endScope); 436 | printScopePathAndTitle = false; 437 | endScope->parent->while_num++; 438 | 439 | fprintf(fp1, "while("); 440 | visitExpr(whilestmt->cond); 441 | fprintf(fp1, ")\n"); 442 | visitStmt(whilestmt->body); 443 | 444 | deleteScope(&endScope); 445 | } 446 | 447 | void visitDoStmt(struct DoStmt* dostmt) { 448 | endScope = createNewScope(DO_scope, endScope); 449 | printScopePathAndTitle = false; 450 | endScope->parent->do_num++; 451 | 452 | fprintf(fp1, "do\n"); 453 | visitStmt(dostmt->body); 454 | fprintf(fp1, "while ("); 455 | visitExpr(dostmt->cond); 456 | fprintf(fp1, ");\n"); 457 | 458 | deleteScope(&endScope); 459 | } 460 | 461 | void visitForStmt(struct ForStmt* forstmt) { 462 | endScope = createNewScope(FOR_scope, endScope); 463 | printScopePathAndTitle = false; 464 | endScope->parent->for_num++; 465 | 466 | fprintf(fp1, "for("); 467 | visitExpr(forstmt->init); 468 | fprintf(fp1, "; "); 469 | visitExpr(forstmt->cond); 470 | fprintf(fp1, "; "); 471 | visitExpr(forstmt->incr); 472 | fprintf(fp1, ")\n"); 473 | visitStmt(forstmt->body); 474 | 475 | deleteScope(&endScope); 476 | } 477 | 478 | void visitIfStmt(struct IfStmt* ifstmt) { 479 | endScope = createNewScope(IF_scope, endScope); 480 | printScopePathAndTitle = false; 481 | endScope->parent->if_num++; 482 | 483 | fprintf(fp1, "if ("); 484 | visitExpr(ifstmt->cond); 485 | fprintf(fp1, ")\n"); 486 | visitStmt(ifstmt->ifBody); 487 | if (ifstmt->elseBody != NULL) { 488 | fprintf(fp1, "\nelse\n"); 489 | visitStmt(ifstmt->elseBody); 490 | } 491 | 492 | deleteScope(&endScope); 493 | } 494 | 495 | void visitExpr(struct Expr* expr) { 496 | switch(expr->e) { 497 | case eOper: 498 | visitOperExpr(expr->type.operExpr); 499 | break; 500 | 501 | case eRef: 502 | visitRefExpr(expr->type.refExpr); 503 | break; 504 | 505 | case eIntnum: 506 | fprintf(fp1, "%d", expr->type.intnum); 507 | break; 508 | 509 | case eFloatnum: 510 | fprintf(fp1, "%f", expr->type.floatnum); 511 | break; 512 | 513 | } 514 | } 515 | 516 | void visitOperExpr(struct OperExpr* operexpr) { 517 | switch(operexpr->e) { 518 | case eUn: 519 | fprintf(fp1, "-"); 520 | visitExpr(operexpr->type.un->expr); 521 | break; 522 | 523 | case eAddi: 524 | visitExpr(operexpr->type.addi->lhs); 525 | if (operexpr->type.addi->e == ePlus) { 526 | fprintf(fp1, "+"); 527 | } else { 528 | fprintf(fp1, "-"); 529 | } 530 | visitExpr(operexpr->type.addi->rhs); 531 | break; 532 | 533 | case eMult: 534 | visitExpr(operexpr->type.mult->lhs); 535 | if (operexpr->type.mult->e == eMul) { 536 | fprintf(fp1, "*"); 537 | } else { 538 | fprintf(fp1, "/"); 539 | } 540 | visitExpr(operexpr->type.mult->rhs); 541 | break; 542 | 543 | case eRela: 544 | visitExpr(operexpr->type.rela->lhs); 545 | switch(operexpr->type.rela->e) { 546 | case eGT: 547 | fprintf(fp1, ">"); 548 | break; 549 | 550 | case eLT: 551 | fprintf(fp1, "<"); 552 | break; 553 | 554 | case eLE: 555 | fprintf(fp1, "<="); 556 | break; 557 | 558 | case eGE: 559 | fprintf(fp1, ">="); 560 | break; 561 | 562 | } 563 | visitExpr(operexpr->type.rela->rhs); 564 | break; 565 | 566 | case eEqlt: 567 | visitExpr(operexpr->type.eqlt->lhs); 568 | if (operexpr->type.eqlt->e == eEQ) { 569 | fprintf(fp1, "=="); 570 | } else { 571 | fprintf(fp1, "!="); 572 | } 573 | visitExpr(operexpr->type.eqlt->rhs); 574 | break; 575 | 576 | case eBracket: 577 | fprintf(fp1, "("); 578 | visitExpr(operexpr->type.bracket); 579 | fprintf(fp1, ")"); 580 | break; 581 | 582 | } 583 | } 584 | 585 | void visitRefExpr(struct RefExpr* ref) { 586 | if (ref->e == eVar) { 587 | visitRefVarExpr(ref->type.refVarExpr); 588 | } else if (ref->e == eCall) { 589 | visitRefCallExpr(ref->type.refCallExpr); 590 | } 591 | } 592 | 593 | void visitRefVarExpr(struct RefVarExpr* ref) { 594 | if (ref->refExpr != NULL) { 595 | visitRefExpr(ref->refExpr); 596 | fprintf(fp1, "."); 597 | } 598 | visitIdentExpr(ref->identExpr); 599 | } 600 | 601 | void visitRefCallExpr(struct RefCallExpr* ref) { 602 | if (ref->refExpr != NULL) { 603 | visitRefExpr(ref->refExpr); 604 | fprintf(fp1, "."); 605 | } 606 | visitCallExpr(ref->callExpr); 607 | } 608 | 609 | void visitIdentExpr(struct IdentExpr* identexpr) { 610 | fprintf(fp1, "%s", identexpr->id); 611 | if (identexpr->expr != NULL) { 612 | fprintf(fp1, "["); 613 | visitExpr(identexpr->expr); 614 | fprintf(fp1, "]"); 615 | } 616 | } 617 | 618 | void visitCallExpr(struct CallExpr* callexpr) { 619 | fprintf(fp1, "%s(", callexpr->id); 620 | if (callexpr->arg != NULL) { 621 | visitArg(callexpr->arg); 622 | } 623 | fprintf(fp1, ")"); 624 | } 625 | 626 | void visitArg(struct Arg* arg) { 627 | if (arg->prev != NULL) { 628 | visitArg(arg->prev); 629 | fprintf(fp1, ","); 630 | } 631 | 632 | visitExpr(arg->expr); 633 | } 634 | -------------------------------------------------------------------------------- /traverseTree.h: -------------------------------------------------------------------------------- 1 | #include "AST.h" 2 | 3 | /* There are 8 statements which contain { } brackets. Each pair of bracket can express a scope */ 4 | typedef enum { CLASS_scope, FUNC_scope, DO_scope, WHILE_scope, FOR_scope, IF_scope, COMPOUND_scope } SCOPETYPE; 5 | 6 | /* start scope and end scope used for make the linked list */ 7 | struct Scope *startScope, *endScope; 8 | /* store the class name and function name to make a symbol table*/ 9 | char* currentClassName; 10 | char* currentFuncName; 11 | 12 | /* count down the number of statements in each scope */ 13 | struct Scope { 14 | /* type */ 15 | SCOPETYPE type; 16 | /* number of the scope type */ 17 | int do_num; 18 | int while_num; 19 | int for_num; 20 | int if_num; 21 | int compound_num; 22 | /* parent and children */ 23 | struct Scope* parent; 24 | struct Scope* child; 25 | }; 26 | 27 | struct Scope* createNewScope(SCOPETYPE type, struct Scope* parent); 28 | 29 | void deleteScope(struct Scope** endScope); 30 | 31 | int getScopeNum(SCOPETYPE type, struct Scope* parent); 32 | 33 | 34 | /* avoid some warning from the terminal */ 35 | int yylex(); 36 | int yyparse(); 37 | 38 | void visitProgram(struct Program* program); 39 | 40 | void visitClass(struct Class* _class); 41 | 42 | void visitMember(struct Member* member); 43 | 44 | void visitVarDecl(struct VarDecl* decl); 45 | 46 | void visitMethodDecl(struct MethodDecl* decl); 47 | 48 | void visitMethodDef(struct MethodDef* decl); 49 | 50 | void visitClassMethod(struct ClassMethodDef* def); 51 | 52 | void visitmainFunc(struct MainFunc* mainfunc); 53 | 54 | void visitParam(struct Param* param); 55 | 56 | void visitIdent(struct Ident* ident); 57 | 58 | void visitType(struct Type* type); 59 | 60 | void visitCompoundStmt(struct CompoundStmt* comp); 61 | 62 | void visitStmt(struct Stmt* stmt); 63 | 64 | void visitExprStmt(struct ExprStmt* exprstmt); 65 | 66 | void visitAssignStmt(struct AssignStmt* assign); 67 | 68 | void visitReturnStmt(struct RetStmt* retstmt); 69 | 70 | void visitWhileStmt(struct WhileStmt* whilestmt); 71 | 72 | void visitDoStmt(struct DoStmt* dostmt); 73 | 74 | void visitForStmt(struct ForStmt* forstmt); 75 | 76 | void visitIfStmt(struct IfStmt* ifstmt); 77 | 78 | void visitExpr(struct Expr* expr); 79 | 80 | void visitOperExpr(struct OperExpr* operexpr); 81 | 82 | void visitRefExpr(struct RefExpr* ref); 83 | 84 | void visitRefVarExpr(struct RefVarExpr* ref); 85 | 86 | void visitRefCallExpr(struct RefCallExpr* ref); 87 | 88 | void visitIdentExpr(struct IdentExpr* identexpr); 89 | 90 | void visitCallExpr(struct CallExpr* callexpr); 91 | 92 | void visitArg(struct Arg* arg); 93 | --------------------------------------------------------------------------------