Blame simple/bytebeat/lexer.c

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
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