#include "parser.h"
#include "macros.h"
#include <ctype.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
#define JUSTDO(a) \
if (!(a)) { \
perror(#a); \
exit(1); \
}
array_t *STACK;
ht_t *WORD_TABLE;
char *INBUF;
parser_t *PARSER;
array_t *init_array(size_t size) {
array_t *a = calloc(1, sizeof(array_t));
a->size = 0;
a->capacity = size;
a->items = calloc(a->capacity, sizeof(value_t *));
return a;
}
void array_append(array_t *a, value_t *v) {
if (a->size >= a->capacity - 2) {
a->capacity = a->capacity * 2;
a->items = realloc(a->items, a->capacity * sizeof(value_t *));
}
a->items[a->size] = v;
a->size++;
}
value_t *array_pop(array_t *a) {
if (a->size > 0) {
value_t *v = a->items[a->size - 1];
a->size--;
return v;
}
return NULL;
}
void array_extend(array_t *a, array_t *b) {
for (int i = 0; i < b->size; i++) {
array_append(a, b->items[i]);
}
}
void array_free(array_t *a) {
for (int i = 0; i < a->size; i++) {
value_free(a->items[i]);
}
free(a->items);
free(a);
}
array_t *array_copy(array_t *a) {
array_t *b = calloc(1, sizeof(array_t));
b->size = a->size;
b->capacity = a->capacity;
b->items = calloc(b->capacity, sizeof(value_t *));
for (int i = 0; i < a->size; i++) {
b->items[i] = value_copy(a->items[i]);
}
return b;
}
value_t *init_value(int type) {
value_t *v = calloc(1, sizeof(value_t));
v->type = type;
v->escaped = false;
return v;
}
value_t *value_copy(value_t *v) {
value_t *a = init_value(VINT);
a->type = v->type;
if (v->type == VINT || v->type == VFLOAT) {
a->int_float = v->int_float;
} else if (v->type == VSTR || v->type == VWORD) {
a->str_word = string_copy(v->str_word);
} else if (v->type == VQUOTE) {
a->quote = array_copy(v->quote);
}
return a;
}
void value_free(value_t *v) {
if (v->type == VSTR || v->type == VWORD) {
string_free(v->str_word);
}
if (v->type == VQUOTE) {
array_free(v->quote);
}
free(v);
}
parser_t *init_parser(char *source) {
parser_t *p = calloc(1, sizeof(parser_t));
p->i = 0;
p->source = source;
p->c = source[0];
return p;
}
void parser_reset(parser_t *p, char *source) {
p->source = source;
p->i = 0;
p->c = source[0];
}
void parser_move(parser_t *p) {
if (p->i < strlen(p->source) && p->c != '\0') {
p->i++;
p->c = p->source[p->i];
}
}
void parser_skip_whitespace(parser_t *p) {
while (isspace(p->c)) {
parser_move(p);
}
}
value_t *parse_string(parser_t *p) {
value_t *retv = init_value(VSTR);
parser_move(p);
string_t *s = init_string(NULL);
while (p->c != '"' && p->c != '\0') {
string_append(s, p->c);
parser_move(p);
}
parser_move(p);
retv->str_word = s;
return retv;
}
value_t *parse_quote(parser_t *p) {
value_t *retv = init_value(VQUOTE);
retv->quote = init_array(10);
parser_move(p);
parser_skip_whitespace(p);
while (p->c != ']') {
array_append(retv->quote, parser_get_next(p));
parser_skip_whitespace(p);
}
parser_move(p);
return retv;
}
void parser_error(parser_t *p) { exit(1); }
value_t *parse_word(parser_t *p) {
value_t *retv = init_value(VWORD);
string_t *s = init_string(NULL);
if (p->c == '\\') {
retv->escaped = true;
parser_move(p);
if (isspace(p->c) || p->c == '\0') {
parser_error(p);
}
}
while (!isspace(p->c) && p->c != '\0') {
string_append(s, p->c);
parser_move(p);
}
retv->str_word = s;
return retv;
}
value_t *parse_num(parser_t *p) {
value_t *retv;
string_t *s = init_string(NULL);
bool is_float = false;
while (isdigit(p->c) || (p->c == '.') && !is_float) {
if (p->c == '.')
is_float = true;
string_append(s, p->c);
parser_move(p);
}
if (is_float)
retv = init_value(VFLOAT);
else
retv = init_value(VINT);
retv->int_float = atof(s->value);
string_free(s);
return retv;
}
value_t *parser_get_next(parser_t *p) {
parser_skip_whitespace(p);
if (isdigit(p->c)) {
return parse_num(p);
}
switch (p->c) {
case '"':
return parse_string(p);
case '[':
return parse_quote(p);
case '\0':
return NULL;
default:
return parse_word(p);
}
}
node_t *init_node(string_t *key, value_t *value) {
node_t *n = calloc(1, sizeof(node_t));
n->key = key;
n->value = v
|