aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mds-kbdc/make-tree.c64
-rw-r--r--src/mds-kbdc/mds-kbdc.c2
-rw-r--r--src/mds-kbdc/tree.c251
-rw-r--r--src/mds-kbdc/tree.h11
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_