protoverse

A metaverse protocol
git clone git://jb55.com/protoverse
Log | Files | Refs | README | LICENSE

commit ee953c868624dae99f0ba9b9630484e0dce1f4a8
parent ac654e95e69881d76b7c17d60cfe00c1707bc294
Author: William Casarin <jb55@jb55.com>
Date:   Thu, 12 Aug 2021 09:05:00 -0700

better room descriptions

Diffstat:
Msatoshis-citadel.space | 27+++++++++++++++++++++++++--
Msrc/describe.c | 210++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/describe.h | 4++--
Msrc/parse.c | 178+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/parse.h | 31+++++++++++++++++++++----------
Msrc/protoverse.c | 47++++++++++++++++++++++++++++++++++++++++++++---
6 files changed, 335 insertions(+), 162 deletions(-)

diff --git a/satoshis-citadel.space b/satoshis-citadel.space @@ -1,10 +1,13 @@ -(space (shape rectangle) +(room (shape rectangle) (condition "clean") (condition "shiny") (material "solid gold") (name "Satoshi's Den") (width 10) (depth 10) (height 100) (group + (table (name "hardy") + (material "rock") + (object (name "pencil"))) (table (id welcome-desk) (name "welcome desk") (material "marble") @@ -12,7 +15,27 @@ (condition "new") (width 1) (depth 2) (height 1) (location center) - (light (name "desk"))) + (group + (light (name "desk")) + (obj (name "chessboard") + (group + (obj (p "a1") (color "white") (material "marble") (name "rook")) + (obj (p "b1") (color "white") (material "marble") (name "knight")) + (obj (p "c1") (color "white") (material "marble") (name "bishop")) + (obj (p "d1") (color "white") (material "marble") (name "queen")) + (obj (p "e1") (color "white") (material "marble") (name "king")) + (obj (p "f1") (color "white") (material "marble") (name "bishop")) + (obj (p "g1") (color "white") (material "marble") (name "knight")) + (obj (p "h1") (color "white") (material "marble") (name "rook")) + (obj (p "a8") (color "black") (material "marble") (name "rook")) + (obj (p "b8") (color "black") (material "marble") (name "knight")) + (obj (p "c8") (color "black") (material "marble") (name "bishop")) + (obj (p "d8") (color "black") (material "marble") (name "queen")) + (obj (p "e8") (color "black") (material "marble") (name "king")) + (obj (p "f8") (color "black") (material "marble") (name "bishop")) + (obj (p "g8") (color "black") (material "marble") (name "knight")) + (obj (p "h8") (color "black") (material "marble") (name "rook")) + )))) (chair (id a)) (chair (id b)) diff --git a/src/describe.c b/src/describe.c @@ -12,15 +12,13 @@ static int push_sized_word(struct cursor *strs, const char *str, int len) { - int ok; - if (strs->p-1 >= strs->start && !isspace(*(strs->p-1))) { - ok = cursor_push_str(strs, " "); - if (!ok) return 0; + if (!cursor_push_str(strs, " ")) + return 0; } - ok = push_sized_str(strs, str, len); - if (!ok) return 0; + if (!push_sized_str(strs, str, len)) + return 0; return 1; } @@ -51,7 +49,7 @@ static int push_adjective(struct cursor *strs, struct attribute *attr) static int is_adjective(struct attribute *attr) { - return attr->type == A_CONDITION; + return attr->type == A_CONDITION || attr->type == A_COLOR; } static int count_adjectives(struct describe *desc) @@ -147,7 +145,8 @@ static int push_named(struct describe *desc) int name_len; int ok; - cell_name(&desc->parsed->attributes, desc->cell, &name, &name_len); + cell_attr_str(&desc->parsed->attributes, desc->cell, &name, &name_len, + A_NAME); if (name_len == 0) return 1; @@ -239,15 +238,22 @@ static int describe_amount(struct describe *desc, int nobjs) static int describe_object_name(struct cursor *strs, struct cursor *attrs, struct cell *cell) { - int ok; const char *name; int name_len; - cell_name(attrs, cell, &name, &name_len); - if (name_len > 0) { - ok = push_sized_word(strs, name, name_len); - if (!ok) return 0; - } + cell_attr_str(attrs, cell, &name, &name_len, A_COLOR); + if (name_len > 0 && !push_sized_word(strs, name, name_len)) + return 0; + + /* + cell_attr_str(attrs, cell, &name, &name_len, A_MATERIAL); + if (name_len > 0 && !push_sized_word(strs, name, name_len)) + return 0; + */ + + cell_attr_str(attrs, cell, &name, &name_len, A_NAME); + if (name_len > 0 && !push_sized_word(strs, name, name_len)) + return 0; if (cell->type == C_OBJECT) { if (cell->obj_type == O_OBJECT) @@ -258,118 +264,162 @@ static int describe_object_name(struct cursor *strs, struct cursor *attrs, struc return push_word(strs, cell_type_str(cell->type)); } -static int describe_group(struct describe *desc) +static int describe_group_children(struct cell *parent, struct describe *desc) { - int i, ok, nobjs; - struct cell *cell; - - nobjs = desc->cell->n_children; - - ok = describe_amount(desc, nobjs); - - ok = push_word(desc->strs, "object"); - if (!ok) return 0; - - if (nobjs > 1) { - ok = cursor_push_str(desc->strs, "s:"); - if (!ok) return 0; - } - else { - cursor_push_str(desc->strs, ":"); - if (!ok) return 0; - } + int i; + struct cell *child; - ok = push_word(desc->strs, "a"); - if (!ok) return 0; + if (!push_word(desc->strs, "a")) + return 0; - for (i = 0; i < nobjs; i++) { - cell = get_cell(&desc->parsed->cells, - desc->cell->children[i]); - assert(cell); + for (i = 0; i < parent->n_children; i++) { + child = get_cell(&desc->parsed->cells, parent->children[i]); + assert(child); if (i > 0) { - if (i == nobjs-1) { - ok = push_word(desc->strs, "and"); - if (!ok) return 0; + if (i == parent->n_children-1) { + if (!push_word(desc->strs, "and")) + return 0; } - else if (i != nobjs-1) { - ok = cursor_push_str(desc->strs, ","); - if (!ok) return 0; + else if (i != parent->n_children-1) { + if (!cursor_push_str(desc->strs, ",")) + return 0; } } - ok = describe_object_name(desc->strs, &desc->parsed->attributes, cell); - if (!ok) return 0; + if (!describe_object_name(desc->strs, &desc->parsed->attributes, child)) + return 0; } return 1; } -static int describe_object(struct describe *desc) +static int describe_group(struct describe *desc) { - if (!push_word(desc->strs, "a")) + if (!describe_amount(desc, desc->cell->n_children)) return 0; + if (!push_word(desc->strs, "object")) + return 0; + + if (desc->cell->n_children > 1) { + if (!cursor_push_str(desc->strs, "s:")) + return 0; + } + else { + if (!cursor_push_str(desc->strs, ":")) + return 0; + } + + return describe_group_children(desc->cell, desc); +} + +static int describe_object(struct describe *desc) +{ return describe_object_name(desc->strs, &desc->parsed->attributes, desc->cell); } -int describe_cell(struct cell *cell, struct parser *parsed, struct cursor *strbuf) +int describe_cell(struct describe *desc) { - struct describe desc; - - desc.cell = cell; - desc.parsed = parsed; - desc.strs = strbuf; - - switch (cell->type) { + switch (desc->cell->type) { case C_ROOM: - return describe_area(&desc, "room"); + return describe_area(desc, "room"); case C_SPACE: - return describe_area(&desc, "space"); + return describe_area(desc, "space"); case C_GROUP: - return describe_group(&desc); + return describe_group(desc); case C_OBJECT: - return describe_object(&desc); + if (!push_word(desc->strs, "a")) + return 0; + + return describe_object(desc); } return 1; } - -int describe_cells(struct cell *cell, struct parser *parsed, struct cursor *strs, int max_depth, int depth) +static int describe_cell_name(struct describe *desc) { - int ok; + if (desc->cell->type == C_OBJECT) + return describe_object(desc); - if (depth > max_depth) - return 1; + return push_word(desc->strs, cell_type_str(desc->cell->type)); +} - ok = describe_cell(cell, parsed, strs); - if (!ok) return 0; +static int describe_cell_children(struct describe *desc); - ok = cursor_push_str(strs, ".\n"); - if (!ok) return 0; +static int describe_cell_children_rest(struct describe desc) +{ + int i; + struct cell *parent = desc.cell; - if (cell->n_children == 0) - return 1; + for (i = 0; i < parent->n_children; i++) { + desc.cell = get_cell(&desc.parsed->cells, parent->children[i]); - if (cell->type == C_ROOM || cell->type == C_SPACE) { - if (!push_word(strs, "It contains")) + if (desc.cell->n_children > 0 && !describe_cell_children(&desc)) return 0; - cell = get_cell(&parsed->cells, cell->children[0]); - return describe_cells(cell, parsed, strs, max_depth, depth+1); } return 1; } +static int describe_cell_children_group(struct describe desc) +{ + struct cell *child; + + if (desc.cell->n_children == 1 && + (child = get_cell(&desc.parsed->cells, desc.cell->children[0])) && + child->type == C_GROUP) { + desc.cell = child; + return describe_cell_children_group(desc); + } + + if (!describe_group_children(desc.cell, &desc)) + return 0; + + if (!cursor_push_byte(desc.strs, '\n')) + return 0; + + return describe_cell_children_rest(desc); +} + +static int describe_cell_children(struct describe *desc) +{ + if (!push_word(desc->strs, "The")) + return 0; + + if (!describe_cell_name(desc)) + return 0; + + if (!push_word(desc->strs, "contains")) + return 0; + + return describe_cell_children_group(*desc); +} + +int describe_cells(struct describe *desc) +{ + if (!describe_cell(desc)) + return 0; + + if (!cursor_push_str(desc->strs, ".\n")) + return 0; + + if (desc->cell->n_children == 0) + return 1; + + return describe_cell_children(desc); +} + int describe(struct parser *parser, u16 root_cell) { - static char strbuf[2048]; + static char strbuf[4096*32]; struct cursor strs; struct cell *cell; + struct describe desc; strbuf[0] = 0; @@ -377,7 +427,11 @@ int describe(struct parser *parser, u16 root_cell) make_cursor((u8*)strbuf, (u8*)strbuf + sizeof(strbuf), &strs); - describe_cells(cell, parser, &strs, 10, 0); + desc.cell = cell; + desc.parsed = parser; + desc.strs = &strs; + + describe_cells(&desc); printf("\n\ndescription\n-----------\n\n%s\n", strbuf); diff --git a/src/describe.h b/src/describe.h @@ -11,7 +11,7 @@ struct describe { }; int describe(struct parser *parser, u16 root_cell); -int describe_cell(struct cell *cell, struct parser *parsed, struct cursor *strbuf); -int describe_cells(struct cell *cell, struct parser *parsed, struct cursor *strs, int max_depth, int depth); +int describe_cell(struct describe *desc); +int describe_cells(struct describe *desc); #endif diff --git a/src/parse.c b/src/parse.c @@ -43,6 +43,7 @@ union token { #ifdef DEBUG +#endif static const char *attr_type_str(enum attribute_type type) { switch (type) { @@ -52,16 +53,17 @@ static const char *attr_type_str(enum attribute_type type) case A_ID: return "id"; case A_LOCATION: return "location"; case A_MATERIAL: return "material"; + case A_COLOR: return "color"; case A_NAME: return "name"; case A_SHAPE: return "shape"; case A_TYPE: return "type"; case A_WIDTH: return "width"; case A_STATE: return "state"; + case A_DATA: return "data"; } return "unknown"; } -#endif static const char *token_error_string(enum token_error err) { @@ -93,13 +95,14 @@ static void init_token_cursor(struct token_cursor *cursor) memset(&cursor->err_data, 0, sizeof(cursor->err_data)); } -struct attribute *get_attr(struct cursor *attributes, u16 index) +struct attribute *get_attr(struct cursor *attributes, int index) { return (struct attribute*)index_cursor(attributes, index, sizeof(struct attribute)); } /* +*/ static const char *shape_str(enum shape shape) { switch (shape) { @@ -142,7 +145,6 @@ static void print_attributes(struct cursor *attributes, struct cell *cell) print_attribute(attr); } } -*/ void print_cell(struct cursor *attributes, struct cell *cell) { @@ -154,14 +156,14 @@ void print_cell(struct cursor *attributes, struct cell *cell) return; } - cell_name(attributes, cell, &name, &name_len); + cell_attr_str(attributes, cell, &name, &name_len, A_NAME); printf("%.*s%s%s ", name_len, name, name_len > 0?" ":"", cell->type == C_OBJECT ? object_type_str(cell->obj_type) : cell_type_str(cell->type)); - /* print_attributes(attributes, cell); */ + //print_attributes(attributes, cell); } @@ -228,9 +230,8 @@ static int push_token_data(struct token_cursor *tokens, #ifdef DEBUG struct tok_str *str; #endif - int ok; - ok = cursor_push_byte(&tokens->c, token); - if (!ok) return 0; + if (!cursor_push_byte(&tokens->c, token)) + return 0; switch (token) { @@ -258,8 +259,11 @@ static int push_token_data(struct token_cursor *tokens, tokdebug("sym %.*s", str->len, str->data); } #endif - ok = cursor_push(&tokens->c, token_data, token_data_size); - if (!ok) return 0; + if (!cursor_push(&tokens->c, token_data, token_data_size)) { + printf("hmm? %d\n", token_data_size); + cursor_print_around(&tokens->c, 10); + return 0; + } #ifdef DEBUG printf("\n"); #endif @@ -489,8 +493,8 @@ static int read_and_push_atom(struct token_cursor *cursor, struct token_cursor * if (ok) { str.len = ok; str.data = start; - ok = push_symbol(tokens, str); - if (!ok) { + if (!push_symbol(tokens, str)) { + cursor_print_around(&tokens->c, 10); printf("read_and_push_atom identifier push overflow\n"); return 0; } @@ -725,10 +729,9 @@ static int parse_stringy_token(struct token_cursor *tokens, enum token_type type) { union token token; - int ok; - ok = pull_token(tokens, &token, type); - if (!ok) return 0; + if (!pull_token(tokens, &token, type)) + return 0; str->data = token.str.data; str->len = token.str.len; @@ -768,7 +771,7 @@ static int parse_number(struct token_cursor *tokens, union number *number) } -struct cell *get_cell(struct cursor *cells, u16 index) +struct cell *get_cell(struct cursor *cells, int index) { return (struct cell*)index_cursor(cells, index, sizeof(struct cell)); @@ -782,11 +785,10 @@ static int symbol_eq(struct tok_str *a, const char *b, int b_len) static int parse_symbol(struct token_cursor *tokens, const char *match) { - int ok; struct tok_str str; - ok = pull_symbol_token(tokens, &str); - if (!ok) return 0; + if (!pull_symbol_token(tokens, &str)) + return 0; if (!symbol_eq(&str, match, strlen(match))) return 0; @@ -837,23 +839,43 @@ static int parse_str_attr(struct token_cursor *tokens, { struct token_cursor temp; struct tok_str str; - int ok; + struct bufstr *bufstr; assert(tok_type == T_NUMBER || tok_type == T_SYMBOL || tok_type == T_STRING); copy_token_cursor(tokens, &temp); - ok = parse_symbol(&temp, sym); - if (!ok) return 0; + if (sym == NULL) { + if (!pull_symbol_token(&temp, &str)) + return 0; - ok = parse_stringy_token(&temp, &str, tok_type); - if (!ok) return 0; + attr->data.data_attr.sym.ptr = (char*)str.data; + attr->data.data_attr.sym.len = str.len; - attr->data.str.ptr = (char*)str.data; - attr->data.str.len = str.len; + bufstr = &attr->data.data_attr.str; + } else { + if (!parse_symbol(&temp, sym)) + return 0; + bufstr = &attr->data.str; + } + + if (!parse_stringy_token(&temp, &str, tok_type)) + return 0; + + bufstr->ptr = (char*)str.data; + bufstr->len = str.len; attr->type = type; - tokdebug("attribute %s %.*s\n", sym, str.len, str.data); +#ifdef DEBUG + if (sym == NULL) + tokdebug("attribute %.*s %.*s\n", + attr->data.data_attr.sym.len, + attr->data.data_attr.sym.ptr, + str.len, + str.data); + else + tokdebug("attribute %s %.*s\n", sym, str.len, str.data); +#endif copy_token_cursor(&temp, tokens); @@ -891,18 +913,28 @@ static int parse_size(struct token_cursor *tokens, struct attribute *attr) return 1; } -int cell_name(struct cursor *attributes, struct cell *cell, const char** name, int *len) +static struct bufstr *attr_bufstr(struct attribute *attr) +{ + if (attr->type == A_DATA) + return &attr->data.data_attr.str; + return &attr->data.str; +} + +int cell_attr_str(struct cursor *attributes, struct cell *cell, + const char** name, int *len, enum attribute_type type) { int i; struct attribute *attr; + struct bufstr *bufstr; *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; + if (attr->type == type) { + bufstr = attr_bufstr(attr); + *name = bufstr->ptr; + *len = bufstr->len; return 1; } } @@ -910,6 +942,14 @@ int cell_name(struct cursor *attributes, struct cell *cell, const char** name, i return 0; } +const char *cell_name(struct cursor *attributes, struct cell *cell, int *len) +{ + const char *name = NULL; + if (!cell_attr_str(attributes, cell, &name, len, A_NAME)) + return NULL; + return name; +} + static int parse_attribute(struct token_cursor *tokens, struct attribute *attr) { int ok; @@ -934,6 +974,9 @@ static int parse_attribute(struct token_cursor *tokens, struct attribute *attr) ok = parse_str_attr(&temp, attr, "material", A_MATERIAL, T_STRING); if (ok) goto close; + ok = parse_str_attr(&temp, attr, "color", A_COLOR, T_STRING); + if (ok) goto close; + /* TODO: parse multiple conditions */ ok = parse_str_attr(&temp, attr, "condition", A_CONDITION, T_STRING); if (ok) goto close; @@ -944,6 +987,9 @@ static int parse_attribute(struct token_cursor *tokens, struct attribute *attr) ok = parse_str_attr(&temp, attr, "state", A_STATE, T_SYMBOL); if (ok) goto close; + ok = parse_str_attr(&temp, attr, NULL, A_DATA, T_STRING); + if (ok) goto close; + ok = parse_size(&temp, attr); if (ok) goto close; @@ -1010,7 +1056,7 @@ static int parse_group(struct cursor *tokens) */ -static int push_cell(struct cursor *cells, struct cell *cell, u16 *cell_index) +static int push_cell(struct cursor *cells, struct cell *cell, int *cell_index) { int index; int ok; @@ -1041,7 +1087,7 @@ static void copy_parser(struct parser *from, struct parser *to) copy_cursor(&from->attributes, &to->attributes); } -static int push_cell_child(struct cell *parent, u16 child_ind) +static int push_cell_child(struct cell *parent, int child_ind) { int ok; struct cursor child_inds; @@ -1085,11 +1131,11 @@ const char *cell_type_str(enum cell_type type) return "unknown"; } -static int parse_cell_attrs(struct parser *parser, u16 *index, struct cell *cell) +static int parse_cell_attrs(struct parser *parser, int *index, struct cell *cell) { struct cursor cell_attr_inds; struct cell *child_cell; - u16 child_cell_index; + int child_cell_index; int attr_inds[2] = {0}; int i, ok; @@ -1116,11 +1162,11 @@ static int parse_cell_attrs(struct parser *parser, u16 *index, struct cell *cell tokdebug("optional child cell in parse_cell_attrs\n"); ok = parse_cell(parser, &child_cell_index); if (ok) { - child_cell = get_cell(&parser->cells, child_cell_index); - if (!child_cell) return 0; + if (!(child_cell = get_cell(&parser->cells, child_cell_index))) + return 0l tokdebug("parse_cell_attrs push child cell\n"); - ok = push_cell_child(cell, child_cell_index); - if (!ok) return 0; + if (!push_cell_child(cell, child_cell_index)) + return 0; } else { @@ -1134,14 +1180,14 @@ static int parse_cell_attrs(struct parser *parser, u16 *index, struct cell *cell } static int parse_cell_by_name(struct parser *parser, - u16 *index, + int *index, const char *name, enum cell_type type) { int ok; struct parser backtracked; struct cell cell; - u16 ind; + int ind; init_cell(&cell); @@ -1163,21 +1209,20 @@ static int parse_cell_by_name(struct parser *parser, return 1; } -static int parse_space(struct parser *parser, u16 *index) +static int parse_space(struct parser *parser, int *index) { return parse_cell_by_name(parser, index, "space", C_SPACE); } -static int parse_room(struct parser *parser, u16 *index) +static int parse_room(struct parser *parser, int *index) { return parse_cell_by_name(parser, index, "room", C_ROOM); } -static int parse_group(struct parser *parser, u16 *index) +static int parse_group(struct parser *parser, int *index) { - int ok; int ncells = 0; - u16 child_ind; + int child_ind; struct parser backtracked; struct cell group; @@ -1187,12 +1232,12 @@ static int parse_group(struct parser *parser, u16 *index) copy_parser(parser, &backtracked); - ok = parse_symbol(&backtracked.tokens, "group"); - if (!ok) return 0; + if (!parse_symbol(&backtracked.tokens, "group")) + return 0; while (1) { - ok = parse_cell(&backtracked, &child_ind); - if (!ok) break; + if (!parse_cell(&backtracked, &child_ind)) + break; child_cell = get_cell(&backtracked.cells, child_ind); if (child_cell == NULL) { @@ -1201,8 +1246,8 @@ static int parse_group(struct parser *parser, u16 *index) } tokdebug("group child cell type %s\n", cell_type_str(child_cell->type)); - ok = push_cell_child(&group, child_ind); - if (!ok) return 0; + if (!push_cell_child(&group, child_ind)) + return 0; ncells++; } @@ -1214,8 +1259,8 @@ static int parse_group(struct parser *parser, u16 *index) group.type = C_GROUP; - ok = push_cell(&backtracked.cells, &group, index); - if (!ok) return 0; + if (!push_cell(&backtracked.cells, &group, index)) + return 0; copy_parser(&backtracked, parser); @@ -1232,25 +1277,25 @@ static struct object_def object_defs[] = { {"chair", O_CHAIR}, {"door", O_DOOR}, {"light", O_LIGHT}, - {"object", O_OBJECT}, + {"obj", O_OBJECT}, }; -static int parse_object(struct parser *parser, u16 *index) +static int parse_object(struct parser *parser, int *index) { - int ok, i; + int i; struct parser backtracked; struct tok_str str; struct object_def *def; struct cell cell; - u16 ind; + int ind; init_cell(&cell); cell.type = C_OBJECT; copy_parser(parser, &backtracked); - ok = pull_symbol_token(&backtracked.tokens, &str); - if (!ok) return 0; + if (!pull_symbol_token(&backtracked.tokens, &str)) + return 0; for (i = 0; i < ARRAY_SIZE(object_defs); i++) { def = &object_defs[i]; @@ -1261,10 +1306,9 @@ static int parse_object(struct parser *parser, u16 *index) } } - ok = parse_cell_attrs(&backtracked, &ind, &cell); - if (!ok) return 0; + if (!parse_cell_attrs(&backtracked, &ind, &cell)) + return 0; - assert(ind < 10); if (index) *index = ind; @@ -1273,7 +1317,7 @@ static int parse_object(struct parser *parser, u16 *index) return 1; } -int parse_cell(struct parser *parser, u16 *index) +int parse_cell(struct parser *parser, int *index) { int ok; struct parser backtracked; @@ -1328,7 +1372,7 @@ int init_parser(struct parser *parser) int ok; int attrs_size = sizeof(struct attribute) * 1024; - int tokens_size = 2048; + int tokens_size = 2048*32; int cells_size = sizeof(struct cell) * 1024; int memsize = attrs_size + tokens_size + cells_size; @@ -1356,7 +1400,7 @@ int free_parser(struct parser *parser) return 1; } -int parse_buffer(struct parser *parser, u8 *file_buf, int len, u16 *root) +int parse_buffer(struct parser *parser, u8 *file_buf, int len, int *root) { int ok; @@ -1377,7 +1421,7 @@ int parse_buffer(struct parser *parser, u8 *file_buf, int len, u16 *root) } -int parse_file(struct parser *parser, const char *filename, u16 *root, u8 *buf, +int parse_file(struct parser *parser, const char *filename, int *root, u8 *buf, u32 bufsize) { int count, ok; diff --git a/src/parse.h b/src/parse.h @@ -42,12 +42,14 @@ enum attribute_type { A_NAME, A_MATERIAL, A_CONDITION, + A_COLOR, A_WIDTH, A_DEPTH, A_HEIGHT, A_LOCATION, A_SHAPE, A_STATE, + A_DATA, }; enum cell_state { @@ -81,11 +83,19 @@ union number { double fdouble; }; +struct bufstr { + const char *ptr; + int len; +}; + +struct data_attr { + struct bufstr str; + struct bufstr sym; +}; + union attr_data { - struct { - const char *ptr; - int len; - } str; + struct bufstr str; + struct data_attr data_attr; enum shape shape; union number number; }; @@ -132,18 +142,19 @@ struct parser { struct cursor cells; }; -int parse_buffer(struct parser *parser, u8 *file_buf, int len, u16 *root); -int parse_file(struct parser *parser, const char *filename, u16 *root, u8 *buf, u32 bufsize); +int parse_buffer(struct parser *parser, u8 *file_buf, int len, int *root); +int parse_file(struct parser *parser, const char *filename, int *root, u8 *buf, u32 bufsize); int init_parser(struct parser *parser); int free_parser(struct parser *parser); void print_cell(struct cursor *attributes, struct cell *cell); int tokenize_cells(unsigned char *buf, int buf_size, struct token_cursor *tokens); -int parse_cell(struct parser *parser, u16 *index); +int parse_cell(struct parser *parser, int *index); void print_token_error(struct token_cursor *cursor); const char *cell_type_str(enum cell_type); const char *object_type_str(enum object_type); -int cell_name(struct cursor *attributes, struct cell *cell, const char** name, int *len); -struct cell *get_cell(struct cursor *cells, u16 index); -struct attribute *get_attr(struct cursor *attributes, u16 index); +struct cell *get_cell(struct cursor *cells, int index); +struct attribute *get_attr(struct cursor *attributes, int index); +int cell_attr_str(struct cursor *attributes, struct cell *cell, const char** name, int *len, enum attribute_type type); +const char *cell_name(struct cursor *attributes, struct cell *cell, int *len); #endif /* PROTOVERSE_PARSE_H */ diff --git a/src/protoverse.c b/src/protoverse.c @@ -41,7 +41,43 @@ static void print_all_cells(struct parser *parser) } */ -static int print_cell_tree(struct parser *parser, u16 root, int depth) +static int match_selector(struct cursor *attrs, struct cell *cell, const char *query) +{ + const char *str; + int str_len; + int query_len = strlen(query); + + if (!cell_attr_str(attrs, cell, &str, &str_len, A_NAME)) + return 0; + if (query_len == str_len && !memcmp(str, query, str_len)) + return 1; + if (!cell_attr_str(attrs, cell, &str, &str_len, A_ID)) + return 0; + if (query_len == str_len && !memcmp(str, query, str_len)) + return 1; + + return 0; +} + +static int cell_selector(struct parser *parser, u32 root, const char *query) +{ + int res; + int i; + struct cell *cell = get_cell(&parser->cells, root); + + if ((res = match_selector(&parser->attributes, cell, query))) + return root; + + for (i = 0; i < cell->n_children; i++) { + //cell = get_cell(&parser->cells, cell->children[i]); + if ((res = cell_selector(parser, cell->children[i], query))) + return res; + } + + return 0; +} + +static int print_cell_tree(struct parser *parser, u32 root, int depth) { int i; @@ -110,7 +146,7 @@ int main(int argc, const char *argv[]) unsigned char *wasm_data; struct parser parser; struct protoverse_server server; - u16 root; + int root, found; int ok; int retval; size_t len; @@ -121,7 +157,7 @@ int main(int argc, const char *argv[]) cmd = argv[1]; if (streq(cmd, "parse")) { - if (argc != 3) + if (argc < 3) return usage(); ok = init_parser(&parser); if (!ok) { @@ -135,6 +171,11 @@ int main(int argc, const char *argv[]) return 1; } + if (argc > 3) { + if ((found = cell_selector(&parser, root, argv[3]))) + root = found; + } + print_cell_tree(&parser, root, 0); describe(&parser, root);