working on csv data, parser works but needs more testing, might add bool to ParserData_DestroyFn callback for clearing
This commit is contained in:
parent
4c3d357cb9
commit
ca6a9c118f
13 changed files with 384 additions and 279 deletions
|
|
@ -64,6 +64,8 @@ set(ARCHEUS_STD_SOURCES
|
||||||
src/std/io.c
|
src/std/io.c
|
||||||
src/std/lexer.c
|
src/std/lexer.c
|
||||||
src/std/parser.c
|
src/std/parser.c
|
||||||
|
src/std/parser/csv.c
|
||||||
|
src/std/parser/helpers.c
|
||||||
src/std/parser/parserlang.c
|
src/std/parser/parserlang.c
|
||||||
src/std/queue.c
|
src/std/queue.c
|
||||||
src/std/stack.c
|
src/std/stack.c
|
||||||
|
|
@ -131,6 +133,8 @@ if(ARCHEUS_STD_TESTS)
|
||||||
#tests/std/vector.c
|
#tests/std/vector.c
|
||||||
#tests/std/lexer.c
|
#tests/std/lexer.c
|
||||||
tests/std/parser.c
|
tests/std/parser.c
|
||||||
|
tests/std/parser/csv.c
|
||||||
|
tests/std/parser/parserlang.c
|
||||||
|
|
||||||
${ARCHEUS_STD_SOURCES}
|
${ARCHEUS_STD_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -245,11 +245,11 @@ ARC_LexerTokenRule ARC_LexerTokenRule_CreateAndReturnMatchCharInStringRule(uint3
|
||||||
/**
|
/**
|
||||||
* @brief basic tokens
|
* @brief basic tokens
|
||||||
*/
|
*/
|
||||||
#define ARC_LEXER_TOKEN_NULL 0
|
#define ARC_LEXER_TOKEN_NULL 0
|
||||||
#define ARC_LEXER_TOKEN_NUMBER 1
|
#define ARC_LEXER_TOKEN_NUMBER 1
|
||||||
#define ARC_LEXER_TOKEN_ALPHALOWERCHAR 2
|
#define ARC_LEXER_TOKEN_ALPHA_LOWER_CHAR 2
|
||||||
#define ARC_LEXER_TOKEN_ALPHAUPPERCHAR 3
|
#define ARC_LEXER_TOKEN_ALPHA_UPPER_CHAR 3
|
||||||
#define ARC_LEXER_TOKEN_WHITESPACE 4
|
#define ARC_LEXER_TOKEN_WHITESPACE 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief basic token type ids, chars, and tags
|
* @brief basic token type ids, chars, and tags
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ typedef struct ARC_ParserTag {
|
||||||
uint32_t tokensOrTagsSize;
|
uint32_t tokensOrTagsSize;
|
||||||
} ARC_ParserTag;
|
} ARC_ParserTag;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* @brief a parser type used inside of the parser data create function
|
* @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
|
* @note there are no public creation and destruction functions for this type as it is only ment to be used within the creation callback
|
||||||
|
|
|
||||||
|
|
@ -5,28 +5,54 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "arc/std/bool.h"
|
||||||
#include "arc/std/parser.h"
|
#include "arc/std/parser.h"
|
||||||
|
#include "arc/std/string.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
<line> -> <body> NEWLINE <line> | <body> | NEWLINE <line> | LAMBDA
|
<line> -> <data> NEWLINE <line> | <data> | NEWLINE <line> | LAMBDA
|
||||||
<body> -> <tag> WHITESPACE ARROW WHITESPACE <arguments>
|
<data> -> <string> COMMA <data> | <string>
|
||||||
|
<string> -> COMMON_CHAR <string> | COMON_CHAR
|
||||||
<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
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
* @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
|
* @brief creates a parser for the Parser Lang
|
||||||
*
|
*
|
||||||
* @note the rules will be inited 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
|
* @param[out] parser the parser to create
|
||||||
*/
|
*/
|
||||||
void ARC_ParserCSV_CreateAsParser(ARC_Parser **parser, ARC_Parser_GetStringIdFn getStringIdFn);
|
void ARC_ParserCSV_CreateAsParser(ARC_Parser **parser, ARC_Bool header, ARC_ParserCSV_CastTypeFn castTypeFn, ARC_ParserCSV_DestroyTypeFn destroyTypeFn);
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_
|
||||||
|
|
@ -9,10 +9,10 @@ extern "C" {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
<line> -> <body> NEWLINE <line> | <body> | NEWLINE <line> | LAMBDA
|
<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>
|
<arguments> -> <argument> <whitespace> OR <whitespace> <arguments> | <argument>
|
||||||
<argument> -> <tagOrConstant> WHITESPACE <argument> | <tagOrConstant>
|
<argument> -> <tagOrConstant> <whitespace> <argument> | <tagOrConstant>
|
||||||
<tagOrConstant> -> <tag> | <constant>
|
<tagOrConstant> -> <tag> | <constant>
|
||||||
|
|
||||||
<constant> -> ALPHA_UPPER_CHAR <constantBody>
|
<constant> -> ALPHA_UPPER_CHAR <constantBody>
|
||||||
|
|
@ -24,9 +24,11 @@ extern "C" {
|
||||||
<variableBody> -> <variableChar> <variableBody> | LAMBDA
|
<variableBody> -> <variableChar> <variableBody> | LAMBDA
|
||||||
<variableChar> -> <alphaChar> | NUMBER | UNDERSCORE
|
<variableChar> -> <alphaChar> | NUMBER | UNDERSCORE
|
||||||
<alphaChar> -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR
|
<alphaChar> -> ALPHA_LOWER_CHAR | ALPHA_UPPER_CHAR
|
||||||
|
|
||||||
|
<whitespace> -> WHITESPACE <whitespace> | WHITESPACE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* @brief creates a parser for the Parser Lang
|
* @brief creates a parser for the Parser Lang
|
||||||
*
|
*
|
||||||
* @note the rules will be inited 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_BODY 21
|
||||||
#define ARC_PARSERLANG_VARIABLE_CHAR 22
|
#define ARC_PARSERLANG_VARIABLE_CHAR 22
|
||||||
#define ARC_PARSERLANG_ALPHA_CHAR 23
|
#define ARC_PARSERLANG_ALPHA_CHAR 23
|
||||||
|
#define ARC_PARSERLANG_WHITESPACE 24
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -477,8 +477,8 @@ void ARC_Lexer_InitBasicTokenRules(ARC_Lexer *lexer){
|
||||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_LEXER_TOKEN_NUMBER, '0', '9'));
|
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_LEXER_TOKEN_NUMBER, '0', '9'));
|
||||||
|
|
||||||
//alpha char
|
//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_ALPHA_LOWER_CHAR, '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_UPPER_CHAR, 'A', 'Z'));
|
||||||
|
|
||||||
//whitespace
|
//whitespace
|
||||||
//TODO: fix this
|
//TODO: fix this
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,7 @@ void ARC_Parser_Parse(ARC_Parser *parser, ARC_String **data){
|
||||||
//error if anything went wrong
|
//error if anything went wrong
|
||||||
if(parsed == ARC_False || allTokensParsed == ARC_False || arc_errno){
|
if(parsed == ARC_False || allTokensParsed == ARC_False || arc_errno){
|
||||||
ARC_Lexer_Clear(parser->lexer);
|
ARC_Lexer_Clear(parser->lexer);
|
||||||
|
ARC_ParserTagToken_Destroy(tagToken);
|
||||||
|
|
||||||
arc_errno = ARC_ERRNO_DATA;
|
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);
|
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_Parser_Parse(parser, data), could not parse the given data at lexer index: %u", lexerIndex);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -324,14 +324,14 @@ void ARC_ParserLang_CreateAsParser(ARC_Parser **parser, ARC_Parser_GetStringIdFn
|
||||||
//<line> -> <body> NEWLINE <line> | <body> | NEWLINE <line> | LAMBDA
|
//<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 } };
|
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>
|
//<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 } };
|
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>
|
//<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 } };
|
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>
|
//<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 } };
|
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>
|
//<tagOrConstant> -> <parserLangageTag> | <constant>
|
||||||
uint32_t *tagOrConstant[] = { (uint32_t[]){ 1, ARC_PARSERLANG_TAG }, (uint32_t[]){ 1, ARC_PARSERLANG_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
|
//<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 }};
|
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_LINE , line , 4 },
|
||||||
{ ARC_PARSERLANG_BODY , body , 1 },
|
{ ARC_PARSERLANG_BODY , body , 1 },
|
||||||
{ ARC_PARSERLANG_ARGUMENTS , arguments , 2 },
|
{ 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 , variable , 2 },
|
||||||
{ ARC_PARSERLANG_VARIABLE_BODY , variableBody , 2 },
|
{ ARC_PARSERLANG_VARIABLE_BODY , variableBody , 2 },
|
||||||
{ ARC_PARSERLANG_VARIABLE_CHAR , variableChar , 3 },
|
{ 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 = {
|
ARC_Array parserLanguageArray = {
|
||||||
13, //size
|
14, //size
|
||||||
parserLangTags //data
|
parserLangTags //data
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,24 @@
|
||||||
#include "../test.h"
|
#include "../test.h"
|
||||||
#include "arc/std/errno.h"
|
#include "arc/std/errno.h"
|
||||||
#include "arc/std/parser.h"
|
#include "arc/std/parser.h"
|
||||||
|
#include "arc/std/parser/helpers.h"
|
||||||
#include "arc/std/lexer.h"
|
#include "arc/std/lexer.h"
|
||||||
#include "arc/std/vector.h"
|
#include "arc/std/vector.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define LAMBDA ARC_PARSER_TAG_LAMBDA
|
const uint32_t TEST_PARSER_CHAR_OR_NUM = 23;
|
||||||
#define CHAR ARC_LEXER_TOKEN_ALPHALOWERCHAR
|
const uint32_t TEST_PARSER_VARIABLE_NAME = 24;
|
||||||
#define NUM ARC_LEXER_TOKEN_NUMBER
|
const uint32_t TEST_PARSER_VARIABLE = 25;
|
||||||
#define CHAR_OR_NUM 23
|
|
||||||
#define VARIABLE_NAME 24
|
|
||||||
#define VARIABLE 25
|
|
||||||
|
|
||||||
const uint32_t TEST_LAMBDA = 0;
|
const uint32_t TEST_PARSER_ALPHA_LOWER_CHAR = 1;
|
||||||
const uint32_t TEST_ALPHA_LOWER_CHAR = 1;
|
const uint32_t TEST_PARSER_ALPHA_UPPER_CHAR = 2;
|
||||||
const uint32_t TEST_ALPHA_UPPER_CHAR = 2;
|
const uint32_t TEST_PARSER_ALPHA_CHAR = 3;
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TEST_ParserData_CreateStringFn(void **data, ARC_ParserTagToken *parsedData, void *userData){
|
void TEST_ParserData_CreateStringFn(void **data, ARC_ParserTagToken *parsedData, void *userData){
|
||||||
ARC_String_Create((ARC_String **)data, NULL, 0);
|
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){
|
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);
|
ARC_String_Destroy((ARC_String *)data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t *charOrNumTokens[] = { (uint32_t[]){ 1, CHAR }, (uint32_t[]){ 1, NUM } };
|
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, CHAR_OR_NUM, VARIABLE_NAME }, (uint32_t[]){ 1, LAMBDA } };
|
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, CHAR, VARIABLE_NAME } };
|
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
|
//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] = {
|
ARC_ParserTag testTags[3] = {
|
||||||
{
|
{
|
||||||
VARIABLE, //tagId
|
TEST_PARSER_VARIABLE, //tagId
|
||||||
variableTokensOrTags, //tokensOrTags
|
variableTokensOrTags, //tokensOrTags
|
||||||
1 //tokenOrTagsSize
|
1 //tokenOrTagsSize
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
VARIABLE_NAME, //tagId
|
TEST_PARSER_VARIABLE_NAME, //tagId
|
||||||
variableNameTags, //tokensOrTags
|
variableNameTags, //tokensOrTags
|
||||||
2 //tokenOrTagsSize
|
2 //tokenOrTagsSize
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
CHAR_OR_NUM, //tagId
|
TEST_PARSER_CHAR_OR_NUM, //tagId
|
||||||
charOrNumTokens, //tokensOrTags
|
charOrNumTokens, //tokensOrTags
|
||||||
2 //tokenOrTagsSize
|
2 //tokenOrTagsSize
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -84,175 +62,179 @@ void TEST_Parser_InitLexerRulesFn(ARC_Lexer *lexer){
|
||||||
ARC_Lexer_InitBasicTokenRules(lexer);
|
ARC_Lexer_InitBasicTokenRules(lexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//ARC_TEST(Parser_Init){
|
ARC_TEST(Parser_Init){
|
||||||
// ARC_Parser *parser;
|
ARC_Parser *parser;
|
||||||
// ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL);
|
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_Basic_ParseError){
|
ARC_Parser_Destroy(parser);
|
||||||
// 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_CHECK(arc_errno == 0);
|
||||||
// ARC_Parser *parser;
|
}
|
||||||
// ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, &createStringFn, &destroyStringFn, NULL);
|
|
||||||
//
|
ARC_TEST(Parser_Basic_Parse){
|
||||||
// ARC_String *tempString;
|
ARC_Parser *parser;
|
||||||
//
|
ARC_Parser_Create(&parser, &languageArray, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL);
|
||||||
//
|
|
||||||
// /* ~ first test ~ */
|
ARC_String *tempString;
|
||||||
// ARC_String_CreateWithStrlen(&tempString, "myvar1");
|
|
||||||
//
|
|
||||||
// //this destroys string, so no need for cleanup
|
/* ~ first test ~ */
|
||||||
// ARC_Parser_Parse(parser, &tempString);
|
ARC_String_CreateWithStrlen(&tempString, "myvar1");
|
||||||
//
|
|
||||||
// ARC_CHECK(arc_errno == 0);
|
//this destroys string, so no need for cleanup
|
||||||
//
|
ARC_Parser_Parse(parser, &tempString);
|
||||||
// ARC_String *checkValue = (ARC_String *)ARC_Parser_GetData(parser);
|
|
||||||
// ARC_CHECK(ARC_String_EqualsCStringWithStrlen(checkValue, "myvar1"));
|
ARC_CHECK(arc_errno == 0);
|
||||||
//
|
|
||||||
//
|
|
||||||
// /* ~ cleanup ~ */
|
/* ~ second test ~ */
|
||||||
// ARC_Parser_Destroy(parser);
|
ARC_String_CreateWithStrlen(&tempString, "z1xwvq");
|
||||||
//}
|
//this destroys string, so no need for cleanup
|
||||||
//
|
ARC_Parser_Parse(parser, &tempString);
|
||||||
//ARC_TEST(Parser_ParserLang_BasicVector){
|
|
||||||
// ARC_Vector *testLanguage;
|
|
||||||
// ARC_Vector_Create(&testLanguage, NULL, NULL);
|
ARC_CHECK(arc_errno == 0);
|
||||||
//
|
|
||||||
// ARC_Vector_Add(testLanguage, testTags + 0);
|
|
||||||
// ARC_Vector_Add(testLanguage, testTags + 1);
|
/* ~ third test ~ */
|
||||||
// ARC_Vector_Add(testLanguage, testTags + 2);
|
ARC_String_CreateWithStrlen(&tempString, "z1234");
|
||||||
//
|
|
||||||
// ARC_Parser *parser;
|
//this destroys string, so no need for cleanup
|
||||||
// ARC_Parser_CreateFromVector(&parser, testLanguage, TEST_Parser_InitLexerRulesFn, NULL, NULL, NULL);
|
ARC_Parser_Parse(parser, &tempString);
|
||||||
//
|
|
||||||
// ARC_String *tempString;
|
ARC_CHECK(arc_errno == 0);
|
||||||
// ARC_String_CreateWithStrlen(&tempString, "variablename");
|
|
||||||
//
|
|
||||||
// //this destroys string, so no need for cleanup
|
/* ~ fourth test ~ */
|
||||||
// ARC_Parser_Parse(parser, &tempString);
|
ARC_String_CreateWithStrlen(&tempString, "aaaaa");
|
||||||
//
|
|
||||||
// //cleanup
|
//this destroys string, so no need for cleanup
|
||||||
// ARC_Parser_Destroy(parser);
|
ARC_Parser_Parse(parser, &tempString);
|
||||||
// ARC_Vector_Destroy(testLanguage);
|
|
||||||
//
|
ARC_CHECK(arc_errno == 0);
|
||||||
// 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 ~ */
|
/* ~ parser tests ~ */
|
||||||
void TEST_Parser_InitBasicLexerTokenRules(ARC_Lexer *lexer){
|
void TEST_Parser_InitBasicLexerTokenRules(ARC_Lexer *lexer){
|
||||||
//null
|
//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
|
//alpha char
|
||||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(TEST_ALPHA_LOWER_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_ALPHA_UPPER_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){
|
uint32_t TEST_Parser_GetStringIdFn(ARC_String *string){
|
||||||
if(ARC_String_EqualsCStringWithStrlen(string, "<alphaChar>")){
|
if(ARC_String_EqualsCStringWithStrlen(string, "<alphaChar>")){
|
||||||
return TEST_ALPHA_CHAR;
|
return TEST_PARSER_ALPHA_CHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_LOWER_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")){
|
if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_UPPER_CHAR")){
|
||||||
return TEST_ALPHA_UPPER_CHAR;
|
return TEST_PARSER_ALPHA_UPPER_CHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ~(uint32_t)0;
|
return ~(uint32_t)0;
|
||||||
|
|
|
||||||
|
|
@ -4,23 +4,20 @@
|
||||||
#include "arc/std/string.h"
|
#include "arc/std/string.h"
|
||||||
#include "arc/std/parser/parserlang.h"
|
#include "arc/std/parser/parserlang.h"
|
||||||
|
|
||||||
const uint32_t TEST_LAMBDA = 0;
|
uint32_t TEST_PARSERLANG_ALPHA_CHAR = 24;
|
||||||
const uint32_t TEST_ALPHA_LOWER_CHAR = 1;
|
|
||||||
const uint32_t TEST_ALPHA_UPPER_CHAR = 2;
|
|
||||||
const uint32_t TEST_ALPHA_CHAR = 3;
|
|
||||||
|
|
||||||
/* ~ parserlang tests ~ */
|
/* ~ parserlang tests ~ */
|
||||||
uint32_t TEST_ParserLang_GetIdFn(ARC_String *string){
|
uint32_t TEST_ParserLang_GetIdFn(ARC_String *string){
|
||||||
if(ARC_String_EqualsCStringWithStrlen(string, "<alphaChar>")){
|
if(ARC_String_EqualsCStringWithStrlen(string, "<alphaChar>")){
|
||||||
return TEST_ALPHA_CHAR;
|
return TEST_PARSERLANG_ALPHA_CHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_LOWER_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")){
|
if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_UPPER_CHAR")){
|
||||||
return TEST_ALPHA_UPPER_CHAR;
|
return ARC_PARSERLANG_TOKEN_ALPHA_UPPER_CHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ~(uint32_t)0;
|
return ~(uint32_t)0;
|
||||||
|
|
@ -31,7 +28,7 @@ ARC_TEST(Parser_ParserLang_BasicTest){
|
||||||
ARC_ParserLang_CreateAsParser(&parser, TEST_ParserLang_GetIdFn);
|
ARC_ParserLang_CreateAsParser(&parser, TEST_ParserLang_GetIdFn);
|
||||||
|
|
||||||
ARC_String *tempString;
|
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
|
//this destroys string, so no need for cleanup
|
||||||
ARC_Parser_Parse(parser, &tempString);
|
ARC_Parser_Parse(parser, &tempString);
|
||||||
|
|
@ -40,13 +37,13 @@ ARC_TEST(Parser_ParserLang_BasicTest){
|
||||||
void *data = ARC_Parser_GetData(parser);
|
void *data = ARC_Parser_GetData(parser);
|
||||||
ARC_ParserTag *tag = ARC_Vector_Get((ARC_Vector *)data, 0);
|
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->tokensOrTagsSize == 2);
|
||||||
ARC_CHECK(tag->tokensOrTags[0][0] == 1);
|
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][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);
|
ARC_Parser_Destroy(parser);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue