From aeb36f9540a96e64a660e83f9e38f85b64cb5f18 Mon Sep 17 00:00:00 2001 From: venko Date: Thu, 6 May 2021 17:16:10 -0700 Subject: [PATCH] Adds type for validating identifiers --- CMakeLists.txt | 4 +- src/identcheck.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++ src/identcheck.h | 36 +++++++++++++ 3 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 src/identcheck.c create mode 100644 src/identcheck.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 56d5ca6..a3cbf9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(LLVM) include_directories(${CMAKE_SOURCE_DIR}) -BISON_TARGET(Parser generators/wraith.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c COMPILE_FLAGS "-d -v -t -Wcounterexamples") +BISON_TARGET(Parser generators/wraith.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c COMPILE_FLAGS "-d -v -t") FLEX_TARGET(Scanner generators/wraith.lex ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c) ADD_FLEX_BISON_DEPENDENCY(Scanner Parser) @@ -41,9 +41,11 @@ add_executable( # Source src/ast.h src/codegen.h + src/identcheck.h src/parser.h src/ast.c src/codegen.c + src/identcheck.c src/parser.c src/main.c # Generated code diff --git a/src/identcheck.c b/src/identcheck.c new file mode 100644 index 0000000..66b964e --- /dev/null +++ b/src/identcheck.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include + +#include "ast.h" +#include "identcheck.h" + +IdNode* MakeIdNode(NodeType type, char *name) { + IdNode *node = (IdNode*)malloc(sizeof(IdNode)); + node->type = type; + node->name = strdup(name); + node->childCount = 0; + node->childCapacity = 0; + node->children = NULL; + return node; +} + +void AddChildToNode(IdNode *node, IdNode *child) { + if (child == NULL) return; + + if (node->children == NULL) { + node->childCapacity = 2; + node->children = (IdNode**)malloc(sizeof(IdNode*) * node->childCapacity); + } else if (node->childCount == node->childCapacity) { + node->childCapacity *= 2; + node->children = realloc(node->children, sizeof(IdNode*) * node->childCapacity); + } + + node->children[node->childCount] = child; + node->childCount += 1; +} + +IdNode* FindId(IdNode *root, NodeType targetType, char *targetName) { + IdNode *result = NULL; + IdNode **frontier = (IdNode**)malloc(sizeof(IdNode*)); + frontier[0] = root; + uint32_t frontierCount = 1; + + while (frontierCount > 0) { + IdNode *current = frontier[0]; + + if (current->type == targetType && strcmp(current->name, targetName)) { + result = current; + break; + } + + IdNode **temp = + (IdNode**)malloc(sizeof(IdNode*) * (frontierCount - 1 + current->childCount)); + uint32_t i; + for (i = 1; i < frontierCount; i++) { + temp[i - 1] = frontier[i]; + } + uint32_t offset = i; + for (i = 0; i < current->childCount; i++) { + temp[offset + i] = current->children[i]; + } + frontier = temp; + frontierCount += current->childCount - 1; + } + + free(frontier); + return result; +} + +IdNode* MakeIdTree(Node *astNode) { + switch (astNode->syntaxKind) { + case Declaration: + return MakeIdNode(Variable, astNode->children[1]->value.string); + + case DeclarationSequence: { + IdNode *declSeqNode = MakeIdNode(LexicalScope, ""); + uint32_t i; + for (i = 0; i < astNode->childCount; i++) { + AddChildToNode(declSeqNode, MakeIdTree(astNode->children[i])); + } + return declSeqNode; + } + + case StructDeclaration: { + Node *idNode = astNode->children[0]; + Node *declsNode = astNode->children[1]; + IdNode *structNode = MakeIdNode(Struct, idNode->value.string); + uint32_t i; + for (i = 0; i < declsNode->childCount; i++) { + AddChildToNode(structNode, MakeIdTree(declsNode->children[i])); + } + return structNode; + } + + case FunctionDeclaration: { + Node *sigNode = astNode->children[0]; + Node *funcNameNode = sigNode->children[0]; + Node *funcArgsNode = sigNode->children[2]; + + Node *bodyStatementsNode = astNode->children[1]; + + IdNode *funcNode = MakeIdNode(Function, funcNameNode->value.string); + uint32_t i; + for (i = 0; i < funcArgsNode->childCount; i++) { + AddChildToNode(funcNode, MakeIdTree(funcArgsNode->children[i])); + } + for (i = 0; i < bodyStatementsNode->childCount; i++) { + AddChildToNode(funcNode, MakeIdTree(bodyStatementsNode->children[i])); + } + return funcNode; + } + + default: + return NULL; + } +} + +void PrintIdTree(IdNode *tree, uint32_t tabCount) { + uint32_t i; + for (i = 0; i < tabCount; i++) { + printf("| "); + } + + switch(tree->type) { + case LexicalScope: printf("Scope\n"); break; + case Struct: printf("%s : Struct\n", tree->name); break; + case Function: printf("%s : Function\n", tree->name); break; + case Variable: printf("%s : Variable\n", tree->name); break; + } + + for (i = 0; i < tree->childCount; i++) { + PrintIdTree(tree->children[i], tabCount + 1); + } +} diff --git a/src/identcheck.h b/src/identcheck.h new file mode 100644 index 0000000..395a73c --- /dev/null +++ b/src/identcheck.h @@ -0,0 +1,36 @@ +// Validates identifier usage in an AST. +#ifndef WRAITH_IDENTCHECK_H +#define WRAITH_IDENTCHECK_H + +#include + +#include "ast.h" + +typedef enum NodeType { + LexicalScope, + Struct, + Function, + Variable +} NodeType; + +typedef struct IdNode { + NodeType type; + char *name; + struct IdNode **children; + uint32_t childCount; + uint32_t childCapacity; +} IdNode; + +typedef struct IdStatus { + enum StatusCode { + Valid, + } StatusCode; +} IdStatus; + + +IdNode* MakeIdTree(Node *astNode); +void PrintIdTree(IdNode *tree, uint32_t tabCount); + +//IdStatus CheckIds(Node *root); + +#endif /* WRAITH_IDENTCHECK_H */