/****************************************************/ /* File: util.c */ /* Utility function implementation */ /* for the TINY compiler */ /* Compiler Construction: Principles and Practice */ /* Kenneth C. Louden */ /****************************************************/ #include "util.h" #include "globals.h" /* Procedure printToken prints a token * and its lexeme to the listing file */ void printToken(TokenType token, const char *tokenString) { switch (token) { case IF: case ELSE: case WHILE: case RETURN: case INT: case VOID: fprintf(listing, "reserved word: %s\n", tokenString); break; case ASSIGN: fprintf(listing, "=\n"); break; case EQ: fprintf(listing, "==\n"); break; case NE: fprintf(listing, "!=\n"); break; case LT: fprintf(listing, "<\n"); break; case LE: fprintf(listing, "<=\n"); break; case GT: fprintf(listing, ">\n"); break; case GE: fprintf(listing, ">=\n"); break; case PLUS: fprintf(listing, "+\n"); break; case MINUS: fprintf(listing, "-\n"); break; case TIMES: fprintf(listing, "*\n"); break; case OVER: fprintf(listing, "/\n"); break; case LPAREN: fprintf(listing, "(\n"); break; case RPAREN: fprintf(listing, ")\n"); break; case LBRACE: fprintf(listing, "[\n"); break; case RBRACE: fprintf(listing, "]\n"); break; case LCURLY: fprintf(listing, "{\n"); break; case RCURLY: fprintf(listing, "}\n"); break; case SEMI: fprintf(listing, ";\n"); break; case COMMA: fprintf(listing, ",\n"); break; case ENDFILE: fprintf(listing, "EOF\n"); break; case NUM: fprintf(listing, "NUM, val= %s\n", tokenString); break; case ID: fprintf(listing, "ID, name= %s\n", tokenString); break; case ERROR: fprintf(listing, "ERROR: %s\n", tokenString); break; default: /* should never happen */ fprintf(listing, "Unknown token: %d\n", token); } } /* Function newStmtNode creates a new statement * node for syntax tree construction */ TreeNode *newStmtNode(StmtKind kind) { TreeNode *t = (TreeNode *) malloc(sizeof(TreeNode)); int i; if (t == NULL) fprintf(listing, "Out of memory error at line %d\n", lineno); else { for (i = 0; i < MAXCHILDREN; i++) t->child[i] = NULL; t->sibling = NULL; t->nodekind = StmtK; t->kind.stmt = kind; t->lineno = lineno; } return t; } /* Function newExpNode creates a new expression * node for syntax tree construction */ TreeNode *newExpNode(ExpKind kind) { TreeNode *t = (TreeNode *) malloc(sizeof(TreeNode)); int i; if (t == NULL) fprintf(listing, "Out of memory error at line %d\n", lineno); else { for (i = 0; i < MAXCHILDREN; i++) t->child[i] = NULL; t->sibling = NULL; t->nodekind = ExpK; t->kind.exp = kind; t->lineno = lineno; t->type = Void; } return t; } /* Function copyString allocates and makes a new * copy of an existing string */ char *copyString(char *s) { int n; char *t; if (s == NULL) return NULL; n = strlen(s) + 1; t = malloc(n); if (t == NULL) fprintf(listing, "Out of memory error at line %d\n", lineno); else strcpy(t, s); return t; } /* Variable indentno is used by printTree to * store current number of spaces to indent */ static int indentno = 0; /* macros to increase/decrease indentation */ #define INDENT indentno += 2 #define UNINDENT indentno -= 2 /* printSpaces indents by printing spaces */ static void printSpaces(void) { int i; for (i = 0; i < indentno; i++) fprintf(listing, " "); } /* procedure printTree prints a syntax tree to the * listing file using indentation to indicate subtrees */ void printTree(TreeNode *tree) { int i; INDENT; while (tree != NULL) { printSpaces(); if (tree->nodekind == StmtK) { switch (tree->kind.stmt) { case IfK: fprintf(listing, "If\n"); break; case RepeatK: fprintf(listing, "Repeat\n"); break; case AssignK: fprintf(listing, "Assign to: %s\n", tree->attr.name); break; case ReadK: fprintf(listing, "Read: %s\n", tree->attr.name); break; case WriteK: fprintf(listing, "Write\n"); break; default: fprintf(listing, "Unknown ExpNode kind\n"); break; } } else if (tree->nodekind == ExpK) { switch (tree->kind.exp) { case OpK: fprintf(listing, "Op: "); printToken(tree->attr.op, "\0"); break; case ConstK: fprintf(listing, "Const: %d\n", tree->attr.val); break; case IdK: fprintf(listing, "Id: %s\n", tree->attr.name); break; default: fprintf(listing, "Unknown ExpNode kind\n"); break; } } else fprintf(listing, "Unknown node kind\n"); for (i = 0; i < MAXCHILDREN; i++) printTree(tree->child[i]); tree = tree->sibling; } UNINDENT; }