diff --git a/include/arc/std/lexer.h b/include/arc/std/lexer.h index a68f65d..f7655d1 100644 --- a/include/arc/std/lexer.h +++ b/include/arc/std/lexer.h @@ -5,11 +5,55 @@ extern "C" { #endif +#include "arc/std/bool.h" +#include "arc/std/string.h" +#include + +/** + * @brief +*/ +typedef enum ARC_Lexer_BasicTokens { + LEXER_TOKEN_LAMBDA = 0, + LEXER_TOKEN_COLON = ':', + LEXER_TOKEN_SEMICOLON = ';', + LEXER_TOKEN_COMMA = ',', + LEXER_TOKEN_PERIOD = '.', + LEXER_TOKEN_FORWARD_SLASH = '/', + LEXER_TOKEN_BACK_SLASH = '\\', + LEXER_TOKEN_LEFT_PARENTHESIS = '(', + LEXER_TOKEN_RIGHT_PARENTHESIS = ')', + LEXER_TOKEN_LEFT_CURLY_BRACE = '{', + LEXER_TOKEN_RIGHT_CURLY_BRACE = '}', +} ARC_Lexer_BasicTokens; + +/** + * @brief checks to see if a string is a type of token + * + * @param[in/out] string a string to be checked to see if it matches a token, + * this needs to srip the token out for the lexer to avoid an infinite loop + * @param[out] tokenData a place to store token data (like a variable name), can be NULL if not needed + * @param[in] automataData any data that needs to be used for the ARC_Lexer_AutomataFn + * + * @return if a token was successfully found ARC_True, otherwise ARC_False +*/ +typedef ARC_Bool (* ARC_Lexer_AutomataFn)(ARC_String **string, ARC_String **tokenData, void *automataData); + /** * @brief a lexer type */ typedef struct ARC_Lexer ARC_Lexer; +/** + * @brief a lexer token type +*/ +typedef struct ARC_LexerToken { + uint32_t id; + + ARC_Lexer_AutomataFn automataFn; + void *automataData; + //TODO: automataData free callback +} ARC_LexerToken; + /** * @brief * @@ -24,6 +68,51 @@ void ARC_Lexer_Create(ARC_Lexer **lexer); */ void ARC_Lexer_Destroy(ARC_Lexer *lexer); +/** + * @brief + * + * @param [in] lexer + * @param [in] token +*/ +void ARC_Lexer_RegisterToken(ARC_Lexer *lexer, ARC_LexerToken token); + +/** + * @brief + * + * @param[in] lexer + * @param[in] path +*/ +void ARC_Lexer_LexFile(ARC_Lexer *lexer, ARC_String *path); + +/** + * @brief checks if the first character of string matches the automataData cast as a char + * + * @note this function is a ARC_Lexer_AutomataFn callback + * + * @param[in/out] string a string to be checked to see if it matches a token, + * this needs to srip the token out for the lexer to avoid an infinite loop + * @param[out] tokenData a place to store token data (like a variable name), can be NULL if not needed + * @param[in] automataData any data that needs to be used for the ARC_Lexer_AutomataFn + * + * @return if a token was successfully found ARC_True, otherwise ARC_False +*/ +ARC_Bool ARC_Lexer_AutomataMatchCharFn(ARC_String **string, ARC_String **tokenData, void *automataData); + +/** + * @brief checks if the substring automataData as an ARC_String matches the first part of string + * + * @note this function is a ARC_Lexer_AutomataFn callback + * + * @param[in/out] string a string to be checked to see if it matches a token, + * this needs to srip the token out for the lexer to avoid an infinite loop + * @param[out] tokenData a place to store token data (like a variable name), can be NULL if not needed + * @param[in] automataData any data that needs to be used for the ARC_Lexer_AutomataFn + * + * @return if a token was successfully found ARC_True, otherwise ARC_False +*/ +ARC_Bool ARC_Lexer_AutomataMatchStringFn(ARC_String **string, ARC_String **tokenData, void *automataData); + + #ifdef __cplusplus } #endif diff --git a/include/arc/std/vector.h b/include/arc/std/vector.h index 23ea203..346266a 100644 --- a/include/arc/std/vector.h +++ b/include/arc/std/vector.h @@ -23,6 +23,13 @@ typedef struct ARC_Vector ARC_Vector; */ typedef ARC_Bool (* ARC_Vector_CompareDataFn)(void *dataA, void *dataB); +/** + * @brief a callback that cleans up memory when it is removed from the vector + * + * @param[in] data the item to delete +*/ +typedef void (* ARC_Vector_DeleteDataFn)(void *data); + /** * @brief creates an ARC_Vector which is an "expandable" array * @@ -32,8 +39,9 @@ typedef ARC_Bool (* ARC_Vector_CompareDataFn)(void *dataA, void *dataB); * @param[out] vector ARC_Vector to initialize * @param[in] compareDataFn a callback that checks if data stored in the array matches, * if set to NULL and ARC_Vector_Remove is called, the pointer addresses will be compared + * @param[in] deleteDataFn a callback that frees an item on remove or clear, can be set to NULL to do nothing */ -void ARC_Vector_Create(ARC_Vector **vector, ARC_Vector_CompareDataFn *compareDataFn); +void ARC_Vector_Create(ARC_Vector **vector, ARC_Vector_CompareDataFn *compareDataFn, ARC_Vector_DeleteDataFn *deleteDataFn); /** * @brief destroys an ARC_Vector @@ -60,6 +68,7 @@ void ARC_Vector_Add(ARC_Vector *vector, void *data); * * @note this function uses the ARC_Vector_CompareDataFn that the ARC_Vector was created with * @note this function will not throw an error if there is no match + * @note this function will call ARC_Vector_RemoveIndex, so it's notes are also applicable to this function * * @param[in] vector ARC_Vector to remove from * @param[in] data matching data to remove @@ -70,6 +79,7 @@ void ARC_Vector_Remove(ARC_Vector *vector, void *data); * @brief removes an item from an ARC_Vector at an index * * @note this function will error if trying to remove an index that is outside the bounds of the ARC_Vector + * @note this function will use ARC_Vector_DeleteDataFn if it was set in the ARC_Vector_Create function * * @param[in] vector ARC_Vector to remove from * @param[in] index position of data to remove diff --git a/src/std/lexer.c b/src/std/lexer.c index e69de29..e26ced2 100644 --- a/src/std/lexer.c +++ b/src/std/lexer.c @@ -0,0 +1,73 @@ +#include "arc/std/lexer.h" + +#include "arc/std/bool.h" +#include "arc/std/string.h" +#include "arc/std/vector.h" +#include "arc/std/io.h" +#include + +struct ARC_Lexer { + ARC_Vector *tokens; +}; + +void ARC_Lexer_Create(ARC_Lexer **lexer){ + *lexer = (ARC_Lexer *)malloc(sizeof(ARC_Lexer)); + + //TODO: add compare and delete callbacks + ARC_Vector_Create(&(*lexer)->tokens, NULL, NULL); +} + +void ARC_Lexer_Destroy(ARC_Lexer *lexer){ + ARC_Vector_Destroy(lexer->tokens); + + free(lexer); +} + +void ARC_Lexer_RegisterToken(ARC_Lexer *lexer, ARC_LexerToken token){ + ARC_LexerToken *storedToken = (ARC_LexerToken *)malloc(sizeof(ARC_LexerToken)); + *storedToken = token; + ARC_Vector_Add(lexer->tokens, storedToken); +} + +void ARC_Lexer_LexFile(ARC_Lexer *lexer, ARC_String *path){ + ARC_String *data; + ARC_IO_FileToStr(path, &data); + + + if(data != NULL){ + ARC_String_Destroy(data); + } +} + +ARC_Bool ARC_Lexer_AutomataMatchCharFn(ARC_String **string, ARC_String **tokenData, void *automataData){ + *tokenData = NULL; + + if((*string)->data[0] == *(char *)automataData){ + if((*string)->length == 1){ + ARC_String_Destroy(*string); + *string = NULL; + } + + ARC_String_ReplaceWithSubstring(string, 1, (*string)->length - 1); + return ARC_True; + } + + return ARC_False; +} + +ARC_Bool ARC_Lexer_AutomataMatchStringFn(ARC_String **string, ARC_String **tokenData, void *automataData){ + *tokenData = NULL; + + ARC_String *automataDataString = (ARC_String *)automataData; + if(ARC_String_Equals(*string, automataDataString)){ + if((*string)->length == automataDataString->length){ + ARC_String_Destroy(*string); + *string = NULL; + } + + ARC_String_ReplaceWithSubstring(string, automataDataString->length, (*string)->length - automataDataString->length); + return ARC_True; + } + + return ARC_False; +} diff --git a/src/std/vector.c b/src/std/vector.c index e49c1b4..a6a206c 100644 --- a/src/std/vector.c +++ b/src/std/vector.c @@ -12,7 +12,8 @@ struct ARC_Vector { void **data; - ARC_Vector_CompareDataFn compareDataFn; + ARC_Vector_CompareDataFn compareDataFn; + ARC_Vector_DeleteDataFn *deleteDataFn; }; //this is a private function used as the default check for removing data from a given pointer @@ -24,7 +25,7 @@ ARC_Bool ARC_Vector_CompareDataDefaultFn(void *dataA, void *dataB){ return ARC_False; } -void ARC_Vector_Create(ARC_Vector **vector, ARC_Vector_CompareDataFn *compareDataFn){ +void ARC_Vector_Create(ARC_Vector **vector, ARC_Vector_CompareDataFn *compareDataFn, ARC_Vector_DeleteDataFn *deleteDataFn){ //create the vector *vector = (ARC_Vector *)malloc(sizeof(ARC_Vector)); @@ -38,9 +39,23 @@ void ARC_Vector_Create(ARC_Vector **vector, ARC_Vector_CompareDataFn *compareDat if(compareDataFn != NULL){ (*vector)->compareDataFn = *compareDataFn; } + + //set NULL as a default for deleteDataFn, then copy the delete data function callback if it exists + (*vector)->deleteDataFn = NULL; + if(deleteDataFn != NULL){ + (*vector)->deleteDataFn = (ARC_Vector_DeleteDataFn *)malloc(sizeof(ARC_Vector_DeleteDataFn)); + *((*vector)->deleteDataFn) = *deleteDataFn; + } } void ARC_Vector_Destroy(ARC_Vector *vector){ + //TODO: clear vector before destroying + + //free the delete data function if it exists + if(vector->deleteDataFn){ + free(vector->deleteDataFn); + } + //free everything stored in the vector free(vector->data); @@ -96,6 +111,11 @@ void ARC_Vector_RemoveIndex(ARC_Vector *vector, uint32_t index){ return; } + //call delete data to clean up item if delete data function exists + if(vector->deleteDataFn != NULL){ + (*(vector->deleteDataFn))(vector->data[index]); + } + //we will be using index to iterate as we will not use it again, so we can skip the first part of the for loop for(; index + 1 < vector->currentSize; index++){ //override the data from index to the end by shifting it back one