diff --git a/Makefile b/Makefile index 21ef43c..6244ce4 100644 --- a/Makefile +++ b/Makefile @@ -82,12 +82,13 @@ prepare_build: @echo [INFO] Using "${COMPILER}" as a compiler! @echo [INFO] Detected current operating system as ${DETECTED_OS} $(CHECK_COMMANDS) - @echo [INFO] Clearing old builds + @echo [INFO] Starting building logic + +clean: $(RM) build $(RM) $(TARGET) $(RM) $(TEST_TARGET) $(RM) $(BENCH_TARGET) - @echo [INFO] Starting building logic $(TARGET): $(COMPILER) $(FLAGS) $(SOURCES) src/cli/main.c -o $(TARGET) diff --git a/benchmarks/main.c b/benchmarks/main.c index 1d49f55..3985c50 100644 --- a/benchmarks/main.c +++ b/benchmarks/main.c @@ -123,7 +123,7 @@ void main(int argc, char* argv[]) { endTimer(i, 0); startTimer(); - struct LexerResult result = runLexer(buff); + struct LexerResult result = runLexer(buff, size); free(buff); @@ -136,20 +136,14 @@ void main(int argc, char* argv[]) { endTimer(i, 2); startTimer(); - struct Context ctx = parseContext(node); - char* compiled = compileV2(ctx); + fptr = fopen("output.txt", "w"); - endTimer(i, 3); - - startTimer(); - - fptr = fopen("output.txt", "w"); - fprintf(fptr, compiled); - fclose(fptr); + IR_CTX* ctx = makeContext(node); + compile(ctx, fptr); - endTimer(i, 4); + fclose(fptr); - free(compiled); + endTimer(i, 3); } printf("========= Benchmarking Results =========\n"); diff --git a/src/cli/main.c b/src/cli/main.c index 754b4ea..358187b 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "../lexer/lexer.h" @@ -16,6 +17,7 @@ #include "../parser/parser.h" #include "../compiler/compiler.h" +#include "../compiler/pe/pe.h" #include "../compiler/ir.h" #include "../utils/logging.c" @@ -23,6 +25,9 @@ // Version #define VERSION "0.1.0" +uint8_t code_section[6] = { + 0xB8, 0x4C, 0x00, 0x00, 0x00, 0xC3 +}; void showCommandEntry(char* commandName, char* description, int argumentCount, char* argumentNames[], char* argumentDescriptions[]) { printf("\n > %s\n\n %s%sDescription%s: %s\n", commandName, STYLE_BOLD, STYLE_UNDERLINE, RESET, description); @@ -108,11 +113,11 @@ int main(int argc, char* argv[]) { char* buff = malloc(size + 1); // Allocates one more byte for the \0 char. - fread(buff, 1, size, fptr); + size = fread(buff, 1, size, fptr); buff[size] = '\0'; fclose(fptr); - struct LexerResult result = runLexer(buff); + struct LexerResult result = runLexer(buff, size); struct ASTNode* root = parseNodes(result, 0, AST_ROOT); IR_CTX* ctx = makeContext(root); @@ -122,7 +127,10 @@ int main(int argc, char* argv[]) { return -1; } - compile(ctx, outputFile); + fptr = fopen(outputFile, "w"); + compile(ctx, fptr); + + //compilePE(fptr, code_section, sizeof(code_section)); break; case 'v': diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 280d288..73cb241 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -2,6 +2,7 @@ * The compiler of Quickfall. */ +#include #include #include @@ -13,6 +14,8 @@ #include "../utils/hash.h" #include "../utils/hashmap.h" +#include "./pe/pe.h" + /** * Parses the AST tree into a context. * @param tree the AST tree. @@ -26,9 +29,7 @@ IR_CTX* makeContext(AST_NODE* tree) { ctx->nodeIndex = 0; ctx->nodeMap = createHashmap(512,200); - while(tree->next != NULL) { - tree = tree->next; - + while(tree != NULL) { switch(tree->type) { case AST_VARIABLE_DECLARATION: @@ -59,10 +60,10 @@ IR_CTX* makeContext(AST_NODE* tree) { case AST_FUNCTION_DECLARATION: - hash = hashstr(tree->left->value); + hash = hashstr(tree->left->right->value); if(hashGet(ctx->nodeMap, hash) != NULL) { - printf("Function %s was already declared!\n", tree->left->value); + printf("Function %s was already declared!\n", tree->left->right->value); return NULL; } @@ -77,18 +78,20 @@ IR_CTX* makeContext(AST_NODE* tree) { node->variables[node->variableIndex] = var; node->variableIndex++; - hashPut(node->variableMap, hashstr(tree->right->value), var); + hashPut(node->variableMap, hashstr(tree->left->left->right->value), var); tree->left->left = tree->left->left->next; } + node->tree = tree->right; + ctx->nodes[ctx->nodeIndex] = node; ctx->nodeIndex++; hashPut(ctx->nodeMap, hash, node); + break; case AST_ASM_FUNCTION_DECLARATION: - hash = hashstr(tree->left->right->value); if(hashGet(ctx->nodeMap, hash) != NULL) { @@ -99,6 +102,7 @@ IR_CTX* makeContext(AST_NODE* tree) { node = createIRNode(IR_ASM_FUNCTION, tree->left->right->value); node->value = tree->value; + node->valueSize = tree->valueSize; while(tree->left->left->next != NULL) { @@ -121,6 +125,8 @@ IR_CTX* makeContext(AST_NODE* tree) { break; } + + tree = tree->next; } return ctx; @@ -131,6 +137,52 @@ IR_CTX* makeContext(AST_NODE* tree) { * @param ctx the IR context. * @param char the output file name. */ -void compile(IR_CTX* ctx, char* outputFileName) { +void compile(IR_CTX* ctx, FILE* out) { + + uint8_t* buff = malloc(sizeof(uint8_t) * 512); + int i = 0; + + int h = hashstr("main"); + + if(hashGet(ctx->nodeMap, h) == NULL) { + printf("Error: the main function wasn't defined!\n"); + return; + } + + IR_NODE* node = hashGet(ctx->nodeMap, h); + + if(node->nodeType != IR_FUNCTION) { + printf("Error: main must be a function!\n"); + return; + } + + while(node->tree != NULL) { + + if(node->tree->type == AST_FUNCTION_INVOKE) { + + int hash = hashstr(node->tree->value); + + IR_NODE* wa = hashGet(ctx->nodeMap, hash); + + if(wa == NULL) { + printf("Error: The %s function doesn't exist!\n", node->tree->value); + return; + } + + if(wa->nodeType == IR_ASM_FUNCTION) { + unsigned char b; + unsigned char* ptr = (unsigned char*) wa->value; + + for(int ii = 0; ii < wa->valueSize; ++ii) { + buff[i] = ptr[ii]; + ++i; + } + } + } + + node->tree = node->tree->next; + } + //todo: change format based on user + compilePE(out, buff, i); } diff --git a/src/compiler/compiler.h b/src/compiler/compiler.h index f0506f8..93ec267 100644 --- a/src/compiler/compiler.h +++ b/src/compiler/compiler.h @@ -19,8 +19,8 @@ IR_CTX* makeContext(AST_NODE* tree); /** * Compiles the Context tree to an executable named the provided name. * @param ctx the IR context. - * @param char the output file name. + * @param char the output file. */ -void compile(IR_CTX* ctx, char* outputFileName); +void compile(IR_CTX* ctx, FILE* outputFileName); #endif diff --git a/src/compiler/ir.h b/src/compiler/ir.h index 54cb88a..9271653 100644 --- a/src/compiler/ir.h +++ b/src/compiler/ir.h @@ -31,7 +31,8 @@ struct IRNode { char* type; // Variable Properties - char* value; + void* value; + int valueSize; // Function Properties struct IRNode** variables; @@ -49,6 +50,9 @@ struct IRContext { int nodeIndex; struct Hashmap* nodeMap; + + IR_NODE* mainFunc; + }; typedef struct IRContext IR_CTX; diff --git a/src/compiler/pe/format.h b/src/compiler/pe/format.h new file mode 100644 index 0000000..58d9257 --- /dev/null +++ b/src/compiler/pe/format.h @@ -0,0 +1,110 @@ +/** + * Quickfall PE Format Defintion. + */ + +#include "../units.h" + +#ifndef PE_FORMAT +#define PE_FORMAT + +/** + * Constants. + */ + +#define PE_HEADER_SIGNATURE 0x00004550 +#define PE_DOS_HDR_SZ 0x40 + +/** + * Structures. + */ + +#pragma pack(push, 1) + +typedef struct { + uint16_t e_magic; + uint16_t e_cblp; + uint16_t e_cp; + uint16_t e_crlc; + uint16_t e_cparhdr; + uint16_t e_minalloc; + uint16_t e_maxalloc; + uint16_t e_ss; + uint16_t e_sp; + uint16_t e_csum; + uint16_t e_ip; + uint16_t e_cs; + uint16_t e_lfarlc; + uint16_t e_ovno; + uint16_t e_res[4]; + uint16_t e_oemid; + uint16_t e_oeminfo; + uint16_t e_res2[10]; + uint32_t e_lfanew; +} PE_DOS_HEADER; + +typedef struct { + uint32_t Signature; + uint16_t Machine; + uint16_t NumberOfSections; + uint32_t TimeDateStamp; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + uint16_t SizeOfOptionalHeader; + uint16_t Characteristics; +} PE_NT_HEADERS; + +typedef struct { + uint16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + uint32_t SizeOfCode; + uint32_t SizeOfInitializedData; + uint32_t SizeOfUninitializedData; + uint32_t AddressOfEntryPoint; + uint32_t BaseOfCode; + uint64_t ImageBase; + uint32_t SectionAlignment; + uint32_t FileAlignment; + uint16_t MajorOperatingSystemVersion; + uint16_t MinorOperatingSystemVersion; + uint16_t MajorImageVersion; + uint16_t MinorImageVersion; + uint16_t MajorSubsystemVersion; + uint16_t MinorSubsystemVersion; + uint32_t Win32VersionValue; + uint32_t SizeOfImage; + uint32_t SizeOfHeaders; + uint32_t CheckSum; + uint16_t Subsystem; + uint16_t DllCharacteristics; + uint64_t SizeOfStackReserve; + uint64_t SizeOfStackCommit; + uint64_t SizeOfHeapReserve; + uint64_t SizeOfHeapCommit; + uint32_t LoaderFlags; + uint32_t NumberOfRvaAndSizes; + struct { + uint32_t VirtualAddress; + uint32_t Size; + } DataDirectory[16]; +} PE_OPTIONAL_HEADER; + +typedef struct { + uint8_t Name[8]; + union { + uint32_t PhysicalAddress; + uint32_t VirtualSize; + } Misc; + uint32_t VirtualAddress; + uint32_t SizeOfRawData; + uint32_t PointerToRawData; + uint32_t PointerToRelocations; + uint32_t PointerToLinenumbers; + uint16_t NumberOfRelocations; + uint16_t NumberOfLinenumbers; + uint32_t Characteristics; +} PE_SECTION_HEADER; + +#pragma pack(pop) + +#endif diff --git a/src/compiler/pe/pe.c b/src/compiler/pe/pe.c new file mode 100644 index 0000000..a9f3b33 --- /dev/null +++ b/src/compiler/pe/pe.c @@ -0,0 +1,71 @@ +/** + * Quickfall PE executable compiling. + */ + +#include +#include +#include + +#include "./format.h" + +/** + * Compiles into PE format. + */ +void compilePE(FILE* fptr, uint8_t program[], int programSize) { + PE_DOS_HEADER dos_header = {0}; + dos_header.e_magic = 0x5A4D; // "MZ" + dos_header.e_lfanew = sizeof(PE_DOS_HEADER); + + fwrite(&dos_header, sizeof(dos_header), 1, fptr); + + // Create NT headers + PE_NT_HEADERS nt_headers = {0}; + nt_headers.Signature = 0x00004550; // "PE\0\0" + nt_headers.Machine = 0x8664; // x64 + nt_headers.NumberOfSections = 1; + nt_headers.SizeOfOptionalHeader = sizeof(PE_OPTIONAL_HEADER); + nt_headers.Characteristics = 0x0002 | 0x0100; // Executable | 32-bit machine + + fwrite(&nt_headers, sizeof(nt_headers), 1, fptr); + + // Create Optional header + PE_OPTIONAL_HEADER optional_header = {0}; + optional_header.Magic = 0x20B; // PE32+ + optional_header.AddressOfEntryPoint = 0x1000; + optional_header.ImageBase = 0x400000; + optional_header.SectionAlignment = 0x1000; + optional_header.FileAlignment = 0x200; + optional_header.MajorOperatingSystemVersion = 5; + optional_header.MinorOperatingSystemVersion = 1; + optional_header.MajorSubsystemVersion = 5; + optional_header.MinorSubsystemVersion = 1; + optional_header.SizeOfImage = 0x2000; + optional_header.SizeOfHeaders = 0x200; + optional_header.Subsystem = 3; // Windows CUI + optional_header.SizeOfStackReserve = 0x100000; + optional_header.SizeOfStackCommit = 0x1000; + optional_header.SizeOfHeapReserve = 0x100000; + optional_header.SizeOfHeapCommit = 0x1000; + optional_header.NumberOfRvaAndSizes = 16; + + fwrite(&optional_header, sizeof(optional_header), 1, fptr); + + // Create Section header + PE_SECTION_HEADER section_header = {0}; + memcpy(section_header.Name, ".text", 5); + section_header.Misc.VirtualSize = 0x1000; + section_header.VirtualAddress = 0x1000; + section_header.SizeOfRawData = programSize; + section_header.PointerToRawData = 0x200; + section_header.Characteristics = 0x60000020; // Code | Execute | Read + + fwrite(§ion_header, sizeof(section_header), 1, fptr); + + // Write padding to align headers + uint8_t padding[256] = {0}; + fwrite(padding, 1, 0x200 - (sizeof(PE_DOS_HEADER) + sizeof(PE_NT_HEADERS) + sizeof(PE_OPTIONAL_HEADER) + sizeof(PE_SECTION_HEADER)), fptr); + + fwrite(program, 1, programSize, fptr); + + fclose(fptr); +} diff --git a/src/compiler/pe/pe.h b/src/compiler/pe/pe.h new file mode 100644 index 0000000..a94aa18 --- /dev/null +++ b/src/compiler/pe/pe.h @@ -0,0 +1,16 @@ +/** + * Quickfall PE executable compiling. + */ + +#include +#include + +#ifndef COMPILER_PE +#define COMPILER_PE + +/** + * Compiles into PE format. + */ +void compilePE(FILE* fptr, uint8_t program[], int programSize); + +#endif diff --git a/src/compiler/units.h b/src/compiler/units.h new file mode 100644 index 0000000..b6dafcf --- /dev/null +++ b/src/compiler/units.h @@ -0,0 +1,11 @@ +/** + * Quickfall Compiler common data-types. + */ + +#ifndef COMPILER_UNITS +#define COMPILER_UNITS + +typedef unsigned long DWORD; // 32 bits +typedef unsigned short WORD; // 16 bits + +#endif diff --git a/src/compiler/utils.c b/src/compiler/utils.c new file mode 100644 index 0000000..2fa9b41 --- /dev/null +++ b/src/compiler/utils.c @@ -0,0 +1,93 @@ +/** + * Utilities for the Quickfall compiler. + */ + +#include +#include +#include +#include +#include + +/** + * Writes an 8 bit number into the file. + */ +void write8(FILE *file, uint8_t value) { + + printf("Input %d for: %02x\n", value, (value >> 0) & 0xff); + + if (fputc(value, file) == EOF) { + perror("fputc"); + exit(1); + } +} + +/** + * Writes an 16 bit number into the file. + */ +void write16(FILE *file, uint16_t value) { + write8(file, (value >> 0) & 0xff); + write8(file, (value >> 8) & 0xff); +} + +/** + * Writes an 32 bit number into the file. + */ +void write32(FILE *file, uint32_t value) { + write8(file, (value >> 0) & 0xff); + write8(file, (value >> 8) & 0xff); + write8(file, (value >> 16) & 0xff); + write8(file, (value >> 24) & 0xff); + + printf("32 Input for %d: %02x %02x %02x %02x\n", (value >> 0) & 0xff, (value >> 8) & 0xff, (value >> 16) && 0xff, (value >> 24) & 0xff); +} + +/** + * Writes a string with a 8 bit padding. + */ +void writestr8(FILE *file, char *str) { + size_t len, i; + + len = strlen(str); + assert(len <= 8 && "The string must fit in 8 bytes."); + + for (i = 0; i < 8; i++) { + write8(file, i < len ? str[i] : 0); + } +} + +/** + * Writes a string with a 16 bit padding. + */ +void writestr16(FILE *file, char *str) { + size_t len, i; + + len = strlen(str); + assert(len <= 15 && "The string and terminator must fit in 16 bytes."); + + for (i = 0; i < 16; i++) { + write8(file, i < len ? str[i] : 0); + } +} + +/** + * Seeks to offset in a file. + */ +void seek(FILE *file, long offset) { + if (fseek(file, offset, SEEK_SET) == -1) { + perror("fseek"); + exit(1); + } +} + +/** + * Rounds the number to the provided alignment. + */ +uint32_t align_to(uint32_t value, uint32_t alignment) { + uint32_t remainder = value % alignment; + + if (remainder == 0) { + return value; + } + + return value + (alignment - remainder); +} diff --git a/src/compiler/utils.h b/src/compiler/utils.h new file mode 100644 index 0000000..55e8cf7 --- /dev/null +++ b/src/compiler/utils.h @@ -0,0 +1,45 @@ +/** + * Utilities for the Quickfall Compiler. + */ + +#include + +#ifndef COMPILER_UTILS_H +#define COMPILER_UTILS_H + +/** + * Writes an 8 bit number into the file. + */ +void write8(FILE* fptr, uint8_t value); + +/** + * Writes an 16 bit number into the file. + */ +void write16(FILE* fptr, uint16_t value); + +/** + * Writes a 32 bit number into the file. + */ +void write32(FILE* fptr, uint32_t value); + +/** + * Writes a string with a 8 bit padding. + */ +void writestr8(FILE* fptr, char* str); + +/** + * Writes a string with a 16 bit padding. + */ +void writestr16(FILE* fptr, char* str); + +/** + * Seeks to offset in a file. + */ +void seek(FILE* fptr, long offset); + +/** + * Rounds the number to the provided alignment. + */ +uint32_t align_to(uint32_t value, uint32_t alignment); + +#endif diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 60dc117..c61f19a 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -20,7 +20,7 @@ void pushToken(struct LexerResult* result, enum TokenType type) { result->size++; } -struct LexerResult runLexer(char* string) { +struct LexerResult runLexer(char* string, int size) { struct LexerResult result; result.size = 0; @@ -28,23 +28,36 @@ struct LexerResult runLexer(char* string) { char c; - while(c = *string++) { + for(int i = 0; i < size; ++i) { + + c = string[i]; int buffLen = 32; char* buff = malloc(buffLen); + buff[0] = '\0'; if(c == ' ' || c == '\t' || c == '\n') { continue; - } else if (isdigit(c)) { + } + else if(c == '\0') { + break; + } + else if (isdigit(c)) { int numLen = 0; - while(isdigit(c) || c == 'x') { + int foundX = 0; + while(isdigit(c) || c == 'x' || (foundX == 1 && c != '\0' && c != ' ' && c != '\n')) { buff[numLen] = c; numLen++; - c = *string++; + if(c == 'x') foundX = 1; + + ++i; + c = string[i]; } + buff[numLen] = '\0'; + pushToken(&result, NUMBER); result.tokens[result.size - 1].value = buff; @@ -55,22 +68,28 @@ struct LexerResult runLexer(char* string) { buff[strLen] = c; strLen++; - c = *string++; + ++i; + c = string[i]; } pushToken(&result, STRING); result.tokens[result.size - 1].value = buff; } else if(isalpha(c)) { + int keywordLen = 0; while(isalpha(c)) { buff[keywordLen] = c; + buff[keywordLen + 1] = '\0'; keywordLen++; - c = *string++; + ++i; + c = string[i]; } + if(keywordLen > 0) --i; + if(strcmp(buff, "func") == 0) { pushToken(&result, FUNCTION); } diff --git a/src/lexer/lexer.h b/src/lexer/lexer.h index f3a9072..68ac9ea 100644 --- a/src/lexer/lexer.h +++ b/src/lexer/lexer.h @@ -16,7 +16,7 @@ struct LexerResult { * Performs lexical analysis on an input string * Returns a LexerResult containing the tokens */ -struct LexerResult runLexer(char* input); +struct LexerResult runLexer(char* input, int size); /** * Adds a token to the LexerResult diff --git a/src/parser/ast.c b/src/parser/ast.c index 21dc281..4400d84 100644 --- a/src/parser/ast.c +++ b/src/parser/ast.c @@ -13,6 +13,7 @@ AST_NODE* createASTNode(enum ASTNodeType type) { AST_NODE* node = malloc(sizeof(AST_NODE)); + node->valueSize = 0; node->type = type; node->left = NULL; node->right = NULL; diff --git a/src/parser/ast.h b/src/parser/ast.h index 3416964..d666f0b 100644 --- a/src/parser/ast.h +++ b/src/parser/ast.h @@ -23,7 +23,11 @@ enum ASTNodeType { AST_FUNCTION_DECLARATION, AST_FUNCTION_HEADER, - + + AST_FUNCTION_INVOKE, + + AST_FUNCTION_ROOT, + AST_MATH_OPERATOR, AST_MATH_OPERATION, AST_MATH_OP_HEADER, @@ -41,6 +45,8 @@ struct ASTNode { struct ASTNode* next; enum ASTNodeType type; + + int valueSize; char* value; int endingIndex; // The index which the parsing ended diff --git a/src/parser/asts/functions.c b/src/parser/asts/functions.c index fea19dc..330b3f6 100644 --- a/src/parser/asts/functions.c +++ b/src/parser/asts/functions.c @@ -62,7 +62,10 @@ AST_NODE* parseParameters(struct LexerResult result, int index) { case PAREN_CLOSE: root->endingIndex = index; return root; + case PAREN_OPEN: + continue; default: + printf("Type: %d", t.type); return NULL; } @@ -109,6 +112,7 @@ AST_NODE* parseFunctionDeclaration(struct LexerResult result, int index) { node->left = createASTNode(AST_FUNCTION_HEADER); if(result.tokens[index].type != KEYWORD) { + printf("jd"); return NULL; } @@ -136,7 +140,9 @@ AST_NODE* parseFunctionDeclaration(struct LexerResult result, int index) { node->left->left = params; - node->right = parseNodes(result, params->endingIndex, AST_ROOT); + node->right = parseNodes(result, params->endingIndex, AST_FUNCTION_ROOT); + + node->endingIndex = node->right->endingIndex; return node; } @@ -174,15 +180,37 @@ AST_NODE* parseASMFunctionDeclaration(struct LexerResult result, int index) { break; } - if(t.type != STRING) { + if(t.type != NUMBER) { return NULL; } buff[buffIndex] = strtol(t.value, NULL, 16); + buffIndex++; } node->endingIndex = index; - node->value = (char*) buff; + + buff = realloc(buff, sizeof(uint8_t) * buffIndex); + + node->valueSize = buffIndex; + node->value = buff; + + return node; +} + +AST_NODE* parseFunctionInvoke(struct LexerResult result, int index) { + AST_NODE* node = createASTNode(AST_FUNCTION_INVOKE); + + node->value = result.tokens[index].value; + + AST_NODE* args = parseArguments(result, index + 2); + + node->endingIndex = index; + + if(args != NULL) { + node->right = args; + node->endingIndex = args->endingIndex; + } return node; } diff --git a/src/parser/asts/functions.h b/src/parser/asts/functions.h index 025f43e..5cc03da 100644 --- a/src/parser/asts/functions.h +++ b/src/parser/asts/functions.h @@ -37,4 +37,6 @@ AST_NODE* parseFunctionDeclaration(struct LexerResult result, int index); */ AST_NODE* parseASMFunctionDeclaration(struct LexerResult result, int index); +AST_NODE* parseFunctionInvoke(struct LexerResult result, int index); + #endif diff --git a/src/parser/parser.c b/src/parser/parser.c index bd250e7..169e1d8 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -27,8 +27,14 @@ AST_NODE* parseNodes(struct LexerResult result, int index, enum ASTNodeType type AST_NODE* node = NULL; switch(t.type) { + case BRACKETS_CLOSE: + if(type == AST_FUNCTION_ROOT) { + root->endingIndex = index; + return root; + } + break; case FUNCTION: - node = parseFunctionDeclaration(result, index); + node = parseFunctionDeclaration(result, index + 1); if(node != NULL) { current->next = node; current = node; @@ -53,6 +59,16 @@ AST_NODE* parseNodes(struct LexerResult result, int index, enum ASTNodeType type index = node->endingIndex; } break; + case KEYWORD: + if(result.tokens[index + 1].type == PAREN_OPEN) { + node = parseFunctionInvoke(result, index); + + if(node != NULL) { + current->next = node; + current = node; + index = node->endingIndex; + } + } } } diff --git a/src/utils/hashmap.c b/src/utils/hashmap.c index a6cfb1c..fd2f351 100644 --- a/src/utils/hashmap.c +++ b/src/utils/hashmap.c @@ -2,6 +2,7 @@ * A simple hashmap implementation. */ +#include #include #include "./hashmap.h"