commit 6ca1543204da40e7a8d07d0b498c490717c5c12c
parent 49f17958c9de9ec29319a5b9535787ae095e05db
Author: William Casarin <jb55@jb55.com>
Date: Tue, 30 Jun 2020 12:22:57 -0700
parsing working
Diffstat:
4 files changed, 247 insertions(+), 129 deletions(-)
diff --git a/parse.c b/parse.c
@@ -6,7 +6,12 @@
#include <stdlib.h>
#include <assert.h>
+#ifdef DEBUG
#define tokdebug printf
+#else
+#define tokdebug(...)
+#define print_spaces(...)
+#endif
enum known_symbol {
S_OBJECT,
@@ -52,11 +57,12 @@ void make_cursor(u8 *start, u8 *end, struct cursor *cursor)
memset(&cursor->err_data, 0, sizeof(cursor->err_data));
}
-static int cursor_index(struct cursor *cursor, int elem_size)
+int cursor_index(struct cursor *cursor, int elem_size)
{
return (cursor->p - cursor->start) / elem_size;
}
+#ifdef DEBUG
static const char *attr_type_str(enum attribute_type type)
{
switch (type) {
@@ -74,7 +80,7 @@ static const char *attr_type_str(enum attribute_type type)
return "unknown";
}
-
+#endif
static const char *token_error_string(enum token_error err)
{
@@ -103,6 +109,8 @@ static const char *token_type_str(enum token_type type)
case T_NUMBER: return "number";
}
+ printf("UNUSUAL: unknown token_type %d\n", type);
+
return "unknown";
}
@@ -138,7 +146,7 @@ void print_token_error(struct cursor *cursor)
static int pull_byte(struct cursor *cursor, u8 *c)
{
- if (cursor->p + 1 >= cursor->end)
+ if (cursor->p + 1 > cursor->end)
return 0;
*c = *cursor->p;
@@ -196,19 +204,23 @@ static int push_u16(struct cursor *cursor, u16 i)
return push_data(cursor, (u8*)&i, sizeof(i));
}
+#ifdef DEBUG
static void print_spaces(int n)
{
int i;
for (i = 0; i < n; i++)
putchar(' ');
}
+#endif
static int push_token_data(struct cursor *tokens,
enum token_type token,
void *token_data, int token_data_size)
{
static int depth = 0;
+#ifdef DEBUG
struct tok_str *str;
+#endif
int ok;
ok = push_byte(tokens, token);
if (!ok) return 0;
@@ -228,6 +240,7 @@ static int push_token_data(struct cursor *tokens,
/* fallthrough */
case T_STRING:
+#ifdef DEBUG
print_spaces(depth*2);
str = (struct tok_str*)token_data;
if (token == T_STRING) {
@@ -237,9 +250,12 @@ static int push_token_data(struct cursor *tokens,
} else {
tokdebug("sym %.*s", str->len, str->data);
}
+#endif
ok = push_data(tokens, token_data, token_data_size);
if (!ok) return 0;
+#ifdef DEBUG
printf("\n");
+#endif
break;
}
@@ -631,6 +647,7 @@ static int pull_token(struct cursor *tokens,
return 1;
}
+#ifdef DEBUG
static void print_token_data(union token *token, enum token_type type)
{
switch (type) {
@@ -677,6 +694,7 @@ static void print_current_token(struct cursor *tokens)
print_token_data(&token, type);
printf("\n");
}
+#endif
/*
* PARSING
@@ -715,11 +733,6 @@ static int pull_symbol_token(struct cursor *tokens, struct tok_str *str)
return parse_stringy_token(tokens, str, T_SYMBOL);
}
-static int pull_string_token(struct cursor *tokens, struct tok_str *str)
-{
- return parse_stringy_token(tokens, str, T_STRING);
-}
-
static int pull_number_token(struct cursor *tokens, struct tok_str *str)
{
return parse_stringy_token(tokens, str, T_NUMBER);
@@ -745,6 +758,31 @@ static int parse_number(struct cursor *tokens, union number *number)
return 1;
}
+static void *index_cursor(struct cursor *cursor, u16 index, int elem_size)
+{
+ u8 *p;
+ p = &cursor->start[elem_size * index];
+
+ if (p > cursor->end)
+ return NULL;
+
+ return (void*)p;
+}
+
+
+static struct attribute *get_attr(struct cursor *attributes, u16 index)
+{
+ return (struct attribute*)index_cursor(attributes, index,
+ sizeof(struct attribute));
+}
+
+struct cell *get_cell(struct cursor *cells, u16 index)
+{
+ return (struct cell*)index_cursor(cells, index,
+ sizeof(struct cell));
+}
+
+
static int memeq(void *buf, int buf_len, void *buf2, int buf2_len)
{
if (buf_len != buf2_len)
@@ -803,25 +841,31 @@ static int parse_shape(struct cursor *tokens, struct attribute *attr)
return 1;
}
-static int parse_name(struct cursor *tokens, struct attribute *attr)
+static int parse_str_attr(struct cursor *tokens,
+ struct attribute *attr,
+ const char *sym,
+ enum attribute_type type,
+ enum token_type tok_type)
{
struct cursor temp;
struct tok_str str;
int ok;
+ assert(tok_type == T_NUMBER || tok_type == T_SYMBOL || tok_type == T_STRING);
+
copy_cursor(tokens, &temp);
- ok = parse_symbol(&temp, "name");
+ ok = parse_symbol(&temp, sym);
if (!ok) return 0;
- ok = pull_string_token(&temp, &str);
+ ok = parse_stringy_token(&temp, &str, tok_type);
if (!ok) return 0;
attr->data.str.ptr = (char*)str.data;
attr->data.str.len = str.len;
- attr->type = A_NAME;
+ attr->type = type;
- printf("attribute name %.*s\n", str.len, str.data);
+ tokdebug("attribute %s %.*s\n", sym, str.len, str.data);
copy_cursor(&temp, tokens);
@@ -850,14 +894,34 @@ static int parse_size(struct cursor *tokens, struct attribute *attr)
ok = parse_number(&temp, &attr->data.number);
if (!ok) return 0;
- printf("attribute %s %d\n", attr_type_str(attr->type),
- attr->data.number.integer);
+ tokdebug("attribute %s %d\n",
+ attr_type_str(attr->type),
+ attr->data.number.integer);
copy_cursor(&temp, tokens);
return 1;
}
+int cell_name(struct cursor *attributes, struct cell *cell, const char** name, int *len)
+{
+ int i;
+ struct attribute *attr;
+ *len = 0;
+ *name = "";
+
+ for (i = 0; i < cell->n_attributes; i++) {
+ attr = get_attr(attributes, cell->attributes[i]);
+ if (attr->type == A_NAME) {
+ *name = attr->data.str.ptr;
+ *len = attr->data.str.len;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static int parse_attribute(struct cursor *tokens, struct attribute *attr)
{
int ok;
@@ -871,7 +935,22 @@ static int parse_attribute(struct cursor *tokens, struct attribute *attr)
ok = parse_shape(&temp, attr);
if (ok) goto close;
- ok = parse_name(&temp, attr);
+ ok = parse_str_attr(&temp, attr, "id", A_ID, T_SYMBOL);
+ if (ok) goto close;
+
+ ok = parse_str_attr(&temp, attr, "name", A_NAME, T_STRING);
+ if (ok) {
+ goto close;
+ }
+
+ ok = parse_str_attr(&temp, attr, "material", A_MATERIAL, T_SYMBOL);
+ if (ok) goto close;
+
+ /* TODO: parse multiple conditions */
+ ok = parse_str_attr(&temp, attr, "condition", A_CONDITION, T_SYMBOL);
+ if (ok) goto close;
+
+ ok = parse_str_attr(&temp, attr, "location", A_LOCATION, T_SYMBOL);
if (ok) goto close;
ok = parse_size(&temp, attr);
@@ -940,17 +1019,22 @@ static int parse_group(struct cursor *tokens)
*/
-static int parse_cell(struct cursor *tokens,
- struct cursor *attributes,
- struct cursor *cells,
- u16 *index);
-
static int push_cell(struct cursor *cells, struct cell *cell, u16 *cell_index)
{
int index;
int ok;
+ static int group_count = 0;
+
+ if (cell->type == C_GROUP)
+ group_count++;
+
+ assert(group_count != 2);
+
+ tokdebug("push_cell %s\n", cell_type_str(cell->type));
+
index = cursor_index(cells, sizeof(cell));
+
if (index > 0xFFFF) {
/* TODO: actual error message here */
printf("push_cell_child overflow\n");
@@ -966,20 +1050,25 @@ static int push_cell(struct cursor *cells, struct cell *cell, u16 *cell_index)
return 1;
}
-static int push_child_cell(struct cursor *cells, struct cell *parent, struct cell *child)
+static void copy_parser(struct parser *from, struct parser *to)
+{
+ to->tokens = from->tokens;
+ to->cells = from->cells;
+ to->attributes = from->attributes;
+}
+
+static int push_cell_child(struct cell *parent, u16 child_ind)
{
int ok;
- u16 index;
struct cursor child_inds;
- ok = push_cell(cells, child, &index);
- if (!ok) return 0;
-
make_cursor((u8*)parent->children,
(u8*)parent->children + sizeof(parent->children),
&child_inds);
- ok = push_u16(&child_inds, index);
+ child_inds.p += parent->n_children * sizeof(parent->children[0]);
+
+ ok = push_u16(&child_inds, child_ind);
if (!ok) return 0;
parent->n_children++;
@@ -987,20 +1076,19 @@ static int push_child_cell(struct cursor *cells, struct cell *parent, struct cel
return 1;
}
-static struct cell *get_cell(struct cursor *cells, u16 index)
+const char *cell_type_str(enum cell_type type)
{
- struct cell *p;
-
- p = (struct cell *)cells->start;
- p = &p[index];
-
- if ((u8*)p > (u8*)cells->end)
- return NULL;
+ switch (type) {
+ case C_GROUP: return "group";
+ case C_SPACE: return "space";
+ case C_OBJECT: return "object";
+ case C_ROOM: return "room";
+ }
- return p;
+ return "unknown";
}
-static int parse_cell_attrs(struct cursor *tokens, struct cursor *attributes, struct cursor *cells, u16 *index)
+static int parse_cell_attrs(struct parser *parser, u16 *index, enum cell_type type)
{
struct cursor cell_attr_inds;
struct cell *child_cell;
@@ -1019,9 +1107,11 @@ static int parse_cell_attrs(struct cursor *tokens, struct cursor *attributes, st
/* 0 attributes returns 1, 1 attrs returns 2, etc
0 is a real error, an attribute push overflow */
- ok = parse_attributes(tokens, attributes, attr_inds);
+ ok = parse_attributes(parser->tokens, parser->attributes, attr_inds);
if (!ok) return 0;
+ tokdebug("parse_attributes %d\n", ok);
+
for (i = attr_inds[0]; i <= attr_inds[1]; i++) {
ok = push_int(&cell_attr_inds, i);
cell.n_attributes++;
@@ -1029,162 +1119,156 @@ static int parse_cell_attrs(struct cursor *tokens, struct cursor *attributes, st
}
/* Optional child cell */
- ok = parse_cell(tokens, attributes, cells, &child_cell_index);
+ tokdebug("optional child cell in parse_cell_attrs\n");
+ ok = parse_cell(parser, &child_cell_index);
if (ok) {
- child_cell = get_cell(cells, child_cell_index);
- ok = push_child_cell(cells, &cell, child_cell);
+ child_cell = get_cell(parser->cells, child_cell_index);
+ if (!child_cell) return 0;
+ tokdebug("parse_cell_attrs push child cell\n");
+ ok = push_cell_child(&cell, child_cell_index);
if (!ok) return 0;
+
+ }
+ else {
+ tokdebug("no child cells found\n");
}
- ok = push_cell(cells, &cell, index);
+ cell.type = type;
+ ok = push_cell(parser->cells, &cell, index);
if (!ok) return 0;
return 1;
}
-static int parse_cell_by_name(struct cursor *tokens,
- struct cursor *attributes,
- struct cursor *cells,
+
+static int parse_cell_by_name(struct parser *parser,
u16 *index,
const char *name,
enum cell_type type)
{
int ok;
struct cursor temp;
- struct cell *cell;
+ struct parser backtracked;
u16 ind;
- copy_cursor(tokens, &temp);
+ copy_cursor(parser->tokens, &temp);
+ copy_parser(parser, &backtracked);
+ backtracked.tokens = &temp;
ok = parse_symbol(&temp, name);
if (!ok) return 0;
- ok = parse_cell_attrs(&temp, attributes, cells, &ind);
+ ok = parse_cell_attrs(&backtracked, &ind, type);
if (!ok) return 0;
- cell = get_cell(cells, ind);
-
if (index)
*index = ind;
- if (!cell) return 0;
- cell->type = type;
-
- copy_cursor(&temp, tokens);
+ copy_cursor(&temp, parser->tokens);
return 1;
}
-static int parse_room(struct cursor *tokens,
- struct cursor *attributes,
- struct cursor *cells,
- u16 *index)
+static int parse_room(struct parser *parser, u16 *index)
{
- return parse_cell_by_name(tokens, attributes, cells, index, "room", C_SPACE);
+ return parse_cell_by_name(parser, index, "room", C_ROOM);
}
-static int parse_group(struct cursor *tokens,
- struct cursor *attributes,
- struct cursor *cells,
- u16 *index)
+static int parse_group(struct parser *parser, u16 *index)
{
int ok;
- int ncells = 0
-;
+ int ncells = 0;
+ u16 child_ind;
+
+ struct parser backtracked;
struct cursor temp;
- struct cell group, child_cell;
+ struct cell group;
+ struct cell *child_cell;
init_cell(&group);
- init_cell(&child_cell);
- copy_cursor(tokens, &temp);
+ copy_cursor(parser->tokens, &temp);
+ copy_parser(parser, &backtracked);
+ backtracked.tokens = &temp;
ok = parse_symbol(&temp, "group");
if (!ok) return 0;
while (1) {
- printf("parsing group cell\n");
- ok = parse_cell(&temp, attributes, cells, NULL);
+ ok = parse_cell(&backtracked, &child_ind);
if (!ok) break;
- ok = push_child_cell(cells, &group, &child_cell);
+ child_cell = get_cell(parser->cells, child_ind);
+ if (child_cell == NULL) {
+ printf("UNUSUAL: group get_cell was NULL\n");
+ return 0;
+ }
+
+ tokdebug("group child cell type %s\n", cell_type_str(child_cell->type));
+ ok = push_cell_child(&group, child_ind);
if (!ok) return 0;
ncells++;
}
- printf("ncells %d\n", ncells);
+ tokdebug("parse_group cells %d\n", ncells);
if (ncells == 0)
return 0;
group.type = C_GROUP;
- ok = push_cell(cells, &group, index);
+ ok = push_cell(parser->cells, &group, index);
if (!ok) return 0;
- copy_cursor(&temp, tokens);
+ copy_cursor(&temp, parser->tokens);
return ncells;
}
-static int parse_object(struct cursor *tokens,
- struct cursor *attributes,
- struct cursor *cells,
- u16 *index)
+static int parse_object(struct parser *parser, u16 *index)
{
- return parse_cell_by_name(tokens, attributes, cells, index, "table", C_OBJECT);
+ return parse_cell_by_name(parser, index, "table", C_OBJECT);
}
-static int parse_cell(struct cursor *tokens,
- struct cursor *attributes,
- struct cursor *cells,
- u16 *index)
+int parse_cell(struct parser *parser, u16 *index)
{
int ok;
- ok = parse_open(tokens);
- if (!ok) return 0;
+ struct cursor temp;
+ struct parser backtracked;
- ok = parse_group(tokens, attributes, cells, index);
- if (ok) {
- printf("got parse_group\n");
- goto close;
+ /* mostly needed for parse_open and parse_close */
+ copy_cursor(parser->tokens, &temp);
+ copy_parser(parser, &backtracked);
+ backtracked.tokens = &temp;
+
+ ok = parse_open(&temp);
+ if (!ok) {
+ tokdebug("parse_open failed in parse_cell\n");
+ return 0;
}
- ok = parse_room(tokens, attributes, cells, index);
+ ok = parse_group(&backtracked, index);
if (ok) {
- printf("got parse_room\n");
+ tokdebug("got parse_group\n");
goto close;
}
- ok = parse_object(tokens, attributes, cells, index);
+ ok = parse_room(&backtracked, index);
if (ok) {
- printf("got parse_object\n");
+ tokdebug("got parse_room\n");
goto close;
}
+ ok = parse_object(&backtracked, index);
+ if (ok) goto close;
+
return 0;
close:
- print_current_token(tokens);
- ok = parse_close(tokens);
- printf("parse_close cell %d\n", ok);
- if (!ok) return 0;
-
- /* ok = parse_object(tokens, cell); */
-
- return 1;
-}
-
-int parse_cells(struct cursor *tokens,
- struct cursor *attributes,
- struct cursor *cells)
-{
- int ok;
-
-
- ok = parse_cell(tokens, attributes, cells, NULL);
+ ok = parse_close(&temp);
if (!ok) return 0;
+ copy_cursor(&temp, parser->tokens);
return 1;
}
diff --git a/parse.h b/parse.h
@@ -22,6 +22,7 @@ enum token_error {
enum cell_type {
C_GROUP,
C_SPACE,
+ C_ROOM,
C_OBJECT,
};
@@ -56,17 +57,19 @@ struct tok_str {
int len;
};
-union cursor_err {
- struct {
- struct tok_str expected;
- struct tok_str got;
- } symbol;
- struct {
- enum token_type expected;
- enum token_type got;
- } lex;
+struct cursor_err {
+ union {
+ struct {
+ struct tok_str expected;
+ struct tok_str got;
+ } symbol;
+ struct {
+ enum token_type expected;
+ enum token_type got;
+ } lex;
+ char c;
+ };
int pos;
- char c;
};
struct cursor {
@@ -74,7 +77,7 @@ struct cursor {
u8 *p;
u8 *end;
enum token_error err;
- union cursor_err err_data;
+ struct cursor_err err_data;
};
union number {
@@ -102,16 +105,23 @@ struct cell {
int n_attributes;
int n_children;
- const char *name;
- const char *id;
-
enum cell_type type;
};
+struct parser {
+ struct cursor *tokens;
+ struct cursor *attributes;
+ struct cursor *cells;
+};
+
void make_cursor(u8 *start, u8 *end, struct cursor *cursor);
int tokenize_cells(unsigned char *buf, int buf_size, struct cursor *tokens);
-int parse_cells(struct cursor *tokens, struct cursor *attributes, struct cursor *cells);
+int parse_cell(struct parser *parser, u16 *index);
void print_token_error(struct cursor *cursor);
+int cursor_index(struct cursor *cursor, int elem_size);
+const char *cell_type_str(enum cell_type);
+int cell_name(struct cursor *attributes, struct cell *cell, const char** name, int *len);
+struct cell *get_cell(struct cursor *cells, u16 index);
#endif /* PROTOVERSE_PARSE_H */
diff --git a/protoverse.c b/protoverse.c
@@ -14,9 +14,22 @@ int main(int argc, const char *argv[]) {
struct cursor attributes;
struct cursor cells;
+ struct cell *cell;
+
+ struct parser parser;
+
size_t count;
const char *space;
- int ok;
+ int ok, i;
+ u16 root;
+ int ncells;
+ const char *name;
+ int name_len;
+
+ parser.tokens = &tokens;
+ parser.attributes = &attributes;
+ parser.cells = &cells;
+
make_cursor(cells_buf, cells_buf + sizeof(cells_buf), &cells);
make_cursor(attrs_buf, attrs_buf + sizeof(attrs_buf), &attributes);
@@ -40,10 +53,20 @@ int main(int argc, const char *argv[]) {
assert(tokens.p == token_buf);
- ok = parse_cells(&tokens, &attributes, &cells);
+ ok = parse_cell(&parser, &root);
if (!ok) {
print_token_error(&tokens);
}
+ ncells = cursor_index(&cells, sizeof(struct cell));
+ printf("ncells %d\n", ncells);
+ for (i = 0; i < ncells; i++) {
+ name_len = 0;
+ cell = get_cell(&cells, i);
+ cell_name(&attributes, cell, &name, &name_len);
+ printf("cell %s %.*s\n",
+ cell_type_str(cell->type), name_len, name);
+ }
+
return 0;
}
diff --git a/satoshis-citadel.space b/satoshis-citadel.space
@@ -6,7 +6,8 @@
(id welcome-desk)
(name "Welcome desk")
(material marble)
- (condition clean new)
+ (condition clean)
+ (condition new)
(width 1) (depth 2) (height 1)
(location center)
)))