working on csv data, parser works but needs more testing, might add bool to ParserData_DestroyFn callback for clearing

This commit is contained in:
herbglitch 2024-12-04 02:43:58 -07:00
parent 4c3d357cb9
commit ca6a9c118f
13 changed files with 384 additions and 279 deletions

View file

@ -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}
)

View file

@ -247,8 +247,8 @@ ARC_LexerTokenRule ARC_LexerTokenRule_CreateAndReturnMatchCharInStringRule(uint3
*/
#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_ALPHA_LOWER_CHAR 2
#define ARC_LEXER_TOKEN_ALPHA_UPPER_CHAR 3
#define ARC_LEXER_TOKEN_WHITESPACE 4
/**

View file

@ -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

View file

@ -5,28 +5,54 @@
extern "C" {
#endif
#include "arc/std/bool.h"
#include "arc/std/parser.h"
#include "arc/std/string.h"
#include <stdint.h>
/*
<line> -> <body> NEWLINE <line> | <body> | NEWLINE <line> | LAMBDA
<body> -> <tag> WHITESPACE ARROW WHITESPACE <arguments>
<arguments> -> <argument> WHITESPACE OR WHITESPACE <arguments> | <argument>
<argument> -> <tagOrConstant> WHITESPACE <argument> | <tagOrConstant>
<tagOrConstant> -> <tag> | <constant>
<constant> -> ALPHA_UPPER_CHAR <constantBody>
<constantBody> -> <constantChar> <constantBody> | LAMBDA
<constantChar> -> ALPHA_UPPER_CHAR | UNDERSCORE
<tag> -> LESS_THAN <variable> GREATER_THAN
<variable> -> <alphaChar> <variableBody> | UNDERSCORE <variableBody>
<variableBody> -> <variableChar> <variableBody> | LAMBDA
<variableChar> -> <alphaChar> | NUMBER | UNDERSCORE
<alphaChar> -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR
<line> -> <data> NEWLINE <line> | <data> | NEWLINE <line> | LAMBDA
<data> -> <string> COMMA <data> | <string>
<string> -> COMMON_CHAR <string> | 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
}

View file

@ -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 <stddef.h>
/**
* @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_

View file

@ -9,10 +9,10 @@ extern "C" {
/*
<line> -> <body> NEWLINE <line> | <body> | NEWLINE <line> | LAMBDA
<body> -> <tag> WHITESPACE ARROW WHITESPACE <arguments>
<body> -> <tag> <whitespace> ARROW <whitespace> <arguments>
<arguments> -> <argument> WHITESPACE OR WHITESPACE <arguments> | <argument>
<argument> -> <tagOrConstant> WHITESPACE <argument> | <tagOrConstant>
<arguments> -> <argument> <whitespace> OR <whitespace> <arguments> | <argument>
<argument> -> <tagOrConstant> <whitespace> <argument> | <tagOrConstant>
<tagOrConstant> -> <tag> | <constant>
<constant> -> ALPHA_UPPER_CHAR <constantBody>
@ -24,9 +24,11 @@ extern "C" {
<variableBody> -> <variableChar> <variableBody> | LAMBDA
<variableChar> -> <alphaChar> | NUMBER | UNDERSCORE
<alphaChar> -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR
<whitespace> -> WHITESPACE <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
}

View file

@ -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

View file

@ -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);

View file

@ -0,0 +1,71 @@
#include "arc/std/parser/csv.h"
#include "arc/std/parser/helpers.h"
#include "arc/std/parser.h"
#include <stddef.h>
#include <stdlib.h>
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 =
"<line> -> <data> NEWLINE <line> | <data> | NEWLINE <line> | LAMBDA"
"<data> -> <string> COMMA <data> | <string>"
"<string> -> COMMON_CHAR <string> | 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);
}

View file

@ -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));
}
}

View file

@ -324,14 +324,14 @@ void ARC_ParserLang_CreateAsParser(ARC_Parser **parser, ARC_Parser_GetStringIdFn
//<line> -> <body> NEWLINE <line> | <body> | NEWLINE <line> | 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 } };
//<body> -> <tag> WHITESPACE ARROW WHITESPACE <arguments>
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 } };
//<body> -> <tag> <whitespace> ARROW <whitespace> <arguments>
uint32_t *body[] = { (uint32_t[]){ 5, ARC_PARSERLANG_TAG, ARC_PARSERLANG_WHITESPACE, ARC_PARSERLANG_TOKEN_ARROW_ID, ARC_PARSERLANG_WHITESPACE, ARC_PARSERLANG_ARGUMENTS } };
//<arguments> -> <argument> WHITESPACE OR WHITESPACE <arguments> | <argument>
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 } };
//<arguments> -> <argument> <whitespace> OR <whitespace> <arguments> | <argument>
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 } };
//<argument> -> <tagOrConstant> WHITESPACE <argument> | <tagOrConstant>
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 } };
//<argument> -> <tagOrConstant> <whitespace> <argument> | <tagOrConstant>
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 } };
//<tagOrConstant> -> <parserLangageTag> | <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
//<alphaChar> -> 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 <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
};

View file

@ -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 <stddef.h>
#include <stdlib.h>
#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,28 +29,25 @@ 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
TEST_PARSER_VARIABLE_NAME, //tagId
variableNameTags, //tokensOrTags
2 //tokenOrTagsSize
},
{
CHAR_OR_NUM, //tagId
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, "<alphaChar>")){
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;

View file

@ -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, "<alphaChar>")){
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, "<alphaChar> -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR\n");
ARC_String_CreateWithStrlen(&tempString, "\n\n<alphaChar> -> 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[0][1] == ARC_PARSERLANG_TOKEN_ALPHA_LOWER_CHAR);
ARC_CHECK(tag->tokensOrTags[1][0] == 1);
ARC_CHECK(tag->tokensOrTags[1][1] == TEST_ALPHA_UPPER_CHAR);
ARC_CHECK(tag->tokensOrTags[1][1] == ARC_PARSERLANG_TOKEN_ALPHA_UPPER_CHAR);
ARC_Parser_Destroy(parser);
}