/* * Copyright 2023 Oleg Borodin */ #include #include #include #include #include #include #define INIT_BSIZE 64 static char* strcopy(char* src) { size_t srcsize = strlen(src) + 1; char* dst = malloc(srcsize); memset(dst, '\0', srcsize); strcpy(dst, src); return dst; } void jparser_init(jparser_t * parser, jlexer_t * lexer) { parser->lexer = lexer; parser->kvalarr = malloc(sizeof(jkval_t) * INIT_BSIZE); parser->kvalcapa = INIT_BSIZE; parser->kvalsize = 0; } #define MAX_TOKEN_SIZE 1024 int jparser_parse(jparser_t * parser) { jlexer_t* lex = parser->lexer; char token[MAX_TOKEN_SIZE]; int type = 0; int pos = 0; char* key = ""; while ((type = jlexer_gettoken(lex, token)) != JLEXTOK_END) { switch (pos) { // POS 0 case 0:{ if (type != JLEXTOK_BLOCKB) { log_error("wrong block token: %s", token); return -1; } pos++; break; } // POS 1 case 1:{ if (type == JLEXTOK_SPACE) continue; if (type == JLEXTOK_NEXT) continue; if (type == JLEXTOK_BLOCKE) return 0; if (type != JLEXTOK_WORD) { log_error("wrong word token: %s", token); return -1; } key = strcopy(token); pos++; break; } // POS 2 case 2:{ if (type == JLEXTOK_SPACE) continue; if (type != JLEXTOK_SEPAR) { log_error("wrong delimeter token: %s", token); return -1; } pos++; break; } // POS 3 case 3:{ if (type == JLEXTOK_SPACE) continue; if (type != JLEXTOK_WORD && type != JLEXTOK_NUMB) { log_error("wrong delimeter token: %s", token); return -1; } char* val = strcopy(token); jkval_t* kv = &(parser->kvalarr[parser->kvalsize]); kv->key = key; if (type == JLEXTOK_NUMB) { kv->type = JVALTYPE_NUM; char* eptr = NULL; kv->num = (int64_t)strtol(val, &eptr, 10);; free(val); } else { kv->type = JVALTYPE_STR; kv->str = val; } parser->kvalsize++; pos++; break; } // POS 4 case 4:{ if (type == JLEXTOK_SPACE) continue; if (type != JLEXTOK_NEXT && type != JLEXTOK_BLOCKE) { log_error("wrong next token: %s", token); return -1; } pos = 1; break; } default:{ log_error("wrong parser stage: %s", token); return -1; } } } return 0; } int jparser_bind(jparser_t* parser, int type, char* key, void* ref) { for (int i = 0; i < parser->kvalsize; i++) { jkval_t* kv = &(parser->kvalarr[i]); if (strcmp(kv->key, key) == 0) { if (kv->type == JVALTYPE_STR) { *(char**)(ref) = strcopy(kv->str); } else if (kv->type == JVALTYPE_NUM) { *(int*)(ref) = kv->num; } return 0; } } return -1; } void jparser_destroy(jparser_t * parser) { free(parser->kvalarr); }