parser fixed (still probably needs more testing, but current tests work), parserlang still not working
This commit is contained in:
parent
6d64a17b1d
commit
84c4dffc85
4 changed files with 153 additions and 161 deletions
115
src/std/parser.c
115
src/std/parser.c
|
|
@ -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){
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue