diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mds-kbdc/make-tree.c | 64 | ||||
-rw-r--r-- | src/mds-kbdc/mds-kbdc.c | 2 | ||||
-rw-r--r-- | src/mds-kbdc/tree.c | 251 | ||||
-rw-r--r-- | src/mds-kbdc/tree.h | 11 |
4 files changed, 322 insertions, 6 deletions
diff --git a/src/mds-kbdc/make-tree.c b/src/mds-kbdc/make-tree.c index 8cdc91b..5caaa72 100644 --- a/src/mds-kbdc/make-tree.c +++ b/src/mds-kbdc/make-tree.c @@ -455,6 +455,56 @@ /** + * Take next parameter, which should be a key combination, + * and store it in the current node + * + * @param var:identifier The name of the member variable, for the current + * node, where the parameter should be stored + */ +#define PURE_KEYS(var) \ + do \ + { \ + if (too_few) \ + break; \ + line += strlen(line); \ + *end = prev_end_char, prev_end_char = '\0'; \ + while (*line && (*line == ' ')) \ + line++; \ + if (*line == '\0') \ + { \ + line = original, end = line + strlen(line); \ + NEW_ERROR(1, ERROR, "too few parameters"); \ + line = end, too_few = 1; \ + } \ + else \ + { \ + char* arg_end = line; \ + char* call_end = arg_end; \ + int escape = 0, quote = 0, triangle = (*arg_end == '<'); \ + while (*arg_end) \ + { \ + char c = *arg_end++ ; \ + if (escape) escape = 0; \ + else if (arg_end <= call_end) ; \ + else if (c == '\\') \ + { \ + escape = 0; \ + call_end = arg_end + get_end_of_call(arg_end, 0, strlen(arg_end)); \ + } \ + else if (quote) quote = (c != '"'); \ + else if (c == '\"') quote = 1; \ + else if (c == '>') triangle = 0; \ + else if ((c == ' ') && !triangle) break; \ + } \ + prev_end_char = *arg_end, *arg_end = '\0'; \ + fail_if ((node->var = strdup(line)) == NULL); \ + end = line = arg_end; \ + } \ + } \ + while (0) + + +/** * Parse a sequence in a mapping */ #define SEQUENCE \ @@ -509,7 +559,7 @@ { \ NEW_NODE(keys, KEYS); \ NO_JUMP; \ - /* TODO (keys); */ \ + PURE_KEYS(keys); \ LEAF; \ node->loc_end = (size_t)(line - source_code.lines[line_i]); \ } \ @@ -802,6 +852,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu NEW_NODE(let, LET); CHARS(variable); TEST_FOR_KEYWORD(":"); + LEAF; *end = prev_end_char; while (*line && (*line == ' ')) line++; @@ -809,7 +860,6 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu { line = original, end = line + strlen(line), prev_end_char = '\0'; NEW_ERROR(1, ERROR, "too few parameters"); - LEAF; } else if (*line != '{') { @@ -820,12 +870,11 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu #undef node node->value = (mds_kbdc_tree_t*)subnode; END; - LEAF; } else { #define node subnode - NEW_NODE(array, ARRAY); + NEW_NODE(array, ARRAY); /* FIXME memory leak */ #define inner elements BRANCH("}"); node->loc_end = node->loc_start + 1; @@ -885,7 +934,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu size_t stack_orig = stack_ptr + 1; #define node supernode #define inner sequence - NEW_NODE(map, MAP); + NEW_NODE(map, MAP); /* FIXME memory leak */ BRANCH(":"); #undef inner #undef node @@ -964,6 +1013,9 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu +#undef SEQUENCE_FULLY_POPPED +#undef SEQUENCE +#undef PURE_KEYS #undef KEYS #undef TEST_FOR_KEYWORD #undef QUOTES_1 @@ -979,4 +1031,6 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu #undef is_name_char #undef in_range #undef xasprintf +#undef PRINT_STACK +#undef DEBUG_PROC diff --git a/src/mds-kbdc/mds-kbdc.c b/src/mds-kbdc/mds-kbdc.c index fccd1df..ef058ba 100644 --- a/src/mds-kbdc/mds-kbdc.c +++ b/src/mds-kbdc/mds-kbdc.c @@ -57,7 +57,7 @@ int main(int argc_, char** argv_) } mds_kbdc_parse_error_free_all(parse_errors); if (fatal) - return mds_kbdc_tree_free(tree), 1; + return mds_kbdc_tree_print(tree, stderr), mds_kbdc_tree_free(tree), 1; } mds_kbdc_tree_free(tree); diff --git a/src/mds-kbdc/tree.c b/src/mds-kbdc/tree.c index 4f0fec0..9f1085c 100644 --- a/src/mds-kbdc/tree.c +++ b/src/mds-kbdc/tree.c @@ -218,3 +218,254 @@ void mds_kbdc_tree_free(mds_kbdc_tree_t* restrict this) free(this); } + + +/** + * Convert the tree to a specialised subtype and + * prints its type and code location + * + * @param LOWERCASE:identifer The name of subtype + * @param NOTATION:const char* The notation for the subtype + */ +#define NODE(LOWERCASE, NOTATION) \ + mds_kbdc_tree_##LOWERCASE##_t* node; \ + node = (mds_kbdc_tree_##LOWERCASE##_t*)this; \ + fprintf(output, "%*.s(\033[01m%s\033[00m", indent, "", NOTATION); \ + fprintf(output, " \033[36m(@ %zu %zu-%zu)\033[00m", \ + node->loc_line, node->loc_start, node->loc_end) + + +/** + * Print a member for `node` which is a subtree + * + * @param MEMBER:identifier The tree structure's member + */ +#define BRANCH(MEMBER) \ + if (node->MEMBER) \ + { \ + fprintf(output, "\n%*.s(.%s\n", indent + 2, "", #MEMBER); \ + mds_kbdc_tree_print_indented(node->MEMBER, output, indent + 4); \ + fprintf(output, "%*.s)", indent + 2, ""); \ + } \ + else \ + fprintf(output, "\n%*.s(.%s \033[35mnil\033[00m)", indent + 2, "", #MEMBER) + + +/** + * End a tree which has at least one member that is a subtree + */ +#define COMPLEX \ + fprintf(output, "\n%*.s)\n", indent, "") + + +/** + * Print a member for `node` which is a string + * + * @param MEMBER:identifier The tree structure's member + */ +#define STRING(MEMBER) \ + if (node->MEMBER) \ + fprintf(output, " ‘\033[32m%s\033[00m’", node->MEMBER); \ + else \ + fprintf(output, " \033[35mnil\033[00m") + + +/** + * Print a member for `node` which is a string, + * and end the tree + * + * @param MEMBER:identifier The tree structure's member + */ +#define SIMPLE(MEMBER) \ + STRING(MEMBER); \ + fprintf(output, ")\n", node->MEMBER) + + +/** + * Print a tree which has only one member, + * and whose member is a string + * + * @param LOWERCASE:identifier See `NODE` + * @param NOTATION:const char* See `NODE` + * @param MEMBER:identifier See `STRING` + */ +#define SIMPLEX(LOWERCASE, NOTATION, MEMBER) \ + { \ + NODE(LOWERCASE, NOTATION); \ + SIMPLE(MEMBER); \ + } \ + break + + +/** + * Print a tree which has exactly two members, + * and whose members is are strings + * + * @param LOWERCASE:identifier See `NODE` + * @param NOTATION:const char* See `NODE` + * @param FIRST:identifier See `STRING`, the first member + * @param LAST:identifier See `STRING`, the second member + */ +#define DUPLEX(LOWERCASE, NOTATION, FIRST, LAST) \ + { \ + NODE(LOWERCASE, NOTATION); \ + STRING(FIRST); \ + SIMPLE(LAST); \ + } \ + break + + +/** + * Print a tree which has exactly one member, + * and whose members is a subtree + * + * @param LOWERCASE:identifier See `NODE` + * @param NOTATION:const char* See `NODE` + * @param MEMBER:identifier See `BRANCH` + */ +#define NESTING(LOWERCASE, NOTATION, MEMBER) \ + { \ + NODE(LOWERCASE, NOTATION); \ + BRANCH(MEMBER); \ + COMPLEX; \ + } \ + break + + +/** + * Print a tree which has exactly two members, + * and whose first member is a string and second + * member is a subtree + * + * @param LOWERCASE:identifier See `NODE` + * @param NOTATION:const char* See `NODE` + * @param NAMER:identifier See `STRING` + * @param MEMBER:identifier See `BRANCH` + */ +#define NAMED_NESTING(LOWERCASE, NOTATION, NAMER, MEMBER) \ + { \ + NODE(LOWERCASE, NOTATION); \ + STRING(NAMER); \ + BRANCH(MEMBER); \ + COMPLEX; \ + } \ + break + + +/** + * Print a tree which has no members + * + * @param NOTATION:const char* See `NODE` + */ +#define NOTHING(NOTATION) \ + fprintf(output, "%*.s(\033[01m%s\033[00m", indent, "", NOTATION); \ + fprintf(output, " \033[36m(@ %zu %zu-%zu)\033[00m", \ + this->loc_line, this->loc_start, this->loc_end); \ + fprintf(output, ")\n"); \ + break + + +/** + * Print a tree into a file + * + * @param this The tree node + * @param output The output file + * @param indent The indent + */ +static void mds_kbdc_tree_print_indented(mds_kbdc_tree_t* restrict this, FILE* output, int indent) +{ + again: + if (this == NULL) + return; + + switch (this->type) + { + /* These have their break built into their macro. */ + case MDS_KBDC_TREE_TYPE_INFORMATION: NESTING(information, "information", inner); + case MDS_KBDC_TREE_TYPE_INFORMATION_LANGUAGE: SIMPLEX(information_language, "language", data); + case MDS_KBDC_TREE_TYPE_INFORMATION_COUNTRY: SIMPLEX(information_country, "country", data); + case MDS_KBDC_TREE_TYPE_INFORMATION_VARIANT: SIMPLEX(information_variant, "variant", data); + case MDS_KBDC_TREE_TYPE_INCLUDE: SIMPLEX(include, "include", filename); + case MDS_KBDC_TREE_TYPE_FUNCTION: NAMED_NESTING(function, "function", name, inner); + case MDS_KBDC_TREE_TYPE_MACRO: NAMED_NESTING(macro, "macro", name, inner); + case MDS_KBDC_TREE_TYPE_ASSUMPTION: NESTING(assumption, "assumption", inner); + case MDS_KBDC_TREE_TYPE_ASSUMPTION_HAVE: NESTING(assumption_have, "have", data); + case MDS_KBDC_TREE_TYPE_ASSUMPTION_HAVE_CHARS: SIMPLEX(assumption_have_chars, "have_chars", chars); + case MDS_KBDC_TREE_TYPE_ASSUMPTION_HAVE_RANGE: DUPLEX(assumption_have_range, "have_range", first, last); + case MDS_KBDC_TREE_TYPE_LET: NAMED_NESTING(let, "let", variable, value); + case MDS_KBDC_TREE_TYPE_ARRAY: NESTING(array, "array", elements); + case MDS_KBDC_TREE_TYPE_KEYS: SIMPLEX(keys, "keys", keys); + case MDS_KBDC_TREE_TYPE_STRING: SIMPLEX(string, "string", string); + case MDS_KBDC_TREE_TYPE_NOTHING: NOTHING("nothing"); + case MDS_KBDC_TREE_TYPE_ALTERNATION: NESTING(alternation, "alternation", inner); + case MDS_KBDC_TREE_TYPE_UNORDERED: NESTING(unordered, "unordered", inner); + case MDS_KBDC_TREE_TYPE_MACRO_CALL: NAMED_NESTING(macro_call, "macro_call", name, arguments); + case MDS_KBDC_TREE_TYPE_RETURN: NOTHING("return"); + case MDS_KBDC_TREE_TYPE_BREAK: NOTHING("break"); + case MDS_KBDC_TREE_TYPE_CONTINUE: NOTHING("continue"); + + case MDS_KBDC_TREE_TYPE_FOR: + { + NODE(for, "for"); + STRING(first); + STRING(last); + fprintf(output, " (.variable"); + STRING(variable); + fprintf(output, ")"); + BRANCH(inner); + COMPLEX; + } + break; + + case MDS_KBDC_TREE_TYPE_IF: + { + NODE(if, "if"); + STRING(condition); + BRANCH(inner); + BRANCH(otherwise); + COMPLEX; + } + break; + + case MDS_KBDC_TREE_TYPE_MAP: + { + NODE(map, "map"); + BRANCH(sequence); + BRANCH(result); + COMPLEX; + } + break; + + default: + abort(); + break; + } + + this = this->next; + goto again; +} + + +/** + * Print a tree into a file + * + * @param this The tree node + * @param output The output file + */ +void mds_kbdc_tree_print(mds_kbdc_tree_t* restrict this, FILE* output) +{ + mds_kbdc_tree_print_indented(this, output, 0); +} + + +#undef NOTHING +#undef NAMED_NESTING +#undef NESTING +#undef DUPLEX +#undef SIMPLEX +#undef SIMPLE +#undef STRING +#undef COMPLEX +#undef BRANCH +#undef NODE + diff --git a/src/mds-kbdc/tree.h b/src/mds-kbdc/tree.h index 7bdbf3d..28d319d 100644 --- a/src/mds-kbdc/tree.h +++ b/src/mds-kbdc/tree.h @@ -20,6 +20,8 @@ #include <stddef.h> +#include <stdio.h> +#include <unistd.h> @@ -707,6 +709,15 @@ void mds_kbdc_tree_destroy(mds_kbdc_tree_t* restrict this); void mds_kbdc_tree_free(mds_kbdc_tree_t* restrict this); +/** + * Print a tree into a file + * + * @param this The tree node + * @param output The output file + */ +void mds_kbdc_tree_print(mds_kbdc_tree_t* restrict this, FILE* output); + + #undef MDS_KBDC_TREE_PADDING #undef MDS_KBDC_TREE_PADDING_ |