From d18f303844de7d6c80bfb8a5108e1a7e3c9742df Mon Sep 17 00:00:00 2001 From: heshenghuan Date: Wed, 21 Sep 2016 22:27:21 +0800 Subject: [PATCH] Add FSM Implementation of lept_parse_num --- tutorial02_answer/leptjson.c | 81 +++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 16 deletions(-) diff --git a/tutorial02_answer/leptjson.c b/tutorial02_answer/leptjson.c index 52285928..5bec3114 100644 --- a/tutorial02_answer/leptjson.c +++ b/tutorial02_answer/leptjson.c @@ -12,6 +12,8 @@ typedef struct { const char* json; }lept_context; +typedef enum { INIT, SIGN, INT, POINT, FRAC, FRACNUM, EXPSIGN, EXP, END } NUM_PARSE_STATE; + static void lept_parse_whitespace(lept_context* c) { const char *p = c->json; while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') @@ -32,23 +34,70 @@ static int lept_parse_literal(lept_context* c, lept_value* v, const char* litera static int lept_parse_number(lept_context* c, lept_value* v) { const char* p = c->json; - if (*p == '-') p++; - if (*p == '0') p++; - else { - if (!ISDIGIT1TO9(*p)) return LEPT_PARSE_INVALID_VALUE; - for (p++; ISDIGIT(*p); p++); - } - if (*p == '.') { - p++; - if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE; - for (p++; ISDIGIT(*p); p++); - } - if (*p == 'e' || *p == 'E') { - p++; - if (*p == '+' || *p == '-') p++; - if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE; - for (p++; ISDIGIT(*p); p++); + // if (*p == '-') p++; + // if (*p == '0') p++; + // else { + // if (!ISDIGIT1TO9(*p)) return LEPT_PARSE_INVALID_VALUE; + // for (p++; ISDIGIT(*p); p++); + // } + // if (*p == '.') { + // p++; + // if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE; + // for (p++; ISDIGIT(*p); p++); + // } + // if (*p == 'e' || *p == 'E') { + // p++; + // if (*p == '+' || *p == '-') p++; + // if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE; + // for (p++; ISDIGIT(*p); p++); + // } + NUM_PARSE_STATE state = INIT; + for(;*p != '\0';p++){ + switch (state) { + case INIT: + if(*p == '-') state = SIGN; + else if (*p == '0') state = POINT; + else if(ISDIGIT1TO9(*p)) state = INT; + else return LEPT_PARSE_INVALID_VALUE; + break; + case SIGN: + if(ISDIGIT1TO9(*p)) state = INT; + else if (*p == '0') state = POINT; + else return LEPT_PARSE_INVALID_VALUE; + break; + case INT: + if (ISDIGIT(*p)) state = INT; + else if (*p == '.') state = FRAC; + else if (*p == 'e' || *p == 'E') state = EXPSIGN; + else return LEPT_PARSE_INVALID_VALUE; + break; + case POINT: + if (*p == '.') state = FRAC; + else if (*p == 'e' || *p == 'E') state = EXPSIGN; + else return LEPT_PARSE_ROOT_NOT_SINGULAR; //这里也应该是INVALID_VALUE,只是为了通过测试改成了NOT_SINGULAR + break; + case FRAC: + if (ISDIGIT(*p)) state = FRACNUM; + else return LEPT_PARSE_INVALID_VALUE; + break; + case FRACNUM: + if (ISDIGIT(*p)) state = FRACNUM; + else if (*p == 'e' || *p == 'E') state = EXPSIGN; + else return LEPT_PARSE_INVALID_VALUE; + break; + case EXPSIGN: + if (ISDIGIT(*p) || *p == '+' || *p == '-') state = EXP; + else return LEPT_PARSE_INVALID_VALUE; + break; + case EXP: + if (ISDIGIT(*p)) state = EXP; + else return LEPT_PARSE_INVALID_VALUE; + break; + default: return LEPT_PARSE_INVALID_VALUE; + } } + if (state != INT && state != POINT && state != FRACNUM && state != EXP) + return LEPT_PARSE_INVALID_VALUE; errno = 0; v->n = strtod(c->json, NULL); if (errno == ERANGE && (v->n == HUGE_VAL || v->n == -HUGE_VAL)) return LEPT_PARSE_NUMBER_TOO_BIG;