renamed chemical to config, and renamed life to entity
This commit is contained in:
parent
30e8d94805
commit
04c89e46fe
10 changed files with 862 additions and 1725 deletions
|
|
@ -1,751 +0,0 @@
|
|||
#include "arc/std/chemical.h"
|
||||
#include "arc/std/parser/helpers.h"
|
||||
#include "arc/std/bool.h"
|
||||
#include "arc/std/errno.h"
|
||||
#include "arc/std/hashtable.h"
|
||||
#include "arc/std/parser.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct ARC_Chemical {
|
||||
ARC_Parser *parser;
|
||||
|
||||
ARC_Hashtable *types;
|
||||
|
||||
ARC_Hashtable *groups;
|
||||
ARC_Hashtable *currentGroup;
|
||||
|
||||
ARC_Bool load;
|
||||
};
|
||||
|
||||
typedef struct ARC_ChemicalTypeData {
|
||||
void *data;
|
||||
ARC_ChemicalType_DestroyFn destroyFn;
|
||||
} ARC_ChemicalTypeData;
|
||||
|
||||
void ARC_Chemical_InitLexerRulesFn(ARC_Lexer *lexer){
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_TAB , '\t'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_NEWLINE, '\n'));
|
||||
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_SPACE , ' ' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_BANG , '!' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_QUOTE , '"' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_HASH , '#' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_DOLLAR , '$' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_PERCENT , '%' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_AMPERSAND , '&' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_SINGLE_QUOTE, '\''));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_OPEN_PAREN , '(' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_CLOSE_PAREN , ')' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_ASTERISK , '*' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_PLUS , '+' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_COMMA , ',' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_MINUS , '-' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_PERIOD , '.' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_SLASH , '/' ));
|
||||
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_CHEMICAL_NUMBER , '0', '9'));
|
||||
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_COLON , ':'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_SEMICOLON , ';'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_LESS_THAN , '<'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_GREATER_THAN , '>'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_EQUAL , '='));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_QUESTION_MARK, '?'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_AT , '@'));
|
||||
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_CHEMICAL_ALPHA_UPPER_CHAR, 'A', 'Z'));
|
||||
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_OPEN_BRACKET , '[' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_BACKSLASH , '\\'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_CLOSE_BRACKET, ']' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_CARET , '^' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_UNDERSCORE , '_' ));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_GRAVE , '`' ));
|
||||
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharOrBetween(ARC_CHEMICAL_ALPHA_LOWER_CHAR, 'a', 'z'));
|
||||
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_OPEN_CURLY_BRACE , '{'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_VERTICAL_LINE , '|'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_CLOSE_CURLY_BRACE, '}'));
|
||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_TILDE , '~'));
|
||||
}
|
||||
|
||||
uint32_t ARC_Chemical_GetStringIdFn(ARC_String *string){
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "LAMBDA")){
|
||||
return ARC_PARSER_TAG_LAMBDA;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "TAB")){
|
||||
return ARC_CHEMICAL_TAB;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "NEWLINE")){
|
||||
return ARC_CHEMICAL_NEWLINE;
|
||||
}
|
||||
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "SPACE")){
|
||||
return ARC_CHEMICAL_SPACE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "BANG")){
|
||||
return ARC_CHEMICAL_BANG;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "QUOTE")){
|
||||
return ARC_CHEMICAL_QUOTE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "HASH")){
|
||||
return ARC_CHEMICAL_HASH;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "DOLLAR")){
|
||||
return ARC_CHEMICAL_DOLLAR;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "PERCENT")){
|
||||
return ARC_CHEMICAL_PERCENT;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "AMPERSAND")){
|
||||
return ARC_CHEMICAL_AMPERSAND;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "SINGLE_QUOTE")){
|
||||
return ARC_CHEMICAL_SINGLE_QUOTE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "OPEN_PAREN")){
|
||||
return ARC_CHEMICAL_OPEN_PAREN;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "CLOSE_PAREN")){
|
||||
return ARC_CHEMICAL_CLOSE_PAREN;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "ASTERISK")){
|
||||
return ARC_CHEMICAL_ASTERISK;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "PLUS")){
|
||||
return ARC_CHEMICAL_PLUS;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "COMMA")){
|
||||
return ARC_CHEMICAL_COMMA;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "MINUS")){
|
||||
return ARC_CHEMICAL_MINUS;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "PERIOD")){
|
||||
return ARC_CHEMICAL_PERIOD;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "SLASH")){
|
||||
return ARC_CHEMICAL_SLASH;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "NUMBER")){
|
||||
return ARC_CHEMICAL_NUMBER;
|
||||
}
|
||||
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "COLON")){
|
||||
return ARC_CHEMICAL_COLON;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "SEMICOLON")){
|
||||
return ARC_CHEMICAL_SEMICOLON;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "LESS_THAN")){
|
||||
return ARC_CHEMICAL_LESS_THAN;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "GREATER_THAN")){
|
||||
return ARC_CHEMICAL_GREATER_THAN;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "EQUAL")){
|
||||
return ARC_CHEMICAL_EQUAL;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "QUESTION_MARK")){
|
||||
return ARC_CHEMICAL_QUESTION_MARK;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "AT")){
|
||||
return ARC_CHEMICAL_AT;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_UPPER_CHAR")){
|
||||
return ARC_CHEMICAL_ALPHA_UPPER_CHAR;
|
||||
}
|
||||
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "OPEN_BRACKET")){
|
||||
return ARC_CHEMICAL_OPEN_BRACKET;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "BACKSLASH")){
|
||||
return ARC_CHEMICAL_BACKSLASH;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "CLOSE_BRACKET")){
|
||||
return ARC_CHEMICAL_CLOSE_BRACKET;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "CARET")){
|
||||
return ARC_CHEMICAL_CARET;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "UNDERSCORE")){
|
||||
return ARC_CHEMICAL_UNDERSCORE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "GRAVE")){
|
||||
return ARC_CHEMICAL_GRAVE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "ALPHA_LOWER_CHAR")){
|
||||
return ARC_CHEMICAL_ALPHA_LOWER_CHAR;
|
||||
}
|
||||
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "OPEN_CURLY_BRACE")){
|
||||
return ARC_CHEMICAL_OPEN_CURLY_BRACE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "VERTICAL_LINE")){
|
||||
return ARC_CHEMICAL_VERTICAL_LINE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "CLOSE_CURLY_BRACE")){
|
||||
return ARC_CHEMICAL_CLOSE_CURLY_BRACE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "TILDE")){
|
||||
return ARC_CHEMICAL_TILDE;
|
||||
}
|
||||
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<language>")){
|
||||
return ARC_CHEMICAL_LANGUAGE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<group>")){
|
||||
return ARC_CHEMICAL_GROUP;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<groupName>")){
|
||||
return ARC_CHEMICAL_GROUP_NAME;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<groupArgs>")){
|
||||
return ARC_CHEMICAL_GROUP_ARGS;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<variableLines>")){
|
||||
return ARC_CHEMICAL_VARIABLE_LINES;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<variableLine>")){
|
||||
return ARC_CHEMICAL_VARIABLE_LINE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<allowSpace>")){
|
||||
return ARC_CHEMICAL_ALLOW_SPACE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<type>")){
|
||||
return ARC_CHEMICAL_TYPE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<value>")){
|
||||
return ARC_CHEMICAL_VALUE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<nestedValue>")){
|
||||
return ARC_CHEMICAL_NESTED_VALUE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<valueArgs>")){
|
||||
return ARC_CHEMICAL_VALUE_ARGS;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<variable>")){
|
||||
return ARC_CHEMICAL_VARIABLE;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<variableName>")){
|
||||
return ARC_CHEMICAL_VARIABLE_NAME;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<variableChar>")){
|
||||
return ARC_CHEMICAL_VARIABLE_CHAR;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<string>")){
|
||||
return ARC_CHEMICAL_STRING;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<stringChars>")){
|
||||
return ARC_CHEMICAL_STRING_CHARS;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<stringChar>")){
|
||||
return ARC_CHEMICAL_STRING_CHAR;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<escapeChar>")){
|
||||
return ARC_CHEMICAL_ESCAPE_CHAR;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<numberSign>")){
|
||||
return ARC_CHEMICAL_NUMBER_SIGN;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<number>")){
|
||||
return ARC_CHEMICAL_NUMBER_TAG;
|
||||
}
|
||||
if(ARC_String_EqualsCStringWithStrlen(string, "<whitespace>")){
|
||||
return ARC_CHEMICAL_WHITESPACE;
|
||||
}
|
||||
|
||||
return ~(uint32_t)0;
|
||||
}
|
||||
|
||||
//private function to check hashtable keys used by chemical
|
||||
ARC_Bool ARC_Chemical_HashtableKeyCompareFn(void *key1, void *key2){
|
||||
return (ARC_Bool)strcmp((const char *)key1, (const char *)key2) == 0;
|
||||
}
|
||||
|
||||
//private function to clean up types
|
||||
void ARC_Chemical_TypeHashtableDestroyKeyValueFn(void *key, void *value){
|
||||
free((char *)key);
|
||||
free((ARC_ChemicalType *)value);
|
||||
}
|
||||
|
||||
//private function to clean up groups
|
||||
void ARC_Chemical_GroupHashtableDestroyKeyValueFn(void *key, void *value){
|
||||
free((char *)key);
|
||||
ARC_Hashtable_Destroy((ARC_Hashtable *)value);
|
||||
}
|
||||
|
||||
//private function to clean up goup data
|
||||
void ARC_Chemical_GroupDataHashtableDestroyKeyValueFn(void *key, void *value){
|
||||
free((char *)key);
|
||||
|
||||
ARC_ChemicalTypeData *typeData = (ARC_ChemicalTypeData *)value;
|
||||
typeData->destroyFn(typeData->data);
|
||||
free(typeData);
|
||||
}
|
||||
|
||||
//<variableLine> -> <whitespace> <type> <whitespace> <variable> <whitespace> EQUAL <whitespace> <value> <whitespace> SEMICOLON
|
||||
void ARC_ChemicalData_RunVariableLineTag(ARC_ParserTagToken *tagToken, ARC_Chemical *chemical){
|
||||
//skip whitespace and check for group name
|
||||
ARC_ParserTagToken *childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 1);
|
||||
|
||||
//get the type
|
||||
ARC_String *typeString;
|
||||
ARC_String_Create(&typeString, NULL, 0);
|
||||
ARC_ParserData_HelperRecurseStringAdd(&typeString, childTagToken);
|
||||
|
||||
//check if type exists in the types hashtable
|
||||
ARC_ChemicalType *type = (ARC_ChemicalType *)ARC_Hashtable_Get(chemical->types, typeString->data);
|
||||
if(type == NULL){
|
||||
//throw an error and return
|
||||
arc_errno = ARC_ERRNO_DATA;
|
||||
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_ChemicalData_RunVariableLineTag(tagToken, chemical), type \"%s\" was not registered to chemical", typeString->data);
|
||||
ARC_String_Destroy(typeString);
|
||||
return;
|
||||
}
|
||||
|
||||
//cleanup
|
||||
ARC_String_Destroy(typeString);
|
||||
|
||||
//get the variable
|
||||
childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 3);
|
||||
ARC_String *variableString;
|
||||
ARC_String_Create(&variableString, NULL, 0);
|
||||
ARC_ParserData_HelperRecurseStringAdd(&variableString, childTagToken);
|
||||
|
||||
//check if removing
|
||||
if(chemical->load == ARC_False){
|
||||
ARC_Hashtable_Remove(chemical->currentGroup, (void *)variableString->data);
|
||||
ARC_String_Destroy(variableString);
|
||||
return;
|
||||
}
|
||||
|
||||
//check to see if the current variable is already in the current group hashtable
|
||||
ARC_ChemicalTypeData *typeData = (ARC_ChemicalTypeData *)ARC_Hashtable_Get(chemical->currentGroup, variableString->data);
|
||||
if(typeData != NULL){
|
||||
//there is already a value so throw an error and return
|
||||
arc_errno = ARC_ERRNO_DATA;
|
||||
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_ChemicalData_RunVariableLineTag(tagToken, chemical), variable \"%s\" already registered to the current group", variableString->data);
|
||||
ARC_String_Destroy(variableString);
|
||||
return;
|
||||
}
|
||||
|
||||
//copy the string into a cstring that will be stored in the hashtable
|
||||
char *elementVariableCStr = malloc(sizeof(char) * (variableString->length + 1));
|
||||
strncpy(elementVariableCStr, variableString->data, variableString->length);
|
||||
elementVariableCStr[variableString->length] = '\0';
|
||||
ARC_String_Destroy(variableString);
|
||||
|
||||
//get <value>
|
||||
childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 7);
|
||||
|
||||
//check if <value> is a reference
|
||||
ARC_String *valueString;
|
||||
ARC_String_Create(&valueString, NULL, 0);
|
||||
ARC_ParserData_HelperRecurseStringAdd(&valueString, childTagToken);
|
||||
void *value = ARC_Hashtable_Get(chemical->currentGroup, valueString);
|
||||
ARC_String_Destroy(valueString);
|
||||
|
||||
//create where to store either the reference or type data
|
||||
typeData = (ARC_ChemicalTypeData *)malloc(sizeof(ARC_ChemicalTypeData));
|
||||
if(value != NULL){
|
||||
//point to the already stored data
|
||||
typeData->data = value;
|
||||
typeData->destroyFn = NULL;
|
||||
|
||||
//add to the current group hashtable
|
||||
ARC_Hashtable_Add(chemical->currentGroup, (void *)elementVariableCStr, (void *)typeData);
|
||||
return;
|
||||
}
|
||||
|
||||
//passed the parsed value into the copy type function and set the destroy function
|
||||
type->copyFn(&(typeData->data), childTagToken, chemical);
|
||||
typeData->destroyFn = type->destroyFn;
|
||||
|
||||
//add to the current group hashtable
|
||||
ARC_Hashtable_Add(chemical->currentGroup, (void *)elementVariableCStr, (void *)typeData);
|
||||
}
|
||||
|
||||
//<variableLines> -> <variableLine> <whitespace> <variableLines> | <variableLine>
|
||||
void ARC_ChemicalData_RunVariableLinesTag(ARC_ParserTagToken *tagToken, ARC_Chemical *chemical){
|
||||
//loop through the tags either going to the next line or the next body
|
||||
for(uint32_t index = 0; index < ARC_Vector_GetSize(tagToken->tagTokens); index++){
|
||||
ARC_ParserTagToken *childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, index);
|
||||
|
||||
switch(childTagToken->id){
|
||||
//recuse to run the next line
|
||||
case ARC_CHEMICAL_VARIABLE_LINES:
|
||||
ARC_ChemicalData_RunVariableLinesTag(childTagToken, chemical);
|
||||
if(arc_errno != 0){
|
||||
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunVariableLinesTag(tagToken, chemical), chemical errored when trying to used parsed data for variable lines");
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
|
||||
//recurse into a variable line tag
|
||||
case ARC_CHEMICAL_VARIABLE_LINE:
|
||||
ARC_ChemicalData_RunVariableLineTag(childTagToken, chemical);
|
||||
if(arc_errno != 0){
|
||||
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunVariableLinesTag(tagToken, chemical), chemical errored when trying to used parsed data for variable line");
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
|
||||
//this is for whitespace and any oddities
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<group> -> <whitespace> <groupName> <whitespace> <variable> <whitespace> OPEN_CURLY_BRACE <groupArgs> <whitespace> CLOSE_CURLY_BRACE
|
||||
void ARC_ChemicalData_RunGroupTag(ARC_ParserTagToken *tagToken, ARC_Chemical *chemical){
|
||||
//skip whitespace and check for group name
|
||||
ARC_ParserTagToken *childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 1);
|
||||
|
||||
/* ~ <groupName> ~ */
|
||||
//get the group name and check if it is named "group"
|
||||
//NOTE: this check may be usedful in the future if there is different functionality for group like tag names
|
||||
ARC_String *groupName;
|
||||
ARC_String_Create(&groupName, NULL, 0);
|
||||
ARC_ParserData_HelperRecurseStringAdd(&groupName, childTagToken);
|
||||
if(ARC_String_EqualsCStringWithStrlen(groupName, ARC_CHEMICAL_GROUP_TAG_NAME) == ARC_False){
|
||||
//throw an error and return
|
||||
arc_errno = ARC_ERRNO_DATA;
|
||||
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_ChemicalData_RunGroupTag(tagToken, chemical), chemical contained keyword \"%s\" instead of using the correct keyword: \"%s\" ", groupName->data, ARC_CHEMICAL_GROUP_TAG_NAME);
|
||||
ARC_String_Destroy(groupName);
|
||||
return;
|
||||
}
|
||||
|
||||
//cleanup
|
||||
ARC_String_Destroy(groupName);
|
||||
|
||||
/* ~ <variable> ~ */
|
||||
//get the group's variable name
|
||||
childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 3);
|
||||
ARC_String *groupVariable;
|
||||
ARC_String_Create(&groupVariable, NULL, 0);
|
||||
ARC_ParserData_HelperRecurseStringAdd(&groupVariable, childTagToken);
|
||||
|
||||
//check if removing
|
||||
if(chemical->load == ARC_False){
|
||||
/* ~ <groupArgs> ~ */
|
||||
childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 6);
|
||||
|
||||
//<groupArgs> -> <whitespace> <variableLines> | LAMBDA
|
||||
if(childTagToken->token == NULL && ARC_Vector_GetSize(childTagToken->tagTokens) == 2){
|
||||
ARC_ParserTagToken *variableLines = (ARC_ParserTagToken *)ARC_Vector_Get(childTagToken->tagTokens, 1);
|
||||
ARC_ChemicalData_RunVariableLinesTag(variableLines, chemical);
|
||||
|
||||
//log error if it happens
|
||||
if(arc_errno != 0){
|
||||
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunGroupTag(tagToken, chemical), chemical errored when trying to used parsed data for variable lines");
|
||||
}
|
||||
}
|
||||
|
||||
//remove an empty hashtable if it is now empty
|
||||
if(ARC_Hashtable_GetSize(chemical->groups)){
|
||||
ARC_String_Destroy(groupVariable);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//get the needed hashtable or create it from the groups hashtable
|
||||
ARC_Hashtable *groupHashtable = ARC_Hashtable_Get(chemical->groups, (void *)groupVariable->data);
|
||||
if(groupHashtable == NULL){
|
||||
//copy the string into a cstring that will be stored in the hashtable
|
||||
char *groupVariableCStr = malloc(sizeof(char) * (groupVariable->length + 1));
|
||||
strncpy(groupVariableCStr, groupVariable->data, groupVariable->length);
|
||||
groupVariableCStr[groupVariable->length] = '\0';
|
||||
|
||||
//create the hashtable with the given group name key
|
||||
ARC_Hashtable_KeyCompareFn keyCompareFn = ARC_Chemical_HashtableKeyCompareFn;
|
||||
ARC_Hashtable_DestroyKeyValueFn groupDataDestroyKeyValueFn = ARC_Chemical_GroupDataHashtableDestroyKeyValueFn;
|
||||
ARC_Hashtable_Create(&groupHashtable, NULL, &keyCompareFn, &groupDataDestroyKeyValueFn);
|
||||
ARC_Hashtable_Add(chemical->groups, (void *)groupVariableCStr, (void *)groupHashtable);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
ARC_String_Destroy(groupVariable);
|
||||
|
||||
//set the current group to the group just created or found
|
||||
chemical->currentGroup = groupHashtable;
|
||||
|
||||
/* ~ <groupArgs> ~ */
|
||||
childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 6);
|
||||
|
||||
//<groupArgs> -> <whitespace> <variableLines> | LAMBDA
|
||||
if(childTagToken->token == NULL && ARC_Vector_GetSize(childTagToken->tagTokens) == 2){
|
||||
ARC_ParserTagToken *variableLines = (ARC_ParserTagToken *)ARC_Vector_Get(childTagToken->tagTokens, 1);
|
||||
ARC_ChemicalData_RunVariableLinesTag(variableLines, chemical);
|
||||
|
||||
//log error if it happens, but as setting the group back is the last thing we shouldn't return
|
||||
if(arc_errno != 0){
|
||||
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunGroupTag(tagToken, chemical), chemical errored when trying to used parsed data for variable lines");
|
||||
}
|
||||
}
|
||||
|
||||
/* ~ reset current group ~ */
|
||||
chemical->currentGroup = ARC_Hashtable_Get(chemical->groups, (void *)ARC_CHEMICAL_DEFAULT_GROUP);
|
||||
}
|
||||
|
||||
//<language> -> <group> <language> | <variableLines> <language> | <whitespace>
|
||||
void ARC_ChemicalData_RunLanguageTag(ARC_ParserTagToken *tagToken, ARC_Chemical *chemical){
|
||||
//loop through the tags either going to the next language, group, or variable lines
|
||||
for(uint32_t index = 0; index < ARC_Vector_GetSize(tagToken->tagTokens); index++){
|
||||
ARC_ParserTagToken *childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, index);
|
||||
|
||||
switch(childTagToken->id){
|
||||
//recuse to run the next line
|
||||
case ARC_CHEMICAL_LANGUAGE:
|
||||
ARC_ChemicalData_RunLanguageTag(childTagToken, chemical);
|
||||
continue;
|
||||
|
||||
//recurse into a group tag
|
||||
case ARC_CHEMICAL_GROUP:
|
||||
ARC_ChemicalData_RunGroupTag(childTagToken, chemical);
|
||||
if(arc_errno != 0){
|
||||
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunLanguageTag(tagToken, chemical), chemical errored when trying to used parsed data for a group");
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
|
||||
//recurse through variable lines
|
||||
case ARC_CHEMICAL_VARIABLE_LINES:
|
||||
ARC_ChemicalData_RunVariableLinesTag(childTagToken, chemical);
|
||||
ARC_ChemicalData_RunGroupTag(childTagToken, chemical);
|
||||
if(arc_errno != 0){
|
||||
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunLanguageTag(tagToken, chemical), chemical errored when trying to used parsed data for variable lines");
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
|
||||
//this is for whitespace and any oddities
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARC_ChemicalData_CreateFn(void **data, ARC_ParserTagToken *parsedData, void *userData){
|
||||
*data = NULL;
|
||||
if(parsedData == NULL || userData == NULL){
|
||||
//TODO: error here?
|
||||
*data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
ARC_ChemicalData_RunLanguageTag(parsedData, (ARC_Chemical *)userData);
|
||||
}
|
||||
|
||||
void ARC_ChemicalData_DestroyFn(void *data, ARC_Bool clear, void *userData){
|
||||
return;
|
||||
}
|
||||
|
||||
void ARC_Chemical_Create(ARC_Chemical **chemical){
|
||||
*chemical = (ARC_Chemical *)malloc(sizeof(ARC_Chemical));
|
||||
|
||||
/* ~ define the language as a string ~ */
|
||||
char *languageCString =
|
||||
"<language> -> <group> <language> | <variableLines> <language> | <whitespace>\n"
|
||||
|
||||
"<group> -> <whitespace> <groupName> <whitespace> <variable> <whitespace> OPEN_CURLY_BRACE <groupArgs> <whitespace> CLOSE_CURLY_BRACE\n"
|
||||
"<groupName> -> <variable>\n"
|
||||
"<groupArgs> -> <whitespace> <variableLines> | LAMBDA\n"
|
||||
|
||||
"<variableLines> -> <variableLine> <whitespace> <variableLines> | <variableLine>\n"
|
||||
"<variableLine> -> <whitespace> <type> <whitespace> <variable> <whitespace> EQUAL <whitespace> <value> <whitespace> SEMICOLON\n"
|
||||
"<allowSpace> -> SPACE <allowSpace> | TAB <allowSpace> | LAMBDA\n"
|
||||
|
||||
"<type> -> <variable>\n"
|
||||
"<value> -> <variable> | <numberSign> | <string> | <nestedValue>\n"
|
||||
"<nestedValue> -> OPEN_CURLY_BRACE <whitespace> <valueArgs> <whitespace> CLOSE_CURLY_BRACE\n"
|
||||
"<valueArgs> -> <value> COMMA <valueArgs> | <value>\n"
|
||||
|
||||
"<variable> -> ALPHA_UPPER_CHAR <variableName> | ALPHA_LOWER_CHAR <variableName> | UNDERSCORE <variableName>\n"
|
||||
"<variableName> -> <variableChar> <variableName> | LAMBDA\n"
|
||||
"<variableChar> -> ALPHA_UPPER_CHAR | ALPHA_LOWER_CHAR | UNDERSCORE | NUMBER\n"
|
||||
|
||||
"<string> -> QUOTE <stringChars> QUOTE\n"
|
||||
"<stringChars> -> <stringChar> <stringChars> | <escapeChar> <stringChars> | LAMBDA\n"
|
||||
"<stringChar> -> TAB | SPACE | BANG | HASH | DOLLAR | PERCENT | AMPERSAND | SINGLE_QUOTE | OPEN_PAREN | CLOSE_PAREN | ASTERISK | PLUS | COMMA | MINUS | PERIOD | SLASH | NUMBER | COLON | SEMICOLON | LESS_THAN | GREATER_THAN | EQUAL | QUESTION_MARK | AT | ALPHA_UPPER_CHAR | OPEN_BRACKET | CLOSE_BRACKET | CARET | UNDERSCORE | GRAVE | ALPHA_LOWER_CHAR | OPEN_CURLY_BRACE | VERTICAL_LINE | CLOSE_CURLY_BRACE | TILDE\n"
|
||||
"<escapeChar> -> BACKSLASH BACKSLASH | BACKSLASH QUOTE | BACKSLASH ALPHA_UPPER_CHAR | BACKSLASH ALPHA_LOWER_CHAR\n"
|
||||
|
||||
"<numberSign> -> MINUS <number> | <number>\n"
|
||||
"<number> -> NUMBER <number> | NUMBER\n"
|
||||
|
||||
"<whitespace> -> SPACE <whitespace> | TAB <whitespace> | NEWLINE <whitespace> | LAMBDA\n";
|
||||
|
||||
/* ~ define the language as a string ~ */
|
||||
ARC_String *languageString;
|
||||
ARC_String_CreateWithStrlen(&languageString, languageCString);
|
||||
|
||||
/* ~ set chemical as userdata ~ */
|
||||
void *userdata = *chemical;
|
||||
|
||||
/* ~ create the language ~ */
|
||||
ARC_ParserData_CreateFn createCharFn = ARC_ChemicalData_CreateFn;
|
||||
ARC_ParserData_DestroyFn destroyCharFn = ARC_ChemicalData_DestroyFn;
|
||||
ARC_Parser_CreateFromString(&((*chemical)->parser), languageString, ARC_Chemical_InitLexerRulesFn, ARC_Chemical_GetStringIdFn, &createCharFn, &destroyCharFn, userdata);
|
||||
|
||||
/* ~ init types ~ */
|
||||
ARC_Hashtable_KeyCompareFn keyCompareFn = ARC_Chemical_HashtableKeyCompareFn;
|
||||
ARC_Hashtable_DestroyKeyValueFn typeDestroyKeyValueFn = ARC_Chemical_TypeHashtableDestroyKeyValueFn;
|
||||
ARC_Hashtable_Create(&((*chemical)->types), NULL, &keyCompareFn, &typeDestroyKeyValueFn);
|
||||
|
||||
/* ~ init groups ~ */
|
||||
ARC_Hashtable_DestroyKeyValueFn groupDestroyKeyValueFn = ARC_Chemical_GroupHashtableDestroyKeyValueFn;
|
||||
ARC_Hashtable_Create(&((*chemical)->groups), NULL, &keyCompareFn, &groupDestroyKeyValueFn);
|
||||
|
||||
//add the default/empty group into the groups
|
||||
ARC_Hashtable_DestroyKeyValueFn groupDataDestroyKeyValueFn = ARC_Chemical_GroupDataHashtableDestroyKeyValueFn;
|
||||
|
||||
//copy empty group cstring (to be freed by hashtable on cleanup, passing directly would cause a segfault)
|
||||
char *emptyCStr = (char *)malloc(sizeof(char) * (strlen(ARC_CHEMICAL_DEFAULT_GROUP) + 1));
|
||||
strcpy(emptyCStr, ARC_CHEMICAL_DEFAULT_GROUP);
|
||||
|
||||
//set the current group as empty, then add that into the groups hashtable
|
||||
ARC_Hashtable_Create(&((*chemical)->currentGroup), NULL, &keyCompareFn, &groupDataDestroyKeyValueFn);
|
||||
ARC_Hashtable_Add((*chemical)->groups, (void *)emptyCStr, (*chemical)->currentGroup);
|
||||
|
||||
(*chemical)->load = ARC_True;
|
||||
|
||||
//cleanup
|
||||
ARC_String_Destroy(languageString);
|
||||
}
|
||||
|
||||
void ARC_Chemical_Destroy(ARC_Chemical *chemical){
|
||||
ARC_Parser_Destroy(chemical->parser);
|
||||
//NOTE: chemical->currentGroup does not need to be freed as it is stored in chemical->groups
|
||||
ARC_Hashtable_Destroy(chemical->groups);
|
||||
ARC_Hashtable_Destroy(chemical->types);
|
||||
free(chemical);
|
||||
}
|
||||
|
||||
void ARC_Chemical_RegisterType(ARC_Chemical *chemical, ARC_String *typeName, ARC_ChemicalType type){
|
||||
ARC_Chemical_RegisterTypeWithCStr(chemical, typeName->data, type);
|
||||
}
|
||||
|
||||
void ARC_Chemical_RegisterTypeWithCStr(ARC_Chemical *chemical, const char *typeNameCStr, ARC_ChemicalType type){
|
||||
//check if the type key already exists and error if it does
|
||||
if(ARC_Hashtable_Get(chemical->types, (void *)typeNameCStr) != NULL){
|
||||
arc_errno = ARC_ERRNO_EXISTS;
|
||||
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_Chemical_RegisterTypeWithCStr(chemical, typeName, type), type \"%s\" has already been registered", typeNameCStr);
|
||||
return;
|
||||
}
|
||||
|
||||
//copy the string into a cstring for long term storage
|
||||
uint64_t typeNameCopyLength = strlen(typeNameCStr) + 1;
|
||||
char *typeNameCopy = (char *)malloc(sizeof(char) * typeNameCopyLength);
|
||||
strncpy(typeNameCopy, typeNameCStr, typeNameCopyLength);
|
||||
typeNameCopy[strlen(typeNameCStr)] = '\0';
|
||||
|
||||
//copy the type for long term storage
|
||||
ARC_ChemicalType *typeCopy = (ARC_ChemicalType *)malloc(sizeof(ARC_ChemicalType));
|
||||
*typeCopy = type;
|
||||
|
||||
//add the type to a hashtable containing all the types
|
||||
ARC_Hashtable_Add(chemical->types, typeNameCopy, typeCopy);
|
||||
}
|
||||
|
||||
void ARC_Chemical_SetGroup(ARC_Chemical *chemical, ARC_String *groupName){
|
||||
ARC_Chemical_SetGroupWithCStr(chemical, groupName->data);
|
||||
}
|
||||
|
||||
void ARC_Chemical_SetGroupWithCStr(ARC_Chemical *chemical, const char *groupName){
|
||||
//try to get the current group
|
||||
void *currentGroup = ARC_Hashtable_Get(chemical->groups, (void *)groupName);
|
||||
|
||||
//error if the current group does not exist
|
||||
if(currentGroup == NULL){
|
||||
arc_errno = ARC_ERRNO_NULL;
|
||||
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_Chemical_SetGroupWithCStr(chemical, groupName), no group with name \"%s\"", groupName);
|
||||
return;
|
||||
}
|
||||
|
||||
//set the current group
|
||||
chemical->currentGroup = currentGroup;
|
||||
}
|
||||
|
||||
void *ARC_Chemical_Get(ARC_Chemical *chemical, ARC_String *energy){
|
||||
//check if the group separator exists
|
||||
uint64_t startSeparatorIndex = ARC_String_FindCStringWithStrlen(energy, ARC_CHEMICAL_GROUP_SEPARATOR);
|
||||
if(startSeparatorIndex == ~(uint64_t)0){
|
||||
//use empty group
|
||||
chemical->currentGroup = ARC_Hashtable_Get(chemical->groups, (void *)ARC_CHEMICAL_DEFAULT_GROUP);
|
||||
|
||||
//get the typeData and pass back the data without the cleanup function
|
||||
ARC_ChemicalTypeData *typeData = (ARC_ChemicalTypeData *)ARC_Hashtable_Get(chemical->currentGroup, (void *)energy->data);
|
||||
if(typeData == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return typeData->data;
|
||||
}
|
||||
|
||||
//get the group
|
||||
startSeparatorIndex--;
|
||||
ARC_String *groupString;
|
||||
ARC_String_CopySubstring(&groupString, energy, 0, startSeparatorIndex);
|
||||
|
||||
//set the group
|
||||
chemical->currentGroup = ARC_Hashtable_Get(chemical->groups, (void *)groupString->data);
|
||||
|
||||
//cleanup
|
||||
ARC_String_Destroy(groupString);
|
||||
|
||||
//get the element
|
||||
ARC_String *energyString;
|
||||
startSeparatorIndex += strlen(ARC_CHEMICAL_GROUP_SEPARATOR);
|
||||
ARC_String_CopySubstring(&energyString, energy, startSeparatorIndex, energy->length - startSeparatorIndex);
|
||||
|
||||
//this will either return the value or NULL
|
||||
ARC_ChemicalTypeData *typeData = (ARC_ChemicalTypeData *)ARC_Hashtable_Get(chemical->currentGroup, (void *)energyString->data);
|
||||
ARC_String_Destroy(energyString);
|
||||
if(typeData == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return typeData->data;
|
||||
}
|
||||
|
||||
void *ARC_Chemical_GetWithCStr(ARC_Chemical *chemical, const char *energy){
|
||||
//create and copy into ARC_String
|
||||
ARC_String *energyString;
|
||||
ARC_String_CreateWithStrlen(&energyString, (char *)energy);
|
||||
|
||||
//get the return value
|
||||
void *returnValue = ARC_Chemical_Get(chemical, energyString);
|
||||
|
||||
//cleanup
|
||||
ARC_String_Destroy(energyString);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void ARC_Chemical_LoadFromString(ARC_Chemical *chemical, ARC_String **string){
|
||||
chemical->load = ARC_True;
|
||||
ARC_Parser_Parse(chemical->parser, string);
|
||||
}
|
||||
|
||||
void ARC_Chemical_LoadFromFile(ARC_Chemical *chemical, ARC_String *path){
|
||||
chemical->load = ARC_True;
|
||||
ARC_Parser_ParseFile(chemical->parser, path);
|
||||
}
|
||||
|
||||
void ARC_Chemical_UnloadFromString(ARC_Chemical *chemical, ARC_String **string){
|
||||
chemical->load = ARC_False;
|
||||
ARC_Parser_Parse(chemical->parser, string);
|
||||
}
|
||||
|
||||
void ARC_Chemical_UnloadFromFile(ARC_Chemical *chemical, ARC_String *path){
|
||||
chemical->load = ARC_False;
|
||||
ARC_Parser_ParseFile(chemical->parser, path);
|
||||
}
|
||||
|
||||
1254
src/std/config.c
1254
src/std/config.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue