C - Compiler Front End

Compiler Front End - C


This is the front end of a compiler including the buffer, scanner and parser written in C. The compiler is for a uniquely defined language of my own design, with specified grammar and semantics, including comments, expressions, keywords, etc.

The compiler and language was built using the professors example and a significant portion of the code was provided. The language supports the minimal features expected in a programming language, including block comments, keywords, datatypes such as integer and floating-point numbers, and text strings. It also had commands for assignment, selection, interaction, input, and output operations, as well as modules for subroutines and functions. The language was modeled using regular expressions (RE), transition diagrams (TD), and transition tables (TT), which were important components of the front-end compiler. The focus for creating the buffer was on developing functions that were highly protected against runtime errors, ensuring that invalid parameters, internal calculations, or memory violations would not cause abrupt termination or crashes. The scanner was implemented and utilized dynamic definition, regular expressions, and finite deterministic automata (FDA). The scanner played a crucial role in the front-end compiler, utilizing the buffer and models previously defined. The code relied on the buffer, scanner, and tokenizer functions, and various procedures corresponding to non-terminals defined in the grammar.

The Language is named “Faiyum”, and files written in Faiyum utilize a “.fy” file extension. An example of what a program may look like is shown below:

function main {

      Float PI

      Float r

      Float Vol

      PI is 3.14

      r is input

      Vol is 4.0 / 3.0 * PI * (r * r * r)

      output Vol

}

A video demonstrating the output and the code is shown below:


Alternate Link

A Sample of the Source Code is below, view the full codebase on GitHub

