parser fixed (still probably needs more testing, but current tests work), parserlang still not working

This commit is contained in:
herbglitch 2024-11-30 01:14:55 -07:00
parent 6d64a17b1d
commit 84c4dffc85
4 changed files with 153 additions and 161 deletions

View file

@ -12,12 +12,14 @@ struct ARC_Parser {
ARC_Lexer *lexer;
void *data;
void *data;
void *createUserData;
ARC_ParserData_CreateFn *createDataFn;
ARC_ParserData_DestroyFn *destroyDataFn;
};
void ARC_Parser_Create(ARC_Parser **parser, ARC_Array *language, ARC_Parser_InitLexerRulesFn initLexerRulesFn, ARC_ParserData_CreateFn *createDataFn, ARC_ParserData_DestroyFn *destroyDataFn){
void ARC_Parser_Create(ARC_Parser **parser, ARC_Array *language, ARC_Parser_InitLexerRulesFn initLexerRulesFn, ARC_ParserData_CreateFn *createDataFn, void *createUserData, ARC_ParserData_DestroyFn *destroyDataFn){
*parser = (ARC_Parser *)malloc(sizeof(ARC_Parser));
//set the language size to 0 and data to NULL in case the language is NULL
@ -63,7 +65,6 @@ void ARC_Parser_Create(ARC_Parser **parser, ARC_Array *language, ARC_Parser_Init
if(createDataFn != NULL){
(*parser)->createDataFn = (ARC_ParserData_CreateFn *)malloc(sizeof(ARC_ParserData_CreateFn));
*((*parser)->createDataFn) = *createDataFn;
(*createDataFn)(&((*parser)->data));
}
(*parser)->destroyDataFn = NULL;
@ -73,7 +74,7 @@ void ARC_Parser_Create(ARC_Parser **parser, ARC_Array *language, ARC_Parser_Init
}
}
void ARC_Parser_CreateFromVector(ARC_Parser **parser, ARC_Vector *language, ARC_Parser_InitLexerRulesFn initLexerRulesFn, ARC_ParserData_CreateFn *createDataFn, ARC_ParserData_DestroyFn *destroyDataFn){
void ARC_Parser_CreateFromVector(ARC_Parser **parser, ARC_Vector *language, ARC_Parser_InitLexerRulesFn initLexerRulesFn, ARC_ParserData_CreateFn *createDataFn, void *createUserData, ARC_ParserData_DestroyFn *destroyDataFn){
//creates the variables to copy the vector into
const uint32_t languageSize = ARC_Vector_GetSize(language);
ARC_ParserTag languageArray[languageSize];
@ -90,7 +91,7 @@ void ARC_Parser_CreateFromVector(ARC_Parser **parser, ARC_Vector *language, ARC_
};
//create the parser
ARC_Parser_Create(parser, &languageAsArray, initLexerRulesFn, createDataFn, destroyDataFn);
ARC_Parser_Create(parser, &languageAsArray, initLexerRulesFn, createDataFn, createUserData, destroyDataFn);
}
void ARC_Parser_CreateFromString(ARC_Parser **parser, ARC_String *languageString, ARC_Parser_InitLexerRulesFn initLexerRulesFn){
@ -129,13 +130,39 @@ void ARC_Parser_Destroy(ARC_Parser *parser){
free(parser);
}
//private creation function for ARC_ParserTagToken type
//note: token and tagTokens will be set to null, it is safe to create tagTokens outside of this as the destructor will clean it up
void ARC_ParserTagToken_Create(ARC_ParserTagToken **tagToken, uint32_t id){
*tagToken = (ARC_ParserTagToken *)malloc(sizeof(ARC_ParserTagToken));
(*tagToken)->id = id;
(*tagToken)->token = NULL;
(*tagToken)->tagTokens = NULL;
}
//private destroy function for ARC_ParserTagToken type
void ARC_ParserTagToken_Destroy(ARC_ParserTagToken *tagToken){
//destroy the tag token vector
if(tagToken->tagTokens != NULL){
ARC_Vector_Destroy(tagToken->tagTokens);
}
free(tagToken);
}
//private function to cleanup a parser tag token from a vector
void ARC_ParserTagToken_VectorDestroyDataFn(void *data){
//we can just use the destroy function with casted data
ARC_ParserTagToken_Destroy((ARC_ParserTagToken *)data);
}
//private recusive function to parse a tag
ARC_Bool ARC_Parser_ParseTag(ARC_Parser *parser, uint32_t *lexerIndex, uint32_t tagId){
ARC_Bool ARC_Parser_ParseTag(ARC_Parser *parser, ARC_ParserTagToken *tagToken, uint32_t *lexerIndex){
//get the current tag
ARC_ParserTag *tag = NULL;
for(uint32_t index = 0; index < parser->language.size; index++){
ARC_ParserTag *foundTag = ((ARC_ParserTag *)parser->language.data) + index;
if(foundTag->tagId == tagId){
if(foundTag->tagId == tagToken->id){
tag = foundTag;
break;
}
@ -144,43 +171,55 @@ ARC_Bool ARC_Parser_ParseTag(ARC_Parser *parser, uint32_t *lexerIndex, uint32_t
//if the tag was not found can't do much, so throw an error
if(tag == NULL){
arc_errno = ARC_ERRNO_NULL;
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_Parser_ParseTag(parser, subdata, tagId), could not find tag with id: %u", tagId);
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_Parser_ParseTag(parser, subdata, tagId), could not find tag with id: %u", tagToken->id);
return ARC_False;
}
//create a vector of found tokens to use if a rule is validated, a comparison function is not needed as it will be iterated through, the destroy function is not needed as well because they will be pointers to lexer tokens (the lexer owns the tokens)
ARC_Vector *foundTokens;
ARC_Vector_Create(&foundTokens, NULL, NULL);
//create a vector of tag token to use if a rule is validated, a comparison function is not needed as it will be iterated through
ARC_Vector_DestroyDataFn destroyTokenTagFn = ARC_ParserTagToken_VectorDestroyDataFn;
ARC_Vector_Create(&(tagToken->tagTokens), NULL, &destroyTokenTagFn);
//loop through each or section of the tags and tokens
for(uint32_t orIndex = 0; orIndex < tag->tokensOrTagsSize; orIndex++){
//reset the tokens for each or index
ARC_Vector_Clear(foundTokens);
//reset the tag tokens for each or index
ARC_Vector_Clear(tagToken->tagTokens);
//loop through each token or tag to check if the lexed data matches
uint32_t lexerCheckIndex = *lexerIndex;
ARC_Bool foundRule = ARC_True;
for(uint32_t tokenOrTagIndex = 1; tokenOrTagIndex < tag->tokensOrTags[orIndex][0] + 1; tokenOrTagIndex++){
//get next tag id to check
uint32_t nextTagId = tag->tokensOrTags[orIndex][tokenOrTagIndex];
//check if it is lambda (can return safely)
if(tag->tokensOrTags[orIndex][tokenOrTagIndex] == ARC_PARSER_TAG_LAMBDA){
if(nextTagId == ARC_PARSER_TAG_LAMBDA){
break;
}
//if the value isn't a token it is a tag, so recurs if it isn't a token
ARC_Bool isToken = ARC_Lexer_IsTokenId(parser->lexer, tag->tokensOrTags[orIndex][tokenOrTagIndex]);
ARC_Bool isToken = ARC_Lexer_IsTokenId(parser->lexer, nextTagId);
if(isToken == ARC_False){
//create a temporary lexer index in case the rule does not exist
uint32_t tempLexerCheckIndex = lexerCheckIndex;
//check if the tag works if not break to continue checking next or
uint32_t nextTagId = tag->tokensOrTags[orIndex][tokenOrTagIndex];
foundRule = ARC_Parser_ParseTag(parser, &tempLexerCheckIndex, nextTagId);
//create tag token for if the rule works
ARC_ParserTagToken *nextTagToken;
ARC_ParserTagToken_Create(&nextTagToken, nextTagId);
//check if the tag works if not break to continue checking next or index
foundRule = ARC_Parser_ParseTag(parser, nextTagToken, &tempLexerCheckIndex);
if(foundRule == ARC_False){
//clean up the tag token
ARC_ParserTagToken_Destroy(nextTagToken);
break;
}
//add the tag token because rule was found
ARC_Vector_Add(tagToken->tagTokens, nextTagToken);
//increase the lexer check index as a recursed rule was found, and continue checking
lexerCheckIndex = tempLexerCheckIndex;
continue;
}
@ -201,24 +240,27 @@ ARC_Bool ARC_Parser_ParseTag(ARC_Parser *parser, uint32_t *lexerIndex, uint32_t
break;
}
//the rule was a match so add it to the found tokens
ARC_Vector_Add(foundTokens, (void *)token);
//the rule was a match so create a tag token to store the token in
ARC_ParserTagToken *nextTagToken;
ARC_ParserTagToken_Create(&nextTagToken, nextTagId);
nextTagToken->token = token;
//add the token to the tag tokens
ARC_Vector_Add(tagToken->tagTokens, nextTagToken);
}
//if the rule is found we don't need to check anymore so we can return out
if(foundRule == ARC_True){
*lexerIndex = lexerCheckIndex;
//free the found tokens vector
ARC_Vector_Destroy(foundTokens);
//cleanup
return ARC_True;
}
}
//cleanup
ARC_Vector_Destroy(foundTokens);
ARC_Vector_Destroy(tagToken->tagTokens);
tagToken->tagTokens = NULL;
//no rule was found, so return false
return ARC_False;
@ -243,11 +285,25 @@ void ARC_Parser_Parse(ARC_Parser *parser, ARC_String **data){
uint32_t lexerIndex = 0;
ARC_ParserTag *startTag = parser->language.data;
//setup a tag token that will be passed to the creation callback on success
ARC_ParserTagToken *tagToken;
ARC_ParserTagToken_Create(&tagToken, startTag->tagId);
//TODO: handle error checks for if parsing fails
//recursivly parse from the inital start tag
ARC_Bool parsed = ARC_Parser_ParseTag(parser, &lexerIndex, startTag->tagId);
ARC_Bool parsed = ARC_Parser_ParseTag(parser, tagToken, &lexerIndex);
ARC_Bool allTokensParsed = lexerIndex == ARC_Lexer_GetTokensSize(parser->lexer);
//create the data if the creation callback exists
if(parser->createDataFn != NULL){
(*(parser->createDataFn))(&(parser->data), tagToken, parser->createUserData);
}
//cleanup
ARC_ParserTagToken_Destroy(tagToken);
ARC_Lexer_Clear(parser->lexer);
//error if anything went wrong
if(parsed == ARC_False || allTokensParsed == ARC_False || arc_errno){
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);
@ -260,8 +316,13 @@ void ARC_Parser_ParseFile(ARC_Parser *parser, ARC_String *path){
}
void ARC_Parser_ClearData(ARC_Parser *parser){
(*(parser->destroyDataFn))(parser->data);
(*(parser->createDataFn))(parser->data);
//check if that data exists and the destructor exists to make sure they can be run
if(parser->data != NULL && parser->destroyDataFn != NULL){
(*(parser->destroyDataFn))(parser->data);
}
//TODO: might want to error here
parser->data = NULL;
}
void *ARC_Parser_GetData(ARC_Parser *parser){