Remove parsing dependance on null terminator

This commit is contained in:
rexy712
2020-03-14 09:21:57 -07:00
parent cc372b2941
commit e38245261e

View File

@@ -30,7 +30,7 @@
#define RJP_INITIAL_PARSE_DEPTH 16
#define rjp_lex_accept 1
typedef enum RJP_lex_node{
typedef enum RJP_lex_category{
rjp_lex_start = 0,
rjp_lex_obracket = 3,
rjp_lex_obrace = 5,
@@ -65,31 +65,12 @@ typedef enum RJP_lex_node{
rjp_lex_signed_number = 49,
rjp_lex_sci_num_signed = 51,
rjp_lex_newlines = 53,
rjp_lex_block_comment = 55,
rjp_lex_block_comment_start = 54,
rjp_lex_block_comment_end1 = 56,
rjp_lex_block_comment_end2 = 57,
rjp_lex_block_comment = 57,
rjp_lex_invalid = 1000,
rjp_lex_unrecognized_word = 1002
}RJP_lex_node;
typedef enum RJP_lex_category{
rjp_lexcat_invalid,
rjp_lexcat_obrace,
rjp_lexcat_cbrace,
rjp_lexcat_obracket,
rjp_lexcat_cbracket,
rjp_lexcat_space,
rjp_lexcat_newline,
rjp_lexcat_string,
rjp_lexcat_colon,
rjp_lexcat_comma,
rjp_lexcat_integer,
rjp_lexcat_float,
rjp_lexcat_scientific,
rjp_lexcat_true,
rjp_lexcat_false,
rjp_lexcat_null,
rjp_lexcat_comment,
rjp_lex_unrecognized_word = 1002,
rjp_lex_end = 1004,
}RJP_lex_category;
typedef enum RJP_yacc_target{
@@ -107,7 +88,7 @@ typedef enum RJP_yacc_target{
typedef struct RJP_lex_state{
const char* str;
RJP_lex_node node;
RJP_lex_category node;
RJP_index length;
RJP_index offset;
}RJP_lex_state;
@@ -164,7 +145,7 @@ static RJP_lex_category irjp_lex_accept(RJP_lex_category val, RJP_lex_state* sta
return val;
}
static RJP_lex_category irjp_lex_error(RJP_lex_state* state){
return irjp_lex_accept(rjp_lexcat_invalid, state);
return irjp_lex_accept(rjp_lex_invalid, state);
}
static RJP_lex_category irjp_lex(RJP_lex_state* state){
state->offset += state->length;
@@ -203,31 +184,33 @@ static RJP_lex_category irjp_lex(RJP_lex_state* state){
state->node = rjp_lex_n;
else if(ch == '/')
state->node = rjp_lex_slash;
else if(ch == 0)
return irjp_lex_accept(rjp_lex_end, state);
else
state->node = rjp_lex_invalid;
break;
//punctuation
case rjp_lex_obracket:
return irjp_lex_accept(rjp_lexcat_obracket, state);
return irjp_lex_accept(rjp_lex_obracket, state);
case rjp_lex_obrace:
return irjp_lex_accept(rjp_lexcat_obrace, state);
return irjp_lex_accept(rjp_lex_obrace, state);
case rjp_lex_cbracket:
return irjp_lex_accept(rjp_lexcat_cbracket, state);
return irjp_lex_accept(rjp_lex_cbracket, state);
case rjp_lex_cbrace:
return irjp_lex_accept(rjp_lexcat_cbrace, state);
return irjp_lex_accept(rjp_lex_cbrace, state);
case rjp_lex_comma:
return irjp_lex_accept(rjp_lexcat_comma, state);
return irjp_lex_accept(rjp_lex_comma, state);
case rjp_lex_colon:
return irjp_lex_accept(rjp_lexcat_colon, state);
return irjp_lex_accept(rjp_lex_colon, state);
//whitespace
case rjp_lex_newlines:
return irjp_lex_accept(rjp_lexcat_newline, state);
return irjp_lex_accept(rjp_lex_newlines, state);
case rjp_lex_spaces:
if(isspace(ch))
break;
return irjp_lex_accept(rjp_lexcat_space, state);
return irjp_lex_accept(rjp_lex_spaces, state);
//numbers
case rjp_lex_signed_number:
@@ -244,7 +227,7 @@ static RJP_lex_category irjp_lex(RJP_lex_state* state){
else if(isalpha(ch))
state->node = rjp_lex_unrecognized_word;
else
return irjp_lex_accept(rjp_lexcat_integer, state);
return irjp_lex_accept(rjp_lex_number, state);
}
break;
case rjp_lex_decimal:
@@ -261,7 +244,7 @@ static RJP_lex_category irjp_lex(RJP_lex_state* state){
else if(isalpha(ch))
state->node = rjp_lex_unrecognized_word;
else
return irjp_lex_accept(rjp_lexcat_float, state);
return irjp_lex_accept(rjp_lex_fnumber, state);
break;
case rjp_lex_fnum_e:
if(ch == '-' || ch == '+')
@@ -283,7 +266,7 @@ static RJP_lex_category irjp_lex(RJP_lex_state* state){
else if(isalpha(ch))
state->node = rjp_lex_unrecognized_word;
else
return irjp_lex_accept(rjp_lexcat_scientific, state);
return irjp_lex_accept(rjp_lex_sci_num, state);
break;
//strings
@@ -299,33 +282,33 @@ static RJP_lex_category irjp_lex(RJP_lex_state* state){
state->node = rjp_lex_quote;
break;
case rjp_lex_string:
return irjp_lex_accept(rjp_lexcat_string, state);
return irjp_lex_accept(rjp_lex_string, state);
//comments
case rjp_lex_slash:
if(ch == '/')
state->node = rjp_lex_line_comment;
else if(ch == '*')
state->node = rjp_lex_block_comment;
state->node = rjp_lex_block_comment_start;
else
state->node = rjp_lex_invalid;
break;
case rjp_lex_line_comment:
if(ch == '\n' || ch == '\r' || ch == 0) //don't consume this character
return irjp_lex_accept(rjp_lexcat_comment, state);
return irjp_lex_accept(rjp_lex_line_comment, state);
break;
case rjp_lex_block_comment:
case rjp_lex_block_comment_start:
if(ch == '*')
state->node = rjp_lex_block_comment_end1;
break;
case rjp_lex_block_comment_end1:
if(ch == '/')
state->node = rjp_lex_block_comment_end2;
else
state->node = rjp_lex_block_comment;
else
state->node = rjp_lex_block_comment_start;
break;
case rjp_lex_block_comment_end2:
return irjp_lex_accept(rjp_lexcat_comment, state);
case rjp_lex_block_comment:
return irjp_lex_accept(rjp_lex_block_comment, state);
//true
case rjp_lex_t:
@@ -348,7 +331,7 @@ static RJP_lex_category irjp_lex(RJP_lex_state* state){
break;
case rjp_lex_true:
if(!isalnum(ch))
return irjp_lex_accept(rjp_lexcat_true, state);
return irjp_lex_accept(rjp_lex_true, state);
else
state->node = rjp_lex_unrecognized_word;
break;
@@ -380,7 +363,7 @@ static RJP_lex_category irjp_lex(RJP_lex_state* state){
break;
case rjp_lex_false:
if(!isalnum(ch))
return irjp_lex_accept(rjp_lexcat_false, state);
return irjp_lex_accept(rjp_lex_false, state);
state->node = rjp_lex_unrecognized_word;
break;
@@ -405,7 +388,7 @@ static RJP_lex_category irjp_lex(RJP_lex_state* state){
break;
case rjp_lex_null:
if(!isalnum(ch))
return irjp_lex_accept(rjp_lexcat_null, state);
return irjp_lex_accept(rjp_lex_null, state);
state->node = rjp_lex_unrecognized_word;
break;
@@ -421,7 +404,7 @@ static RJP_lex_category irjp_lex(RJP_lex_state* state){
if(ch == 0)
break;
}
return irjp_lex_error(state);
return irjp_lex_accept(state->node, state);
}
static int irjp_init_value(RJP_value* newval, RJP_lex_category cat, RJP_yacc_state* state){
@@ -429,7 +412,7 @@ static int irjp_init_value(RJP_value* newval, RJP_lex_category cat, RJP_yacc_sta
RJP_index offset = state->lexstate.offset;
const char* str = state->lexstate.str + offset;
switch(cat){
case rjp_lexcat_string:;
case rjp_lex_string:;
RJP_index newlength;
newval->type = rjp_json_string;
newval->string.value = irjp_convert_string(str, length, &newlength);
@@ -437,32 +420,32 @@ static int irjp_init_value(RJP_value* newval, RJP_lex_category cat, RJP_yacc_sta
return 1;
newval->string.length = newlength;
break;
case rjp_lexcat_integer:
case rjp_lex_number:
newval->type = rjp_json_integer;
newval->integer = strtoll(str, NULL, 10);
break;
case rjp_lexcat_float:
case rjp_lexcat_scientific:
case rjp_lex_fnumber:
case rjp_lex_sci_num:
newval->type = rjp_json_dfloat;
newval->dfloat = strtod(str, NULL);
break;
case rjp_lexcat_true:
case rjp_lex_true:
newval->type = rjp_json_boolean;
newval->boolean = 1;
break;
case rjp_lexcat_false:
case rjp_lex_false:
newval->type = rjp_json_boolean;
newval->boolean = 0;
break;
case rjp_lexcat_null:
case rjp_lex_null:
newval->type = rjp_json_null;
break;
case rjp_lexcat_obrace:
case rjp_lex_obrace:
newval->type = rjp_json_object;
irjp_yacc_stack_push(&state->target_stack, rjp_yacc_first_mem_key);
state->curr = state->lastadded;
break;
case rjp_lexcat_obracket:
case rjp_lex_obracket:
newval->type = rjp_json_array;
irjp_yacc_stack_push(&state->target_stack, rjp_yacc_arr_first_value);
state->curr = state->lastadded;
@@ -488,8 +471,8 @@ static RJP_value* irjp_add_value_to_object(RJP_yacc_state* state, const char* ke
static RJP_lex_category irjp_convert_comment(_Bool allow_comments){
if(allow_comments)
return rjp_lexcat_space;
return rjp_lexcat_invalid;
return rjp_lex_spaces;
return rjp_lex_invalid;
}
static void irjp_init_parse_state(RJP_yacc_state* state, const char* str){
@@ -514,31 +497,18 @@ static void irjp_delete_parse_state(RJP_yacc_state* state){
return RJP_PARSE_STATUS_ERR; \
}while(0)
static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_yacc_state* state);
static int irjp_parse(RJP_yacc_state* state){
RJP_lex_category cat;
for(;state->lexstate.str[state->lexstate.offset+state->lexstate.length];state->row += state->lexstate.length){
cat = irjp_lex(&state->lexstate);
if(irjp_parse_handle_lexcat(cat, state) != RJP_PARSE_STATUS_SUC)
return RJP_PARSE_STATUS_ERR;
}
if(state->target_stack.position != 0)
irjp_parse_error("Missing closing brace");
return RJP_PARSE_STATUS_SUC;
}
static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_yacc_state* state){
if(cat == rjp_lexcat_comment)
if(cat == rjp_lex_line_comment || cat == rjp_lex_block_comment)
cat = irjp_convert_comment(state->allow_comments);
if(cat == rjp_lexcat_space)
if(cat == rjp_lex_spaces)
return RJP_PARSE_STATUS_SUC;
if(cat == rjp_lexcat_newline){
if(cat == rjp_lex_newlines){
state->row = 1;
++(state->column);
return RJP_PARSE_STATUS_SUC;
}
if(cat == rjp_lexcat_invalid)
if(cat == rjp_lex_invalid)
irjp_parse_error("Invalid token");
switch(irjp_yacc_stack_current(&state->target_stack)){
@@ -550,13 +520,13 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_yacc_state* state)
}
break;
case rjp_yacc_first_mem_key:
if(cat == rjp_lexcat_cbrace){
if(cat == rjp_lex_cbrace){
irjp_yacc_stack_pop(&state->target_stack);
state->curr = state->curr->parent;
}else{
//fallthrough
case rjp_yacc_mem_key:
if(cat == rjp_lexcat_string){
if(cat == rjp_lex_string){
irjp_yacc_stack_set(&state->target_stack, rjp_yacc_key_colon);
if(!irjp_add_value_to_object(state, state->lexstate.str+state->lexstate.offset, state->lexstate.length)){
irjp_parse_error("Expected member key");
@@ -567,7 +537,7 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_yacc_state* state)
}
break;
case rjp_yacc_arr_first_value:
if(cat == rjp_lexcat_cbracket){
if(cat == rjp_lex_cbracket){
irjp_yacc_stack_pop(&state->target_stack);
state->curr = state->curr->parent;
}else{
@@ -580,7 +550,7 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_yacc_state* state)
break;
case rjp_yacc_key_colon:
if(cat != rjp_lexcat_colon)
if(cat != rjp_lex_colon)
irjp_parse_error("Expected member key");
irjp_yacc_stack_set(&state->target_stack, rjp_yacc_obj_value);
break;
@@ -591,9 +561,9 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_yacc_state* state)
}
break;
case rjp_yacc_obj_comma:
if(cat == rjp_lexcat_comma){
if(cat == rjp_lex_comma){
irjp_yacc_stack_set(&state->target_stack, state->allow_trail_comma ? rjp_yacc_first_mem_key : rjp_yacc_mem_key);
}else if(cat == rjp_lexcat_cbrace){
}else if(cat == rjp_lex_cbrace){
irjp_yacc_stack_pop(&state->target_stack);
state->curr = state->curr->parent;
}else{
@@ -602,9 +572,9 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_yacc_state* state)
break;
case rjp_yacc_arr_comma:
if(cat == rjp_lexcat_comma){
if(cat == rjp_lex_comma){
irjp_yacc_stack_set(&state->target_stack, state->allow_trail_comma ? rjp_yacc_arr_first_value : rjp_yacc_arr_value);
}else if(cat == rjp_lexcat_cbracket){
}else if(cat == rjp_lex_cbracket){
irjp_yacc_stack_pop(&state->target_stack);
state->curr = state->curr->parent;
}else{
@@ -618,6 +588,18 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_yacc_state* state)
};
return RJP_PARSE_STATUS_SUC;
}
static int irjp_parse(RJP_yacc_state* state){
RJP_lex_category cat;
for(cat = irjp_lex(&state->lexstate);cat & rjp_lex_accept;cat = irjp_lex(&state->lexstate),state->row += state->lexstate.length){
if(irjp_parse_handle_lexcat(cat, state) != RJP_PARSE_STATUS_SUC)
return RJP_PARSE_STATUS_ERR;
}
if(state->target_stack.position != 0)
irjp_parse_error("Missing closing brace");
if(cat == rjp_lex_end)
return RJP_PARSE_STATUS_SUC;
irjp_parse_error("Invalid Token");
}
RJP_value* rjp_parse(const char* str, int flags){
RJP_yacc_state state = {.allow_comments = (flags & RJP_PARSE_ALLOW_COMMENTS),
.allow_trail_comma = (flags & RJP_PARSE_ALLOW_TRAILING_COMMA)