Buffer
Scanner
Parser
Exported from Notepad++
1 /************************************************************ 2 * File name : MainBuffer.c 3 * Compiler : MS Visual Studio 2019, Debug Win32 4 * Author : Paulo Sousa, Mostapha Abdelaziz 5 * Professor: Paulo Sousa 6 * Purpose: This file is the main code for Buffer (A1) 7 * Function list: mainBuffer, bErrorPrint, displayBuffer, getFileSize, isNumber, startBuffer 8 *************************************************************/ 9 10 /* 11 * The #define _CRT_SECURE_NO_WARNINGS should be used in MS Visual Studio projects 12 * to suppress the warnings about using "unsafe" functions like fopen() 13 * and standard sting library functions defined in string.h. 14 * The define directive does not have any effect on other compiler projects (gcc, Borland). 15 */ 16 17 #define _CRT_SECURE_NO_WARNINGS 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <stdarg.h> 23 #include <ctype.h> 24 25 #ifndef COMPILERS_H_ 26 #include "Compilers.h" 27 #endif 28 29 #ifndef BUFFER_H_ 30 #include "Buffer.h" 31 #endif 32 33 /* Check for ANSI C compliancy */ 34 #define ANSI_C 0 35 #if defined(__STDC__) 36 #undef ANSI_C 37 #define ANSI_C 1 38 #endif 39 40 /* 41 * ------------------------------------------------------------- 42 * Function declarations 43 * ------------------------------------------------------------- 44 */ 45 void bErrorPrint(char* fmt, ...); 46 void displayBuffer(Buffer* ptr_Buffer); 47 long getFileSize(char* fname); 48 int isNumber(const char* ns); 49 void startBuffer(char*, char*, char, short, int); 50 51 /************************************************************* 52 * Main function from Buffer 53 * Parameters: 54 * argc / argv = Parameters from command prompt 55 * Return value: 56 * Success operation. 57 *************************************************************/ 58 59 int mainBuffer(int argc, char** argv) { 60 61 int isAnsiC = !ANSI_C; /* ANSI C flag */ 62 short size = 0, increment = 0, wrongNumber = 0; 63 64 /* Check if the compiler option is set to compile ANSI C */ 65 /* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/ 66 if (isAnsiC) { 67 bErrorPrint("Date: %s Time: %s", __DATE__, __TIME__); 68 bErrorPrint("ERROR: Compiler is not ANSI C compliant!\n"); 69 exit(EXIT_FAILURE); 70 } 71 72 /* missing file name or/and mode parameter */ 73 if (argc <= 2) { 74 bErrorPrint("\nDate: %s Time: %s", __DATE__, __TIME__); 75 bErrorPrint("\nRuntime error at line %d in file %s\n", __LINE__, __FILE__); 76 bErrorPrint("%s\b\b\b\b%s%s", argv[0], ": ", "Missing parameters."); 77 bErrorPrint("Usage: <Option=0> <SourceFile> [<Mode>]"); 78 exit(EXIT_FAILURE); 79 } 80 81 /* create source input buffer */ 82 char* program = argv[0]; 83 char* input = argv[2]; 84 char mode = MODE_FIXED; 85 86 if (argc == 4) { 87 mode = *argv[3]; 88 switch (mode) { 89 case MODE_FIXED: case MODE_ADDIT: case MODE_MULTI: break; 90 default: 91 bErrorPrint("%s%s%c%s%c%s%c%s", program, ": Wrong mode - choose: ", 92 MODE_FIXED, ", ", MODE_ADDIT, ", ", MODE_MULTI, "."); 93 exit(EXIT_FAILURE); 94 } 95 } 96 /* read additional parameters, if any */ 97 if (argc == 6) { 98 mode = *argv[3]; 99 if (isNumber(argv[4]))size = (short)atoi(argv[4]); else wrongNumber = 1; 100 if (isNumber(argv[5]))increment = (short)atoi(argv[5]); else wrongNumber = 1; 101 if (wrongNumber) { 102 bErrorPrint("\nDate: %s Time: %s", __DATE__, __TIME__); 103 bErrorPrint("\nRuntime error at line %d in file %s\n", __LINE__, __FILE__); 104 bErrorPrint("%s\b\b\b\b%s", argv[0], ": Missing or wrong number parameters."); 105 bErrorPrint("Usage: <Option=0> <SourceFile> [<Mode> <Size> <Increment>]"); 106 exit(EXIT_FAILURE); 107 } 108 } 109 110 startBuffer(program, input, mode, size, increment); 111 112 /*return success */ 113 return (EXIT_SUCCESS); 114 } 115 116 /************************************************************* 117 * Buffer starting method 118 * Params: 119 * - Program: Name of the program 120 * - Input: Filename 121 * - Mode: Operational mode 122 * - Size: Buffer capacity 123 * - Increment: buffer increment. 124 *************************************************************/ 125 void startBuffer(char* program, char* input, char mode, short size, int increment) { 126 127 BufferPointer bufferp; /* pointer to Buffer structure */ 128 FILE* fileHandler; /* input file handle */ 129 int loadSize = 0; /*the size of the file loaded in the buffer */ 130 char symbol; /*symbol read from input file */ 131 132 /* create buffer */ 133 bufferp = create(size, (char)increment, mode); 134 135 if (bufferp == NULL) { 136 bErrorPrint("%s%s", program, 137 ": Cannot allocate buffer - Use: buffer <input> <mode> <size> <increment>."); 138 bErrorPrint("Filename: %s %c %d %d\n", input, mode, size, increment); 139 exit(1); 140 } 141 142 /* open source file */ 143 if ((fileHandler = fopen(input, "r")) == NULL) { 144 bErrorPrint("%s%s%s", program, ": Cannot open file: ", input); 145 exit(1); 146 } 147 148 /* load source file into input buffer */ 149 printf("Reading file %s ....Please wait\n", input); 150 loadSize = load(bufferp, fileHandler); 151 152 /* if the input file has not been completely loaded, find the file size and print the last symbol loaded */ 153 if (loadSize == BUFFER_ERROR) { 154 printf("The input file %s %s\n", input, "has not been completely loaded."); 155 printf("Current size of buffer: %d.\n", getSize(bufferp)); 156 symbol = (char)fgetc(fileHandler); 157 printf("Last character read from the input file is: %c %d\n", symbol, symbol); 158 printf("Input file size: %ld\n", getFileSize(input)); 159 } 160 161 /* close source file */ 162 fclose(fileHandler); 163 164 /* 165 * Finishes the buffer: add end of file character (EOF) to the buffer 166 * display again 167 */ 168 if ((loadSize != BUFFER_ERROR) && (loadSize != 0)) { 169 if (!addChar(bufferp, BUFFER_EOF)) { 170 bErrorPrint("%s%s%s", program, ": ", "Error in compacting buffer."); 171 } 172 } 173 displayBuffer(bufferp); 174 175 /* free the dynamic memory used by the buffer */ 176 destroy(bufferp); 177 bufferp = NULL; 178 } 179 180 /************************************************************* 181 * Error printing function with variable number of arguments 182 * Params: Variable arguments, using formats from C language. 183 * - Internal vars use list of arguments and types from stdarg.h 184 * - NOTE: The format is using signature from C Language 185 *************************************************************/ 186 187 void bErrorPrint(char* fmt, ...) { 188 189 /* Initialize variable list */ 190 va_list ap; 191 va_start(ap, fmt); 192 193 (void)vfprintf(stderr, fmt, ap); 194 va_end(ap); 195 196 /* Move to new line */ 197 if (strchr(fmt, '\n') == NULL) 198 fprintf(stderr, "\n"); 199 } 200 201 /************************************************************* 202 * Print function 203 * - Params: buffer to print all properties. 204 *************************************************************/ 205 206 void displayBuffer(Buffer* ptr_Buffer) { 207 208 printf("\nPrinting buffer parameters:\n\n"); 209 printf("The capacity of the buffer is: %d\n", 210 getSize(ptr_Buffer)); 211 printf("The current size of the buffer is: %d\n", 212 getWritePos(ptr_Buffer)); 213 printf("The operational mode of the buffer is: %c\n", 214 getMode(ptr_Buffer)); 215 printf("The increment factor of the buffer is: %lu\n", 216 getIncrement(ptr_Buffer)); 217 printf("The first symbol in the buffer is: %c\n", 218 getWritePos(ptr_Buffer) ? *getContent(ptr_Buffer, 0) : ' '); 219 printf("The value of the flags field is: %02hX\n", 220 getFlags(ptr_Buffer)); 221 printf("\nPrinting buffer contents:\n\n"); 222 recover(ptr_Buffer); 223 if (!print(ptr_Buffer)) 224 printf("Empty buffer\n"); 225 226 } 227 228 /************************************************************* 229 * Get buffer size 230 * Params: 231 * - Filename: Name of the file 232 *************************************************************/ 233 234 long getFileSize(char* fname) { 235 FILE* input; 236 long flength; 237 input = fopen(fname, "r"); 238 if (input == NULL) { 239 bErrorPrint("%s%s", "Cannot open file: ", fname); 240 return 0; 241 } 242 fseek(input, 0L, SEEK_END); 243 flength = ftell(input); 244 fclose(input); 245 return flength; 246 } 247 248 /************************************************************* 249 * Tests for decimal-digit character string 250 * Params: 251 * - String to be evaluated as numeric 252 * Return: 253 * - Number value: Returns nonzero (true) if ns is a number; 0 (False) otherwise 254 *************************************************************/ 255 256 int isNumber(const char* ns) { 257 char c; int i = 0; 258 if (ns == NULL) return 0; 259 while ((c = ns[i++]) == 0) { 260 if (!isdigit(c)) return 0; 261 } 262 return 1; 263 } 264
Exported from Notepad++
1 /************************************************************* 2 * File name: MainScanner.c 3 * Compiler: MS Visual Studio 2019 4 * Author: Svillen Ranev - Paulo Sousa, Mostapha Abdelaziz 5 * Professor: Paulo Sousa 6 * Purpose: This file is the main code for Scanner (A2) 7 *************************************************************/ 8 9 /* The #define _CRT_SECURE_NO_WARNINGS should be used in MS Visual Studio projects 10 * to suppress the warnings about using "unsafe" functions like fopen() 11 * and standard sting library functions defined in string.h. 12 * The define does not have any effect in other compiler projects. 13 */ 14 #define _CRT_SECURE_NO_WARNINGS 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <stdarg.h> 20 21 #ifndef COMPILERS_H_ 22 #include "Compilers.h" 23 #endif 24 25 #ifndef BUFFER_H_ 26 #include "Buffer.h" 27 #endif 28 29 #ifndef SCANNER_H_ 30 #include "Scanner.h" 31 #endif 32 33 /*check for ANSI C compliancy */ 34 #define ANSI_C 0 35 #if defined(__STDC__) 36 #undef ANSI_C 37 #define ANSI_C 0 38 #endif 39 40 /* 41 * ------------------------------------------------------------- 42 * Global vars and External vars 43 * ------------------------------------------------------------- 44 */ 45 46 /* Global objects - variables (used in other codes as external) */ 47 BufferPointer stringLiteralTable; /* this buffer implements String Literal Table */ 48 int errorNumber; /* run-time error number = 0 by default (ANSI) */ 49 50 /* External objects */ 51 extern int line; /* source code line numbers - defined in scanner.c */ 52 extern short startScanner(Buffer* sc_buf); 53 extern Token tokenizer(void); 54 55 /* 56 * ------------------------------------------------------------- 57 * Function declarations 58 * ------------------------------------------------------------- 59 */ 60 void printScannerError(char* fmt, ...); 61 void displayScanner(Buffer* ptrBuffer); 62 long getScannerFilesize(char* fname); 63 void printToken(Token t); 64 65 /************************************************************* 66 * Scanner Main function 67 * Parameters: 68 * argc / argv = Parameters from command prompt 69 * Return value: 70 * Success operation. 71 ************************************************************/ 72 73 int mainScanner(int argc, char** argv) { 74 75 BufferPointer sourceBuffer; /* pointer to input (source) buffer */ 76 FILE* fileHandler; /* input file handle */ 77 Token currentToken; /* token produced by the scanner */ 78 int loadSize = 0; /* the size of the file loaded in the buffer */ 79 int isAnsiC = ANSI_C; /* ANSI C compliancy flag */ 80 81 /* Check if the compiler option is set to compile ANSI C */ 82 /* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/ 83 if (isAnsiC) { 84 printScannerError("Date: %s Time: %s", __DATE__, __TIME__); 85 printScannerError("ERROR: Compiler is not ANSI C compliant!\n"); 86 exit(EXIT_FAILURE); 87 } 88 89 /*check for correct arrguments - source file name */ 90 if (argc <= 2) { 91 /* __DATE__, __TIME__, __LINE__, __FILE__ are predefined preprocessor macros*/ 92 printScannerError("Date: %s Time: %s", __DATE__, __TIME__); 93 printScannerError("Runtime error at line %d in file %s", __LINE__, __FILE__); 94 printScannerError("%s%s", argv[0], ": Missing source file name."); 95 printScannerError("%s", "Usage: <Option=1> <SourceFile>"); 96 exit(EXIT_FAILURE); 97 } 98 99 /* Shows debug mode */ 100 printf("%s%d%s", "[Debug mode: ", DEBUG, "]\n"); 101 102 /* create a source code input buffer - multiplicative mode */ 103 sourceBuffer = create(BUFFER_DEFAULT_SIZE, BUFFER_DEFAULT_INCREMENT, MODE_MULTI); 104 if (sourceBuffer == NULL) { 105 printScannerError("%s%s", argv[1], ": Could not create source buffer"); 106 exit(EXIT_FAILURE); 107 } 108 109 /* open source file */ 110 if ((fileHandler = fopen(argv[2], "r")) == NULL) { 111 printScannerError("%s%s%s", argv[0], ": Cannot open file: ", argv[2]); 112 exit(EXIT_FAILURE); 113 } 114 115 /* load source file into input buffer */ 116 printf("Reading file %s ....Please wait\n", argv[2]); 117 loadSize = load(sourceBuffer, fileHandler); 118 if (loadSize == BUFFER_ERROR) 119 printScannerError("%s%s", argv[0], ": Error in loading buffer."); 120 121 /* close source file */ 122 fclose(fileHandler); 123 /* find the size of the file */ 124 if (loadSize == BUFFER_ERROR) { 125 printf("The input file %s %s\n", argv[2], "is not completely loaded."); 126 printf("Input file size: %ld\n", getScannerFilesize(argv[2])); 127 } 128 129 /* compact and display the source buffer */ 130 /* add SEOF to input program buffer*/ 131 if ((loadSize != BUFFER_ERROR) && (loadSize != 0)) { 132 if (addChar(sourceBuffer, BUFFER_EOF)) { 133 displayScanner(sourceBuffer); 134 } 135 } 136 137 /* create string Literal Table */ 138 stringLiteralTable = create(BUFFER_DEFAULT_SIZE, BUFFER_DEFAULT_INCREMENT, MODE_ADDIT); 139 if (stringLiteralTable == NULL) { 140 printScannerError("%s%s", argv[0], ": Could not create string literals buffer"); 141 exit(EXIT_FAILURE); 142 } 143 144 /* Testbed for the scanner */ 145 /* add SEOF to input program buffer*/ 146 /* Initialize scanner input buffer */ 147 if (startScanner(sourceBuffer)) { 148 printScannerError("%s%s", argv[0], ": Empty program buffer - scanning canceled"); 149 exit(EXIT_FAILURE); 150 } 151 152 printf("\nScanning source file...\n\n"); 153 printf("Token\t\tAttribute\n"); 154 printf("----------------------------------\n"); 155 do { 156 currentToken = tokenizer(); 157 printToken(currentToken); 158 } while (currentToken.code != SEOF_T); 159 160 /* print String Literal Table if not empty */ 161 printf("\nPrinting string table...\n"); 162 printf("----------------------------------\n"); 163 if (getWritePos(stringLiteralTable)) print(stringLiteralTable); 164 printf("\n----------------------------------\n"); 165 destroy(sourceBuffer); 166 destroy(stringLiteralTable); 167 sourceBuffer = stringLiteralTable = NULL; 168 169 /* Ass2 evaluation only */ 170 if (argv[3] != NULL && *argv[3] == 'l') 171 printf("The number of lines is: %d\n", line); 172 173 return (EXIT_SUCCESS); 174 } 175 176 /************************************************************* 177 * Error printing function with variable number of arguments 178 * Params: Variable arguments, using formats from C language. 179 * - Internal vars use list of arguments and types from stdarg.h 180 * - NOTE: The format is using signature from C Language 181 ************************************************************/ 182 183 void printScannerError(char* fmt, ...) { 184 va_list ap; 185 va_start(ap, fmt); 186 (void)vfprintf(stderr, fmt, ap); 187 va_end(ap); 188 /* Move to new line */ 189 if (strchr(fmt, '\n') == NULL) 190 fprintf(stderr, "\n"); 191 } 192 193 /************************************************************* 194 * The function displays buffer contents 195 * Param: 196 * - Scanner to be displayed. 197 ************************************************************/ 198 199 void displayScanner(Buffer* ptrBuffer) { 200 printf("\nPrinting buffer parameters:\n\n"); 201 printf("The capacity of the buffer is: %d\n", getSize(ptrBuffer)); 202 printf("The current size of the buffer is: %d\n", getWritePos(ptrBuffer)); 203 printf("\nPrinting buffer contents:\n\n"); 204 recover(ptrBuffer); 205 print(ptrBuffer); 206 207 } 208 209 /************************************************************* 210 * The function gets size of scanner file 211 * Param: 212 * - Filename 213 * Return: 214 * - Size of the file 215 ************************************************************/ 216 217 long getScannerFilesize(char* fname) { 218 FILE* fileInput; 219 long fileLength; 220 fileInput = fopen(fname, "r"); 221 if (fileInput == NULL) { 222 printScannerError("%s%s", "Cannot open file: ", fname); 223 return 0L; 224 } 225 fseek(fileInput, 0L, SEEK_END); 226 fileLength = ftell(fileInput); 227 fclose(fileInput); 228 return fileLength; 229 } 230
Exported from Notepad++
1 /************************************************************* 2 * File name: MainParser.c 3 * Compiler: MS Visual Studio 2019\ 4 * Author: Svillen Ranev - Paulo Sousa, Mostapha Abdelaziz 5 * Professor: Paulo Sousa 6 * Purpose: This file is the main code for Parser (A3) 7 *************************************************************/ 8 9 /************************************************************* 10 * IMPORTANT NOTE: 11 * The #define _CRT_SECURE_NO_WARNINGS should be used in MS Visual Studio projects 12 * to suppress the warnings about using "unsafe" functions like fopen() 13 * and standard sting library functions defined in string.h. 14 * The define does not have any effect in other compilers projects. 15 **********************************************************/ 16 17 #define _CRT_SECURE_NO_WARNINGS 18 19 #include <stdio.h> 20 #include <stdlib.h> /* Constants for calls to exit()*/ 21 22 #include <string.h> 23 #include <stdarg.h> 24 25 #ifndef COMPILERS_H_ 26 #include "Compilers.h" 27 #endif 28 29 #ifndef BUFFER_H_ 30 #include "Buffer.h" 31 #endif 32 33 #ifndef SCANNER_H_ 34 #include "Scanner.h" 35 #endif 36 37 /* Check for ANSI C compliancy */ 38 #define ANSI_C 0 39 #if defined(__STDC__) 40 #undef ANSI_C 41 #define ANSI_C 1 42 #endif 43 44 45 /* 46 * ------------------------------------------------------------- 47 * Global vars and External vars 48 * ------------------------------------------------------------- 49 */ 50 51 /* Global objects - variables */ 52 static BufferPointer sourceBuffer; /* pointer to input (source) buffer */ 53 BufferPointer stringLiteralTable; /* This buffer is used as a repository for string literals */ 54 int errorNumber; /* Run-time error number = 0 by default (ANSI) */ 55 56 /* External objects */ 57 extern int syntaxErrorNumber /* number of syntax errors reported by the parser */; 58 extern int line; /* source code line number - defined in scanner.c */ 59 60 /* 61 * ------------------------------------------------------------- 62 * Function declarations 63 * ------------------------------------------------------------- 64 */ 65 66 /* Function declarations (prototypes) */ 67 extern void startParser(void); 68 extern short startScanner(BufferPointer sc_buf); 69 70 static void printParserError(char* fmt, ...); 71 static void displayParser(BufferPointer ptrBuffer); 72 static long getParserFileSize(char* fname); 73 static void callGarbageCollector(void); 74 75 76 /************************************************************* 77 * Parser Main function 78 * Parameters: 79 * - argc / argv = Parameters from command prompt 80 * Return value: 81 * - Success operation. 82 ************************************************************/ 83 84 int mainParser(int argc, char** argv) { 85 86 FILE* fi; /* input file handle */ 87 int loadsize = 0; /*the size of the file loaded in the buffer */ 88 int ansi_c = !ANSI_C; /* ANSI C flag */ 89 /* Check if the compiler option is set to compile ANSI C */ 90 /* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/ 91 if (ansi_c) { 92 printParserError("Date: %s Time: %s", __DATE__, __TIME__); 93 printParserError("ERROR: Compiler is not ANSI C compliant!\n"); 94 exit(EXIT_FAILURE); 95 } 96 97 /*check for correct arrguments - source file name */ 98 if (argc <= 1) { 99 /* __DATE__, __TIME__, __LINE__, __FILE__ are predefined preprocessor macros*/ 100 printParserError("Date: %s Time: %s", __DATE__, __TIME__); 101 printParserError("Runtime error at line %d in file %s", __LINE__, __FILE__); 102 printParserError("%s%s%s", argv[0], ": ", "Missing source file name."); 103 printParserError("%s%s%s", "Usage: ", "parser", " source_file_name"); 104 exit(EXIT_FAILURE); 105 } 106 107 /* create a source code input buffer - multiplicative mode */ 108 sourceBuffer = create(BUFFER_DEFAULT_SIZE, BUFFER_DEFAULT_INCREMENT, MODE_MULTI); 109 if (sourceBuffer == NULL) { 110 printParserError("%s%s%s", argv[0], ": ", "Could not create source buffer"); 111 exit(EXIT_FAILURE); 112 } 113 114 /*open source file */ 115 if ((fi = fopen(argv[2], "r")) == NULL) { 116 printParserError("%s%s%s%s", argv[0], ": ", "Cannot open file: ", argv[2]); 117 exit(EXIT_FAILURE); 118 } 119 120 /* load source file into input buffer */ 121 printf("Reading file %s ....Please wait\n", argv[2]); 122 loadsize = load(sourceBuffer, fi); 123 if (loadsize == BUFFER_ERROR) 124 printParserError("%s%s%s", argv[0], ": ", "Error in loading buffer."); 125 126 /* close source file */ 127 fclose(fi); 128 /*find the size of the file */ 129 if (loadsize == BUFFER_ERROR) { 130 printf("The input file %s %s\n", argv[2], "is not completely loaded."); 131 printf("Input file size: %ld\n", getParserFileSize(argv[2])); 132 } 133 /* Add SEOF (EOF) to input buffer and display the source buffer */ 134 if ((loadsize != BUFFER_ERROR) && (loadsize != 0)) { 135 if (addChar(sourceBuffer, BUFFER_EOF)) { 136 displayParser(sourceBuffer); 137 } 138 } 139 /* create string Literal Table */ 140 stringLiteralTable = create(BUFFER_DEFAULT_SIZE, BUFFER_DEFAULT_INCREMENT, MODE_ADDIT); 141 if (stringLiteralTable == NULL) { 142 printParserError("%s%s%s", argv[0], ": ", "Could not create string literal buffer"); 143 exit(EXIT_FAILURE); 144 } 145 146 /* Registrer exit function */ 147 atexit(callGarbageCollector); 148 149 /* Initialize scanner */ 150 startScanner(sourceBuffer); 151 152 /* Start parsing */ 153 printf("\nParsing the source file...\n\n"); 154 155 startParser(); 156 157 return (EXIT_SUCCESS); /* same effect as exit(0) */ 158 159 } 160 161 /************************************************************* 162 * Error printing function with variable number of arguments 163 * Params: Variable arguments, using formats from C language. 164 * - Internal vars use list of arguments and types from stdarg.h 165 * - NOTE: The format is using signature from C Language 166 *************************************************************/ 167 168 void printParserError(char* fmt, ...) { 169 170 va_list ap; 171 va_start(ap, fmt); 172 173 (void)vfprintf(stderr, fmt, ap); 174 va_end(ap); 175 176 /* Move to new line */ 177 if (strchr(fmt, '\n') == NULL) 178 fprintf(stderr, "\n"); 179 } 180 181 /************************************************************* 182 * The function return the size of an open file 183 * Param: 184 * - Filename 185 * Return: 186 * - Size of the file 187 *************************************************************/ 188 189 long getParserFileSize(char* fname) { 190 FILE* input; 191 long flength; 192 input = fopen(fname, "r"); 193 if (input == NULL) { 194 printParserError("%s%s", "Cannot open file: ", fname); 195 return 0; 196 } 197 fseek(input, 0L, SEEK_END); 198 flength = ftell(input); 199 fclose(input); 200 return flength; 201 } 202 203 /************************************************************* 204 * The function display buffer contents 205 * Param: 206 * - Parser to be displayed. 207 *************************************************************/ 208 209 void displayParser(Buffer* ptrBuffer) { 210 printf("\nPrinting input buffer parameters:\n\n"); 211 printf("The capacity of the buffer is: %d\n", getSize(ptrBuffer)); 212 printf("The current size of the buffer is: %d\n", getWritePos(ptrBuffer)); 213 printf("\nPrinting input buffer contents:\n\n"); 214 recover(ptrBuffer); 215 print(ptrBuffer); 216 } 217 218 /************************************************************* 219 * The function frees all dynamically allocated memory. 220 * This function is always called despite how the program terminates - normally or abnormally. 221 *************************************************************/ 222 223 void callGarbageCollector(void) { 224 if (syntaxErrorNumber) 225 printf("\nSyntax errors: %d\n", syntaxErrorNumber); 226 printf("\nCollecting garbage...\n"); 227 destroy(sourceBuffer); 228 destroy(stringLiteralTable); 229 } 230