|
CS456 - Systems Programming
| Displaying exercises/e7/solution/parse.c
#include "main.h"
extern int _line;
extern struct cur_tok _cur;
value_t *newvalue(value_dt type, void *value)
{
value_t *v = malloc(sizeof(value_t));
v->type = type;
v->any = value;
return v;
}
pair_t *newpair(char *name, value_t *v)
{
pair_t *p = malloc(sizeof(pair_t));
p->name = name;
p->v = *v;
p-> next = NULL;
return p;
}
value_t *parse_array(void)
{
long len = 0;
array_t *a = malloc(sizeof(array_t));
value_t *v;
a->length = 0;
a->a = NULL;
do {
// Putting this in here Allows a hanging , prior to ]:
if (accept(T_CBRAC)) return newvalue(DT_ARRAY, a);
if ((v = parse_value()) == NULL) return NULL;
if (a->length == 0) a->a = v;
else {
a->a = realloc(a->a, sizeof(value_t) * (a->length+1));
a->a[a->length] = *v;
}
a->length++;
} while (accept(T_COMMA));
if (accept(T_CBRAC)) return newvalue(DT_ARRAY, a);
fprintf(stderr,"Missing closing ] in input on line %d\n", _line);
return NULL;
}
pair_t *parse_pair(void)
{
char *name;
value_t *v;
// TODO: Add support for identifiers as keys:
if (_cur.tok != T_STRING) {
fprintf(stderr,"Invalid key in key/value pair on line %d\n", _line);
return NULL;
}
name = strdup(_cur.buf);
match(_cur.tok);
if (!accept(T_COLON)) {
fprintf(stderr,"Missing : in key/value pair on line %d\n", _line);
return NULL;
}
if ((v = parse_value()) == NULL) {
fprintf(stderr,"Missing value in key/value pair on line %d\n", _line);
return NULL;
}
return newpair(name, v);
}
value_t *parse_object(void)
{
pair_t *o = NULL, *p, *e;
do {
// Putting this here allows a hanging comma at end of object:
if (accept(T_CCBRACE)) return newvalue(DT_OBJECT, o);
if ((p = parse_pair()) == NULL) return NULL;
if (o == NULL) e = o = p;
else {
e->next = p;
e = p;
}
} while(accept(T_COMMA));
if (accept(T_CCBRACE)) return newvalue(DT_OBJECT, o);
fprintf(stderr,"Missing } for object on line %d\n", _line);
return NULL;
}
value_t *parse_value(void)
{
value_t *v;
switch(_cur.tok) {
case T_NUMBER:
v = newvalue(DT_NUMBER, NULL);
v->n = _cur.val;
match(_cur.tok);
return v;
case T_STRING:
v = newvalue(DT_STRING, strdup(_cur.buf));
match(_cur.tok);
return v;
case T_TRUE:
match(_cur.tok);
return newvalue(DT_TRUE, NULL);
case T_FALSE:
match(_cur.tok);
return newvalue(DT_FALSE, NULL);
case T_NULL:
match(_cur.tok);
return newvalue(DT_NULL, NULL);
case T_OBRAC:
match(_cur.tok);
return parse_array();
case T_OCBRACE:
match(_cur.tok);
return parse_object();
default:
fprintf(stderr,"Unknown token %d on line %d\n", _cur.tok, _line);
return NULL;
}
}
|