diff --git a/CMakeLists.txt b/CMakeLists.txt index 2768a14..819e9de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,8 @@ set(ARCHEUS_STD_SOURCES src/std/io.c src/std/lexer.c src/std/parser.c + src/std/parser/csv.c + src/std/parser/helpers.c src/std/parser/parserlang.c src/std/queue.c src/std/stack.c @@ -131,6 +133,8 @@ if(ARCHEUS_STD_TESTS) #tests/std/vector.c #tests/std/lexer.c tests/std/parser.c + tests/std/parser/csv.c + tests/std/parser/parserlang.c ${ARCHEUS_STD_SOURCES} ) diff --git a/include/arc/std/lexer.h b/include/arc/std/lexer.h index 5c4b154..2525cf3 100644 --- a/include/arc/std/lexer.h +++ b/include/arc/std/lexer.h @@ -245,11 +245,11 @@ ARC_LexerTokenRule ARC_LexerTokenRule_CreateAndReturnMatchCharInStringRule(uint3 /** * @brief basic tokens */ -#define ARC_LEXER_TOKEN_NULL 0 -#define ARC_LEXER_TOKEN_NUMBER 1 -#define ARC_LEXER_TOKEN_ALPHALOWERCHAR 2 -#define ARC_LEXER_TOKEN_ALPHAUPPERCHAR 3 -#define ARC_LEXER_TOKEN_WHITESPACE 4 +#define ARC_LEXER_TOKEN_NULL 0 +#define ARC_LEXER_TOKEN_NUMBER 1 +#define ARC_LEXER_TOKEN_ALPHA_LOWER_CHAR 2 +#define ARC_LEXER_TOKEN_ALPHA_UPPER_CHAR 3 +#define ARC_LEXER_TOKEN_WHITESPACE 4 /** * @brief basic token type ids, chars, and tags diff --git a/include/arc/std/parser.h b/include/arc/std/parser.h index 5eedb17..d6ba98d 100644 --- a/include/arc/std/parser.h +++ b/include/arc/std/parser.h @@ -25,7 +25,7 @@ typedef struct ARC_ParserTag { uint32_t tokensOrTagsSize; } ARC_ParserTag; -/* +/** * @brief a parser type used inside of the parser data create function * * @note there are no public creation and destruction functions for this type as it is only ment to be used within the creation callback diff --git a/include/arc/std/parser/csv.h b/include/arc/std/parser/csv.h index 3a5f136..757fd1c 100644 --- a/include/arc/std/parser/csv.h +++ b/include/arc/std/parser/csv.h @@ -5,28 +5,54 @@ extern "C" { #endif +#include "arc/std/bool.h" #include "arc/std/parser.h" +#include "arc/std/string.h" +#include /* - -> NEWLINE | | NEWLINE | LAMBDA - -> WHITESPACE ARROW WHITESPACE - - -> WHITESPACE OR WHITESPACE | - -> WHITESPACE | - -> | - - -> ALPHA_UPPER_CHAR - -> | LAMBDA - -> ALPHA_UPPER_CHAR | UNDERSCORE - - -> LESS_THAN GREATER_THAN - -> | UNDERSCORE - -> | LAMBDA - -> | NUMBER | UNDERSCORE - -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR + -> NEWLINE | | NEWLINE | LAMBDA + -> COMMA | + -> COMMON_CHAR | COMON_CHAR */ -/* +/** + * @brief a callback for the csv parser to use to cast that data the stored data + * + * @note this callback will only be called on non-header data + * + * @param[in/out] data the csv data casted into the users type + * @param[in] string an value of the csv as a string +*/ +typedef uint32_t (* ARC_ParserCSV_CastTypeFn)(void **data, ARC_String *string); + +/** + * @brief a callback for the csv parser to use to free csv data + * + * @note this callback will only be called on non-header data + * + * @param[in] data the csv data to free +*/ +typedef uint32_t (* ARC_ParserCSV_DestroyTypeFn)(void *data); + +/** + * @brief defines a csv data type, data is set by the callback passed in when createing a parserCSV as parser + * + * @note this data can be retieved after parsing by calling get data, check arc/std/parser.h for more information + * @note destroyTypeFn is stored here (for clearing as userdata is not passed in then) but should not be used by anything but the parser +*/ +typedef struct ARC_ParserCSVData { + ARC_Bool hasHeader; + ARC_String **headers; + + uint32_t width; + uint32_t height; + void **data; + + ARC_ParserCSV_DestroyTypeFn destroyTypeFn; +} ARC_ParserCSVData; + +/** * @brief creates a parser for the Parser Lang * * @note the rules will be inited for the parser lang @@ -34,42 +60,7 @@ extern "C" { * * @param[out] parser the parser to create */ -void ARC_ParserCSV_CreateAsParser(ARC_Parser **parser, ARC_Parser_GetStringIdFn getStringIdFn); - -#define ARC_PARSERLANG_TOKEN_NULL 0 -#define ARC_PARSERLANG_TOKEN_NUMBER 1 -#define ARC_PARSERLANG_TOKEN_ALPHA_LOWER_CHAR 2 -#define ARC_PARSERLANG_TOKEN_ALPHA_UPPER_CHAR 3 -#define ARC_PARSERLANG_TOKEN_WHITESPACE 4 - -#define ARC_PARSERLANG_TOKEN_NEWLINE_ID 5 -#define ARC_PARSERLANG_TOKEN_NEWLINE_CHAR '\n' -#define ARC_PARSERLANG_TOKEN_LESS_THAN_ID 6 -#define ARC_PARSERLANG_TOKEN_LESS_THAN_CHAR '<' -#define ARC_PARSERLANG_TOKEN_GREATER_THAN_ID 7 -#define ARC_PARSERLANG_TOKEN_GREATER_THAN_CHAR '>' -#define ARC_PARSERLANG_TOKEN_OR_ID 8 -#define ARC_PARSERLANG_TOKEN_OR_CHAR '|' -#define ARC_PARSERLANG_TOKEN_UNDERSCORE_ID 9 -#define ARC_PARSERLANG_TOKEN_UNDERSCORE_CHAR '_' - -#define ARC_PARSERLANG_TOKEN_ARROW_ID 10 -#define ARC_PARSERLANG_TOKEN_ARROW_CSTRING "->" - -#define ARC_PARSERLANG_LAMBDA ARC_PARSER_TAG_LAMBDA -#define ARC_PARSERLANG_LINE 11 -#define ARC_PARSERLANG_BODY 12 -#define ARC_PARSERLANG_ARGUMENTS 13 -#define ARC_PARSERLANG_ARGUMENT 14 -#define ARC_PARSERLANG_TAG_OR_CONSTANT 15 -#define ARC_PARSERLANG_CONSTANT 16 -#define ARC_PARSERLANG_CONSTANT_BODY 17 -#define ARC_PARSERLANG_CONSTANT_CHAR 18 -#define ARC_PARSERLANG_TAG 19 -#define ARC_PARSERLANG_VARIABLE 20 -#define ARC_PARSERLANG_VARIABLE_BODY 21 -#define ARC_PARSERLANG_VARIABLE_CHAR 22 -#define ARC_PARSERLANG_ALPHA_CHAR 23 +void ARC_ParserCSV_CreateAsParser(ARC_Parser **parser, ARC_Bool header, ARC_ParserCSV_CastTypeFn castTypeFn, ARC_ParserCSV_DestroyTypeFn destroyTypeFn); #ifdef __cplusplus } diff --git a/include/arc/std/parser/helpers.h b/include/arc/std/parser/helpers.h index e69de29..e06f5c5 100644 --- a/include/arc/std/parser/helpers.h +++ b/include/arc/std/parser/helpers.h @@ -0,0 +1,26 @@ +#ifndef ARC_STD_PARSER_HELPERS_H_ +#define ARC_STD_PARSER_HELPERS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "arc/std/parser.h" +#include + +/** + * @brief recurses through a tag token adding token strings to a main string + * + * @note the string needs to be created otherwise this will break + * @note this will only add tokens that have data + * + * @param[in/out] data + * @param[in] tagToken the tag token to recurse through +*/ +void ARC_ParserData_HelperRecurseStringAdd(ARC_String **data, ARC_ParserTagToken *tagToken); + +#ifdef __cplusplus +} +#endif + +#endif //ARC_STD_PARSER_HELPERS_H_ diff --git a/include/arc/std/parser/parserlang.h b/include/arc/std/parser/parserlang.h index ee884e7..f7b8c35 100644 --- a/include/arc/std/parser/parserlang.h +++ b/include/arc/std/parser/parserlang.h @@ -9,10 +9,10 @@ extern "C" { /* -> NEWLINE | | NEWLINE | LAMBDA - -> WHITESPACE ARROW WHITESPACE + -> ARROW - -> WHITESPACE OR WHITESPACE | - -> WHITESPACE | + -> OR | + -> | -> | -> ALPHA_UPPER_CHAR @@ -24,9 +24,11 @@ extern "C" { -> | LAMBDA -> | NUMBER | UNDERSCORE -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR + + -> WHITESPACE | WHITESPACE */ -/* +/** * @brief creates a parser for the Parser Lang * * @note the rules will be inited for the parser lang @@ -70,6 +72,7 @@ void ARC_ParserLang_CreateAsParser(ARC_Parser **parser, ARC_Parser_GetStringIdFn #define ARC_PARSERLANG_VARIABLE_BODY 21 #define ARC_PARSERLANG_VARIABLE_CHAR 22 #define ARC_PARSERLANG_ALPHA_CHAR 23 +#define ARC_PARSERLANG_WHITESPACE 24 #ifdef __cplusplus } diff --git a/src/std/lexer.c b/src/std/lexer.c index ce90395..6e35bdd 100644 --- a/src/std/lexer.c +++ b/src/std/lexer.c @@ -477,8 +477,8 @@ void ARC_Lexer_InitBasicTokenRules(ARC_Lexer *lexer){ ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_LEXER_TOKEN_NUMBER, '0', '9')); //alpha char - ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_LEXER_TOKEN_ALPHALOWERCHAR, 'a', 'z')); - ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_LEXER_TOKEN_ALPHAUPPERCHAR, 'A', 'Z')); + ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_LEXER_TOKEN_ALPHA_LOWER_CHAR, 'a', 'z')); + ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_LEXER_TOKEN_ALPHA_UPPER_CHAR, 'A', 'Z')); //whitespace //TODO: fix this diff --git a/src/std/parser.c b/src/std/parser.c index 8846e37..bd5d23a 100644 --- a/src/std/parser.c +++ b/src/std/parser.c @@ -323,6 +323,7 @@ void ARC_Parser_Parse(ARC_Parser *parser, ARC_String **data){ //error if anything went wrong if(parsed == ARC_False || allTokensParsed == ARC_False || arc_errno){ ARC_Lexer_Clear(parser->lexer); + ARC_ParserTagToken_Destroy(tagToken); arc_errno = ARC_ERRNO_DATA; ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_Parser_Parse(parser, data), could not parse the given data at lexer index: %u", lexerIndex); diff --git a/src/std/parser/csv.c b/src/std/parser/csv.c index e69de29..cb8bfca 100644 --- a/src/std/parser/csv.c +++ b/src/std/parser/csv.c @@ -0,0 +1,71 @@ +#include "arc/std/parser/csv.h" +#include "arc/std/parser/helpers.h" +#include "arc/std/parser.h" +#include +#include + +typedef struct ARC_ParserCSVUserData { + ARC_Bool header; + ARC_ParserCSV_CastTypeFn castTypeFn; + ARC_ParserCSV_DestroyTypeFn destroyTypeFn; +} ARC_ParserCSVUserData; + +void ARC_ParserCSV_InitLexerRulesFn(ARC_Lexer *lexer){ +} + +uint32_t ARC_ParserCSV_GetStringIdFn(ARC_String *string){ + return 0; +} + +void ARC_ParserCSVData_CreateFn(void **data, ARC_ParserTagToken *parsedData, void *userData){ + if(data == NULL){ + return; + } +} + +void ARC_ParserCSVData_DestroyFn(void *data, void *userData){ + if(data != NULL){ + ARC_ParserCSVData *csvData = (ARC_ParserCSVData *)data; + + for(uint32_t x = 0; x < csvData->width; x++){ + ARC_String *string = csvData->headers[x]; + ARC_String_Destroy(string); + } + free(csvData->headers); + + for(uint32_t y = 0; y < csvData->height; y++){ + csvData->destroyTypeFn(csvData->data[y]); + } + free(csvData->data); + } + + if(userData != NULL){ + free((ARC_ParserCSVUserData *)userData); + } +} + +void ARC_ParserCSV_CreateAsParser(ARC_Parser **parser, ARC_Bool header, ARC_ParserCSV_CastTypeFn castTypeFn, ARC_ParserCSV_DestroyTypeFn destroyTypeFn){ + /* ~ define the language as a string ~ */ + char *languageCString = + " -> NEWLINE | | NEWLINE | LAMBDA" + " -> COMMA | " + " -> COMMON_CHAR | COMON_CHAR"; + + ARC_String *languageString; + ARC_String_CreateWithStrlen(&languageString, languageCString); + + /* ~ init the userdata ~ */ + ARC_ParserCSVUserData *userdata = (ARC_ParserCSVUserData *)malloc(sizeof(ARC_ParserCSVUserData)); + userdata->header = header; + userdata->castTypeFn = castTypeFn; + userdata->destroyTypeFn = destroyTypeFn; + + /* ~ create the language ~ */ + ARC_ParserData_CreateFn createCharFn = ARC_ParserCSVData_CreateFn; + ARC_ParserData_DestroyFn destroyCharFn = ARC_ParserCSVData_DestroyFn; + ARC_Parser_CreateFromString(parser, languageString, ARC_ParserCSV_InitLexerRulesFn, ARC_ParserCSV_GetStringIdFn, &createCharFn, &destroyCharFn, userdata); + + //cleanup + ARC_String_Destroy(languageString); +} + diff --git a/src/std/parser/helpers.c b/src/std/parser/helpers.c index e69de29..a32fff7 100644 --- a/src/std/parser/helpers.c +++ b/src/std/parser/helpers.c @@ -0,0 +1,26 @@ +#include "arc/std/parser/helpers.h" +#include "arc/std/errno.h" + +void ARC_ParserData_HelperRecurseStringAdd(ARC_String **data, ARC_ParserTagToken *tagToken){ + if(*data == NULL){ + arc_errno = ARC_ERRNO_NULL; + ARC_DEBUG_LOG_ERROR("ARC_ParserData_RecurseStringAdd(data, tagToken), string data was NULL"); + return; + } + + //only adds tokens with data (check the header for more information) + if(tagToken->token != NULL && tagToken->token->data != NULL){ + ARC_String_Append(data, tagToken->token->data); + return; + } + + //TODO: probs don't need this + if(tagToken->tagTokens == NULL){ + return; + } + + //recurse through all the tag tokens + for(uint32_t index = 0; index < ARC_Vector_GetSize(tagToken->tagTokens); index++){ + ARC_ParserData_HelperRecurseStringAdd(data, (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, index)); + } +} diff --git a/src/std/parser/parserlang.c b/src/std/parser/parserlang.c index 41c4a7b..0ef12a8 100644 --- a/src/std/parser/parserlang.c +++ b/src/std/parser/parserlang.c @@ -324,14 +324,14 @@ void ARC_ParserLang_CreateAsParser(ARC_Parser **parser, ARC_Parser_GetStringIdFn // -> NEWLINE | | NEWLINE | LAMBDA uint32_t *line[] = { (uint32_t[]){ 3, ARC_PARSERLANG_BODY, ARC_PARSERLANG_TOKEN_NEWLINE_ID, ARC_PARSERLANG_LINE }, (uint32_t[]){ 1, ARC_PARSERLANG_BODY }, (uint32_t[]){ 2, ARC_PARSERLANG_TOKEN_NEWLINE_ID, ARC_PARSERLANG_LINE }, (uint32_t[]){ 1, ARC_PARSERLANG_LAMBDA } }; - // -> WHITESPACE ARROW WHITESPACE - uint32_t *body[] = { (uint32_t[]){ 5, ARC_PARSERLANG_TAG, ARC_PARSERLANG_TOKEN_WHITESPACE, ARC_PARSERLANG_TOKEN_ARROW_ID, ARC_PARSERLANG_TOKEN_WHITESPACE, ARC_PARSERLANG_ARGUMENTS } }; + // -> ARROW + uint32_t *body[] = { (uint32_t[]){ 5, ARC_PARSERLANG_TAG, ARC_PARSERLANG_WHITESPACE, ARC_PARSERLANG_TOKEN_ARROW_ID, ARC_PARSERLANG_WHITESPACE, ARC_PARSERLANG_ARGUMENTS } }; - // -> WHITESPACE OR WHITESPACE | - uint32_t *arguments[] = { (uint32_t[]){ 5, ARC_PARSERLANG_ARGUMENT, ARC_PARSERLANG_TOKEN_WHITESPACE, ARC_PARSERLANG_TOKEN_OR_ID, ARC_PARSERLANG_TOKEN_WHITESPACE, ARC_PARSERLANG_ARGUMENTS }, (uint32_t[]){ 1, ARC_PARSERLANG_ARGUMENT } }; + // -> OR | + uint32_t *arguments[] = { (uint32_t[]){ 5, ARC_PARSERLANG_ARGUMENT, ARC_PARSERLANG_WHITESPACE, ARC_PARSERLANG_TOKEN_OR_ID, ARC_PARSERLANG_WHITESPACE, ARC_PARSERLANG_ARGUMENTS }, (uint32_t[]){ 1, ARC_PARSERLANG_ARGUMENT } }; - // -> WHITESPACE | - uint32_t *argument[] = { (uint32_t[]){ 3, ARC_PARSERLANG_TAG_OR_CONSTANT, ARC_PARSERLANG_TOKEN_WHITESPACE, ARC_PARSERLANG_ARGUMENT }, (uint32_t[]){ 1, ARC_PARSERLANG_TAG_OR_CONSTANT } }; + // -> | + uint32_t *argument[] = { (uint32_t[]){ 3, ARC_PARSERLANG_TAG_OR_CONSTANT, ARC_PARSERLANG_WHITESPACE, ARC_PARSERLANG_ARGUMENT }, (uint32_t[]){ 1, ARC_PARSERLANG_TAG_OR_CONSTANT } }; // -> | uint32_t *tagOrConstant[] = { (uint32_t[]){ 1, ARC_PARSERLANG_TAG }, (uint32_t[]){ 1, ARC_PARSERLANG_CONSTANT } }; @@ -360,7 +360,10 @@ void ARC_ParserLang_CreateAsParser(ARC_Parser **parser, ARC_Parser_GetStringIdFn // -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR uint32_t *alphaChar[] = { (uint32_t[]){ 1, ARC_PARSERLANG_TOKEN_ALPHA_LOWER_CHAR }, (uint32_t[]){ 1, ARC_PARSERLANG_TOKEN_ALPHA_UPPER_CHAR }}; - ARC_ParserTag parserLangTags[13] = { + // -> WHITESPACE | WHITESPACE + uint32_t *whitespace[] = { (uint32_t[]){ 2, ARC_PARSERLANG_TOKEN_WHITESPACE, ARC_PARSERLANG_WHITESPACE }, (uint32_t[]){ 1, ARC_PARSERLANG_TOKEN_WHITESPACE }}; + + ARC_ParserTag parserLangTags[14] = { { ARC_PARSERLANG_LINE , line , 4 }, { ARC_PARSERLANG_BODY , body , 1 }, { ARC_PARSERLANG_ARGUMENTS , arguments , 2 }, @@ -373,11 +376,12 @@ void ARC_ParserLang_CreateAsParser(ARC_Parser **parser, ARC_Parser_GetStringIdFn { ARC_PARSERLANG_VARIABLE , variable , 2 }, { ARC_PARSERLANG_VARIABLE_BODY , variableBody , 2 }, { ARC_PARSERLANG_VARIABLE_CHAR , variableChar , 3 }, - { ARC_PARSERLANG_ALPHA_CHAR , alphaChar , 2 } + { ARC_PARSERLANG_ALPHA_CHAR , alphaChar , 2 }, + { ARC_PARSERLANG_WHITESPACE , whitespace , 2 } }; ARC_Array parserLanguageArray = { - 13, //size + 14, //size parserLangTags //data }; diff --git a/tests/std/parser.c b/tests/std/parser.c index 70c1d44..a1f4aa3 100644 --- a/tests/std/parser.c +++ b/tests/std/parser.c @@ -1,43 +1,24 @@ #include "../test.h" #include "arc/std/errno.h" #include "arc/std/parser.h" +#include "arc/std/parser/helpers.h" #include "arc/std/lexer.h" #include "arc/std/vector.h" #include #include -#define LAMBDA ARC_PARSER_TAG_LAMBDA -#define CHAR ARC_LEXER_TOKEN_ALPHALOWERCHAR -#define NUM ARC_LEXER_TOKEN_NUMBER -#define CHAR_OR_NUM 23 -#define VARIABLE_NAME 24 -#define VARIABLE 25 +const uint32_t TEST_PARSER_CHAR_OR_NUM = 23; +const uint32_t TEST_PARSER_VARIABLE_NAME = 24; +const uint32_t TEST_PARSER_VARIABLE = 25; -const uint32_t TEST_LAMBDA = 0; -const uint32_t TEST_ALPHA_LOWER_CHAR = 1; -const uint32_t TEST_ALPHA_UPPER_CHAR = 2; -const uint32_t TEST_ALPHA_CHAR = 3; - -void TEST_ParserData_RecurseStringAdd(ARC_String **data, ARC_ParserTagToken *tagToken){ - if(tagToken->token != NULL){ - ARC_String_Append(data, tagToken->token->data); - return; - } - - //TODO: probs don't need this - if(tagToken->tagTokens == NULL){ - return; - } - - for(uint32_t index = 0; index < ARC_Vector_GetSize(tagToken->tagTokens); index++){ - TEST_ParserData_RecurseStringAdd(data, (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, index)); - } -} +const uint32_t TEST_PARSER_ALPHA_LOWER_CHAR = 1; +const uint32_t TEST_PARSER_ALPHA_UPPER_CHAR = 2; +const uint32_t TEST_PARSER_ALPHA_CHAR = 3; void TEST_ParserData_CreateStringFn(void **data, ARC_ParserTagToken *parsedData, void *userData){ ARC_String_Create((ARC_String **)data, NULL, 0); - TEST_ParserData_RecurseStringAdd((ARC_String **)data, parsedData); + ARC_ParserData_HelperRecurseStringAdd((ARC_String **)data, parsedData); } void TEST_ParserData_DestroyStringFn(void *data, void *userData){ @@ -48,30 +29,27 @@ void TEST_ParserData_DestroyStringFn(void *data, void *userData){ ARC_String_Destroy((ARC_String *)data); } -uint32_t *charOrNumTokens[] = { (uint32_t[]){ 1, CHAR }, (uint32_t[]){ 1, NUM } }; -uint32_t *variableNameTags[] = { (uint32_t[]){ 2, CHAR_OR_NUM, VARIABLE_NAME }, (uint32_t[]){ 1, LAMBDA } }; -uint32_t *variableTokensOrTags[] = { (uint32_t[]){ 2, CHAR, VARIABLE_NAME } }; +uint32_t *charOrNumTokens[] = { (uint32_t[]){ 1, ARC_LEXER_TOKEN_ALPHA_LOWER_CHAR }, (uint32_t[]){ 1, ARC_LEXER_TOKEN_NUMBER } }; +uint32_t *variableNameTags[] = { (uint32_t[]){ 2, TEST_PARSER_CHAR_OR_NUM, TEST_PARSER_VARIABLE_NAME }, (uint32_t[]){ 1, ARC_PARSER_TAG_LAMBDA } }; +uint32_t *variableTokensOrTags[] = { (uint32_t[]){ 2, ARC_LEXER_TOKEN_ALPHA_LOWER_CHAR, TEST_PARSER_VARIABLE_NAME } }; //TODO: note how language function callbacks work, and how they use the parentData if createDataFn is NULL -ARC_ParserData_CreateFn createStringFn = TEST_ParserData_CreateStringFn; -ARC_ParserData_DestroyFn destroyStringFn = TEST_ParserData_DestroyStringFn; - ARC_ParserTag testTags[3] = { { - VARIABLE, //tagId + TEST_PARSER_VARIABLE, //tagId variableTokensOrTags, //tokensOrTags 1 //tokenOrTagsSize }, { - VARIABLE_NAME, //tagId - variableNameTags, //tokensOrTags - 2 //tokenOrTagsSize + TEST_PARSER_VARIABLE_NAME, //tagId + variableNameTags, //tokensOrTags + 2 //tokenOrTagsSize }, { - CHAR_OR_NUM, //tagId - charOrNumTokens, //tokensOrTags - 2 //tokenOrTagsSize + TEST_PARSER_CHAR_OR_NUM, //tagId + charOrNumTokens, //tokensOrTags + 2 //tokenOrTagsSize } }; @@ -84,175 +62,179 @@ void TEST_Parser_InitLexerRulesFn(ARC_Lexer *lexer){ ARC_Lexer_InitBasicTokenRules(lexer); } -//ARC_TEST(Parser_Init){ -// ARC_Parser *parser; -// ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL); -// -// ARC_Parser_Destroy(parser); -// -// ARC_CHECK(arc_errno == 0); -//} -// -//ARC_TEST(Parser_Basic_Parse){ -// ARC_Parser *parser; -// ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL); -// -// ARC_String *tempString; -// -// -// /* ~ first test ~ */ -// ARC_String_CreateWithStrlen(&tempString, "myvar1"); -// -// //this destroys string, so no need for cleanup -// ARC_Parser_Parse(parser, &tempString); -// -// ARC_CHECK(arc_errno == 0); -// -// -// /* ~ second test ~ */ -// ARC_String_CreateWithStrlen(&tempString, "z1xwvq"); -// //this destroys string, so no need for cleanup -// ARC_Parser_Parse(parser, &tempString); -// -// -// ARC_CHECK(arc_errno == 0); -// -// -// /* ~ third test ~ */ -// ARC_String_CreateWithStrlen(&tempString, "z1234"); -// -// //this destroys string, so no need for cleanup -// ARC_Parser_Parse(parser, &tempString); -// -// ARC_CHECK(arc_errno == 0); -// -// -// /* ~ fourth test ~ */ -// ARC_String_CreateWithStrlen(&tempString, "aaaaa"); -// -// //this destroys string, so no need for cleanup -// ARC_Parser_Parse(parser, &tempString); -// -// ARC_CHECK(arc_errno == 0); -// -// -// /* ~ cleanup ~ */ -// ARC_Parser_Destroy(parser); -//} +ARC_TEST(Parser_Init){ + ARC_Parser *parser; + ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL); -//ARC_TEST(Parser_Basic_ParseError){ -// ARC_Parser *parser; -// ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL); -// -// ARC_String *tempString; -// -// -// /* ~ first test ~ */ -// ARC_String_CreateWithStrlen(&tempString, "!myVar1"); -// -// //this destroys string, so no need for cleanup -// ARC_Parser_Parse(parser, &tempString); -// -// ARC_CHECK(arc_errno == ARC_ERRNO_DATA); -// -// -// /* ~ second test ~ */ -// //check again with moved character -// arc_errno = 0; -// ARC_String_CreateWithStrlen(&tempString, "my!Var1"); -// -// //this destroys string, so no need for cleanup -// ARC_Parser_Parse(parser, &tempString); -// -// ARC_CHECK(arc_errno == ARC_ERRNO_DATA); -// -// -// /* ~ third test ~ */ -// //check again with moved character -// arc_errno = 0; -// ARC_String_CreateWithStrlen(&tempString, "myVar1!"); -// -// //this destroys string, so no need for cleanup -// ARC_Parser_Parse(parser, &tempString); -// -// ARC_CHECK(arc_errno == ARC_ERRNO_DATA); -// -// -// /* ~ cleanup ~ */ -// ARC_Parser_Destroy(parser); -// -// //reset for next test -// arc_errno = 0; -//} + ARC_Parser_Destroy(parser); -//ARC_TEST(Parser_Basic_GetParsedValue){ -// ARC_Parser *parser; -// ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, &createStringFn, &destroyStringFn, NULL); -// -// ARC_String *tempString; -// -// -// /* ~ first test ~ */ -// ARC_String_CreateWithStrlen(&tempString, "myvar1"); -// -// //this destroys string, so no need for cleanup -// ARC_Parser_Parse(parser, &tempString); -// -// ARC_CHECK(arc_errno == 0); -// -// ARC_String *checkValue = (ARC_String *)ARC_Parser_GetData(parser); -// ARC_CHECK(ARC_String_EqualsCStringWithStrlen(checkValue, "myvar1")); -// -// -// /* ~ cleanup ~ */ -// ARC_Parser_Destroy(parser); -//} -// -//ARC_TEST(Parser_ParserLang_BasicVector){ -// ARC_Vector *testLanguage; -// ARC_Vector_Create(&testLanguage, NULL, NULL); -// -// ARC_Vector_Add(testLanguage, testTags + 0); -// ARC_Vector_Add(testLanguage, testTags + 1); -// ARC_Vector_Add(testLanguage, testTags + 2); -// -// ARC_Parser *parser; -// ARC_Parser_CreateFromVector(&parser, testLanguage, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL); -// -// ARC_String *tempString; -// ARC_String_CreateWithStrlen(&tempString, "variablename"); -// -// //this destroys string, so no need for cleanup -// ARC_Parser_Parse(parser, &tempString); -// -// //cleanup -// ARC_Parser_Destroy(parser); -// ARC_Vector_Destroy(testLanguage); -// -// ARC_CHECK(arc_errno == 0); -//} + ARC_CHECK(arc_errno == 0); +} + +ARC_TEST(Parser_Basic_Parse){ + ARC_Parser *parser; + ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL); + + ARC_String *tempString; + + + /* ~ first test ~ */ + ARC_String_CreateWithStrlen(&tempString, "myvar1"); + + //this destroys string, so no need for cleanup + ARC_Parser_Parse(parser, &tempString); + + ARC_CHECK(arc_errno == 0); + + + /* ~ second test ~ */ + ARC_String_CreateWithStrlen(&tempString, "z1xwvq"); + //this destroys string, so no need for cleanup + ARC_Parser_Parse(parser, &tempString); + + + ARC_CHECK(arc_errno == 0); + + + /* ~ third test ~ */ + ARC_String_CreateWithStrlen(&tempString, "z1234"); + + //this destroys string, so no need for cleanup + ARC_Parser_Parse(parser, &tempString); + + ARC_CHECK(arc_errno == 0); + + + /* ~ fourth test ~ */ + ARC_String_CreateWithStrlen(&tempString, "aaaaa"); + + //this destroys string, so no need for cleanup + ARC_Parser_Parse(parser, &tempString); + + ARC_CHECK(arc_errno == 0); + + + /* ~ cleanup ~ */ + ARC_Parser_Destroy(parser); +} + +ARC_TEST(Parser_Basic_ParseError){ + ARC_Parser *parser; + ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL); + + ARC_String *tempString; + + + /* ~ first test ~ */ + ARC_String_CreateWithStrlen(&tempString, "!myVar1"); + + //this destroys string, so no need for cleanup + ARC_Parser_Parse(parser, &tempString); + + ARC_CHECK(arc_errno == ARC_ERRNO_DATA); + + + /* ~ second test ~ */ + //check again with moved character + arc_errno = 0; + ARC_String_CreateWithStrlen(&tempString, "my!Var1"); + + //this destroys string, so no need for cleanup + ARC_Parser_Parse(parser, &tempString); + + ARC_CHECK(arc_errno == ARC_ERRNO_DATA); + + + /* ~ third test ~ */ + //check again with moved character + arc_errno = 0; + ARC_String_CreateWithStrlen(&tempString, "myVar1!"); + + //this destroys string, so no need for cleanup + ARC_Parser_Parse(parser, &tempString); + + ARC_CHECK(arc_errno == ARC_ERRNO_DATA); + + + /* ~ cleanup ~ */ + ARC_Parser_Destroy(parser); + + //reset for next test + arc_errno = 0; +} + +ARC_TEST(Parser_Basic_GetParsedValue){ + ARC_Parser *parser; + + ARC_ParserData_CreateFn createStringFn = TEST_ParserData_CreateStringFn; + ARC_ParserData_DestroyFn destroyStringFn = TEST_ParserData_DestroyStringFn; + + ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, &createStringFn, &destroyStringFn, NULL); + + ARC_String *tempString; + + + /* ~ first test ~ */ + ARC_String_CreateWithStrlen(&tempString, "myvar1"); + + //this destroys string, so no need for cleanup + ARC_Parser_Parse(parser, &tempString); + + ARC_CHECK(arc_errno == 0); + + ARC_String *checkValue = (ARC_String *)ARC_Parser_GetData(parser); + ARC_CHECK(ARC_String_EqualsCStringWithStrlen(checkValue, "myvar1")); + + + /* ~ cleanup ~ */ + ARC_Parser_Destroy(parser); +} + +ARC_TEST(Parser_ParserLang_BasicVector){ + ARC_Vector *testLanguage; + ARC_Vector_Create(&testLanguage, NULL, NULL); + + ARC_Vector_Add(testLanguage, testTags + 0); + ARC_Vector_Add(testLanguage, testTags + 1); + ARC_Vector_Add(testLanguage, testTags + 2); + + ARC_Parser *parser; + ARC_Parser_CreateFromVector(&parser, testLanguage, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL); + + ARC_String *tempString; + ARC_String_CreateWithStrlen(&tempString, "variablename"); + + //this destroys string, so no need for cleanup + ARC_Parser_Parse(parser, &tempString); + + //cleanup + ARC_Parser_Destroy(parser); + ARC_Vector_Destroy(testLanguage); + + ARC_CHECK(arc_errno == 0); +} /* ~ parser tests ~ */ void TEST_Parser_InitBasicLexerTokenRules(ARC_Lexer *lexer){ //null - ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(TEST_LAMBDA, 0)); + ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_PARSER_TAG_LAMBDA, 0)); //alpha char - ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(TEST_ALPHA_LOWER_CHAR, 'a', 'z')); - ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(TEST_ALPHA_UPPER_CHAR, 'A', 'Z')); + ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(TEST_PARSER_ALPHA_LOWER_CHAR, 'a', 'z')); + ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(TEST_PARSER_ALPHA_UPPER_CHAR, 'A', 'Z')); } uint32_t TEST_Parser_GetStringIdFn(ARC_String *string){ if(ARC_String_EqualsCStringWithStrlen(string, "")){ - return TEST_ALPHA_CHAR; + return TEST_PARSER_ALPHA_CHAR; } if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_LOWER_CHAR")){ - return TEST_ALPHA_LOWER_CHAR; + return TEST_PARSER_ALPHA_LOWER_CHAR; } if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_UPPER_CHAR")){ - return TEST_ALPHA_UPPER_CHAR; + return TEST_PARSER_ALPHA_UPPER_CHAR; } return ~(uint32_t)0; diff --git a/tests/std/parser/parserlang.c b/tests/std/parser/parserlang.c index a814cb2..c9777ca 100644 --- a/tests/std/parser/parserlang.c +++ b/tests/std/parser/parserlang.c @@ -4,23 +4,20 @@ #include "arc/std/string.h" #include "arc/std/parser/parserlang.h" -const uint32_t TEST_LAMBDA = 0; -const uint32_t TEST_ALPHA_LOWER_CHAR = 1; -const uint32_t TEST_ALPHA_UPPER_CHAR = 2; -const uint32_t TEST_ALPHA_CHAR = 3; +uint32_t TEST_PARSERLANG_ALPHA_CHAR = 24; /* ~ parserlang tests ~ */ uint32_t TEST_ParserLang_GetIdFn(ARC_String *string){ if(ARC_String_EqualsCStringWithStrlen(string, "")){ - return TEST_ALPHA_CHAR; + return TEST_PARSERLANG_ALPHA_CHAR; } if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_LOWER_CHAR")){ - return TEST_ALPHA_LOWER_CHAR; + return ARC_PARSERLANG_TOKEN_ALPHA_LOWER_CHAR; } if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_UPPER_CHAR")){ - return TEST_ALPHA_UPPER_CHAR; + return ARC_PARSERLANG_TOKEN_ALPHA_UPPER_CHAR; } return ~(uint32_t)0; @@ -31,7 +28,7 @@ ARC_TEST(Parser_ParserLang_BasicTest){ ARC_ParserLang_CreateAsParser(&parser, TEST_ParserLang_GetIdFn); ARC_String *tempString; - ARC_String_CreateWithStrlen(&tempString, " -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR\n"); + ARC_String_CreateWithStrlen(&tempString, "\n\n -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR\n\n\n"); //this destroys string, so no need for cleanup ARC_Parser_Parse(parser, &tempString); @@ -40,13 +37,13 @@ ARC_TEST(Parser_ParserLang_BasicTest){ void *data = ARC_Parser_GetData(parser); ARC_ParserTag *tag = ARC_Vector_Get((ARC_Vector *)data, 0); - ARC_CHECK(tag->tagId == TEST_ALPHA_CHAR); + ARC_CHECK(tag->tagId == TEST_PARSERLANG_ALPHA_CHAR); - ARC_CHECK(tag->tokensOrTagsSize == 2); - ARC_CHECK(tag->tokensOrTags[0][0] == 1); - ARC_CHECK(tag->tokensOrTags[0][1] == TEST_ALPHA_LOWER_CHAR); - ARC_CHECK(tag->tokensOrTags[1][0] == 1); - ARC_CHECK(tag->tokensOrTags[1][1] == TEST_ALPHA_UPPER_CHAR); + ARC_CHECK(tag->tokensOrTagsSize == 2); + ARC_CHECK(tag->tokensOrTags[0][0] == 1); + ARC_CHECK(tag->tokensOrTags[0][1] == ARC_PARSERLANG_TOKEN_ALPHA_LOWER_CHAR); + ARC_CHECK(tag->tokensOrTags[1][0] == 1); + ARC_CHECK(tag->tokensOrTags[1][1] == ARC_PARSERLANG_TOKEN_ALPHA_UPPER_CHAR); ARC_Parser_Destroy(parser); }