Blame simple/bytebeat/lexer.c

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