|
|
744572 |
|
|
|
744572 |
#include <math.h></math.h>
|
|
|
744572 |
#include <ctype.h></ctype.h>
|
|
|
744572 |
#include <stdio.h></stdio.h>
|
|
|
744572 |
#include <stdlib.h></stdlib.h>
|
|
|
744572 |
#include <limits.h></limits.h>
|
|
|
744572 |
#include <string.h></string.h>
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
|
|
|
9e60e5 |
typedef int I32;
|
|
|
744572 |
typedef unsigned int U32;
|
|
|
744572 |
typedef float F32;
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
typedef enum {
|
|
|
744572 |
LT_NONE = 0,
|
|
|
744572 |
LT_KEY,
|
|
|
744572 |
LT_INT,
|
|
|
744572 |
LT_FLOAT,
|
|
|
744572 |
} LexType;
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
typedef struct {
|
|
|
744572 |
LexType type;
|
|
|
744572 |
union {
|
|
|
744572 |
U32 u;
|
|
|
744572 |
F32 f;
|
|
|
744572 |
};
|
|
|
744572 |
} Lex;
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
typedef struct {
|
|
|
744572 |
Lex *data;
|
|
|
744572 |
size_t size;
|
|
|
744572 |
} LexList;
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
const char **keys;
|
|
|
744572 |
int keysCnt;
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
static inline int iskey(const Lex *l, U32 k)
|
|
|
744572 |
{ return l && l->type == LT_KEY && l->u == k; }
|
|
|
744572 |
|
|
|
744572 |
static inline const char* skipSpaces(const char *s)
|
|
|
744572 |
{ while(isspace(*s)) ++s; return s; }
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
void lexPrint(const Lex *l, FILE *f) {
|
|
|
744572 |
if (!f) f = stdout;
|
|
|
744572 |
switch(l->type) {
|
|
|
744572 |
case LT_NONE:
|
|
|
744572 |
fprintf(f, "[none]");
|
|
|
744572 |
break;
|
|
|
744572 |
case LT_KEY:
|
|
|
744572 |
if (l->u < keysCnt) fprintf(f, "[key:%d:%s]", l->u, keys[l->u]);
|
|
|
744572 |
else fprintf(f, "[key:%d]", l->u);
|
|
|
744572 |
break;
|
|
|
744572 |
case LT_INT:
|
|
|
744572 |
fprintf(f, "[int:%x:%d]", l->u, l->u);
|
|
|
744572 |
break;
|
|
|
744572 |
case LT_FLOAT:
|
|
|
744572 |
fprintf(f, "[float:%x:%g]", l->u, l->f);
|
|
|
744572 |
break;
|
|
|
744572 |
default:
|
|
|
744572 |
fprintf(f, "[unknown:%u:%08x]", l->type, l->u);
|
|
|
744572 |
break;
|
|
|
744572 |
}
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
void lexChainPrint(const Lex *l, FILE *f) {
|
|
|
744572 |
do { lexPrint(l, f); } while((l++)->type);
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
int lexParseEnd(Lex *l, const char **p) {
|
|
|
744572 |
const char *s = skipSpaces(*p);
|
|
|
744572 |
if (*s) return 0;
|
|
|
744572 |
l->type = LT_NONE;
|
|
|
744572 |
*p = s;
|
|
|
744572 |
return 1;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
int lexParseKey(Lex *l, const char **p) {
|
|
|
744572 |
const char *s = skipSpaces(*p);
|
|
|
744572 |
size_t maxlen = 0;
|
|
|
744572 |
U32 key = 0;
|
|
|
744572 |
for(U32 i = 1; i < keysCnt; ++i) {
|
|
|
744572 |
size_t len = strlen(keys[i]);
|
|
|
744572 |
if (len > maxlen && 0 == strncmp(s, keys[i], len))
|
|
|
744572 |
{ key = i; maxlen = len; }
|
|
|
744572 |
}
|
|
|
744572 |
if (!key) return 0;
|
|
|
744572 |
l->type = LT_KEY;
|
|
|
744572 |
l->u = key;
|
|
|
744572 |
*p = s + maxlen;
|
|
|
744572 |
return 1;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
int lexParseNum(Lex *l, const char **p) {
|
|
|
744572 |
const char *s = skipSpaces(*p);
|
|
|
744572 |
const char *s0 = s;
|
|
|
744572 |
|
|
|
744572 |
U32 factor = 10;
|
|
|
744572 |
if (*s == '0') {
|
|
|
744572 |
++s;
|
|
|
744572 |
if (*s >= '0' && *s <= '7') factor = 8; else
|
|
|
744572 |
if (*s == 'x' || *s == 'X') { s0 = ++s; factor = 16; }
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
U32 iv = 0;
|
|
|
744572 |
double fv = 0;
|
|
|
744572 |
while(1) {
|
|
|
744572 |
U32 d = 0;
|
|
|
744572 |
if (*s >= '0' && *s <= '9') d = *s - '0'; else
|
|
|
744572 |
if (*s >= 'a' && *s <= 'f') d = *s - 'a' + 10; else
|
|
|
744572 |
if (*s >= 'A' && *s <= 'F') d = *s - 'A' + 10; else
|
|
|
744572 |
break;
|
|
|
744572 |
if (d >= factor) break;
|
|
|
744572 |
iv = iv*factor + d;
|
|
|
744572 |
fv = fv*factor + d;
|
|
|
744572 |
++s;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
int success = 0;
|
|
|
744572 |
if (s > s0) {
|
|
|
744572 |
l->type = LT_INT;
|
|
|
744572 |
l->u = iv;
|
|
|
744572 |
*p = s;
|
|
|
744572 |
success = 1;
|
|
|
744572 |
}
|
|
|
744572 |
if (factor != 10) return success;
|
|
|
744572 |
s0 = s;
|
|
|
744572 |
|
|
|
744572 |
if (*s == '.') {
|
|
|
744572 |
++s;
|
|
|
744572 |
double f = 1;
|
|
|
744572 |
while(*s >= '0' && *s <= '9')
|
|
|
744572 |
fv += (f *= 0.1)*(*s++ - '0');
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
if (s > s0 && (*s == 'e' || *s == 'E')) {
|
|
|
744572 |
double e = 0;
|
|
|
744572 |
double sign = (*s == '-' || *s == '+') && (*s++ == '-') ? -1 : 1;
|
|
|
744572 |
s0 = s;
|
|
|
744572 |
while(*s >= '0' && *s <= '9')
|
|
|
744572 |
e = e*10 + (*s++ - '0');
|
|
|
744572 |
fv *= pow(10, e*sign);
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
if (s <= s0) return success;
|
|
|
744572 |
if (*s == 'f') ++s;
|
|
|
744572 |
|
|
|
744572 |
l->type = LT_FLOAT;
|
|
|
744572 |
l->f = fv;
|
|
|
744572 |
*p = s;
|
|
|
744572 |
return 1;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
void lexListDeinit(LexList *ll)
|
|
|
744572 |
{ free(ll->data); memset(ll, 0, sizeof(*ll)); }
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Lex* lexListAdd(LexList *ll) {
|
|
|
744572 |
++ll->size;
|
|
|
744572 |
ll->data = (Lex*)realloc(ll->data, sizeof(*ll->data) * ll->size);
|
|
|
744572 |
if (!ll->data) { fprintf(stderr, "out of memory\n"); exit(1); }
|
|
|
744572 |
Lex *l = ll->data + ll->size - 1;
|
|
|
744572 |
memset(l, 0, sizeof(*l));
|
|
|
744572 |
return l;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
void lexListPrint(const LexList *ll, FILE *f) {
|
|
|
744572 |
if (!f) f = stdout;
|
|
|
744572 |
fprintf(f, "count %zu: ", ll->size);
|
|
|
744572 |
for(size_t i = 0; i < ll->size; ++i)
|
|
|
744572 |
lexPrint(ll->data + i, f);
|
|
|
744572 |
fprintf(f, "\n");
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
int lexListParse(LexList *ll, const char *s) {
|
|
|
744572 |
lexListDeinit(ll);
|
|
|
744572 |
Lex *l = lexListAdd(ll);
|
|
|
744572 |
while(1) {
|
|
|
744572 |
if (lexParseEnd(l, &s)) break;
|
|
|
744572 |
if (!lexParseKey(l, &s) && !lexParseNum(l, &s))
|
|
|
744572 |
{ fprintf(stderr, "lex parse error at: %s\n", s); return 0; }
|
|
|
744572 |
l = lexListAdd(ll);
|
|
|
744572 |
}
|
|
|
744572 |
return 1;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Lex* lexParse(const char *s) {
|
|
|
744572 |
LexList ll = {};
|
|
|
744572 |
lexListParse(&ll, s);
|
|
|
744572 |
return ll.data;
|
|
|
744572 |
}
|
|
|
744572 |
|