diff options
20 files changed, 328 insertions, 21 deletions
diff --git a/src/mds-kbdc/make-tree.c b/src/mds-kbdc/make-tree.c index 37ed34c..1172dbe 100644 --- a/src/mds-kbdc/make-tree.c +++ b/src/mds-kbdc/make-tree.c @@ -134,6 +134,21 @@ /** + * Create a new node named `subnode` + * + * @param LOWERCASE:identifier The keyword, for the node type, in lower case + * @param UPPERCASE:identifier The keyword, for the node type, in upper case + */ +#define NEW_SUBNODE(LOWERCASE, UPPERCASE) \ + mds_kbdc_tree_##LOWERCASE##_t* subnode; \ + fail_if (xcalloc(subnode, 1, mds_kbdc_tree_##LOWERCASE##_t)); \ + subnode->type = MDS_KBDC_TREE_TYPE_##UPPERCASE; \ + subnode->loc_line = line_i; \ + subnode->loc_start = (size_t)(line - source_code.lines[line_i]); \ + subnode->loc_end = (size_t)(end - source_code.lines[line_i]) + + +/** * Update the tip of the tree stack with the current node * and change the pointer at the tip to the pointer to the * current node's down pointer @@ -283,12 +298,12 @@ call_end = arg_end + get_end_of_call(arg_end, 0, strlen(arg_end)); \ } \ else if (quote) quote = (c != '"'); \ - else if (c == ' ') break; \ + else if (c == ' ') { arg_end--; break; } \ else quote = (c == '"'); \ } \ - prev_end_char = *arg_end, *arg_end = '\0'; \ + prev_end_char = *arg_end, *arg_end = '\0', end = arg_end; \ fail_if ((node->var = strdup(line)) == NULL); \ - end = line = arg_end; \ + line = end; \ } \ } \ while (0) @@ -429,26 +444,22 @@ else if (quote) quote = (c != '"'); \ else if (c == '\"') quote = 1; \ else if (c == '>') triangle = 0; \ - else if ((c == ' ') && !triangle) break; \ + else if ((c == ' ') && !triangle) { arg_end--; break; } \ } \ - prev_end_char = *arg_end, *arg_end = '\0'; \ + prev_end_char = *arg_end, *arg_end = '\0', end = arg_end; \ if (*line == '<') \ { \ - mds_kbdc_tree_keys_t* subnode; \ - fail_if (xcalloc(subnode, 1, mds_kbdc_tree_keys_t)); \ - subnode->type = MDS_KBDC_TREE_TYPE_KEYS; \ + NEW_SUBNODE(keys, KEYS); \ node->var = (mds_kbdc_tree_t*)subnode; \ fail_if ((subnode->keys = strdup(line)) == NULL); \ } \ else \ { \ - mds_kbdc_tree_string_t* subnode; \ - fail_if (xcalloc(subnode, 1, mds_kbdc_tree_string_t)); \ - subnode->type = MDS_KBDC_TREE_TYPE_STRING; \ + NEW_SUBNODE(string, STRING); \ node->var = (mds_kbdc_tree_t*)subnode; \ fail_if ((subnode->string = strdup(line)) == NULL); \ } \ - end = line = arg_end; \ + line = end; \ } \ } \ while (0) @@ -494,11 +505,11 @@ else if (quote) quote = (c != '"'); \ else if (c == '\"') quote = 1; \ else if (c == '>') triangle = 0; \ - else if ((c == ' ') && !triangle) break; \ + else if ((c == ' ') && !triangle) { arg_end--; break; } \ } \ prev_end_char = *arg_end, *arg_end = '\0'; \ fail_if ((node->var = strdup(line)) == NULL); \ - end = line = arg_end; \ + end = arg_end, line = end; \ } \ } \ while (0) @@ -821,12 +832,13 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu tree_stack[stack_ptr + 1] = &(node->otherwise); keyword_stack[stack_ptr++] = "if"; } - else if ((strstr(line, "if") == line) && ((line[3] == ' ') || (line[3] == '\0'))) + else if ((strstr(line, "if") == line) && ((line[2] == ' ') || (line[2] == '\0'))) { /* else if */ NEW_NODE(if, IF); + node->loc_end = node->loc_start + 2; tree_stack[stack_ptr][0]->if_.otherwise = (mds_kbdc_tree_t*)node; - line += 2; + end = line += 2, prev_end_char = *end, *end = '\0'; CHARS(condition); END; BRANCH("if"); @@ -943,8 +955,10 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu SEQUENCE_FULLY_POPPED(stack_orig); stack_ptr--; *end = prev_end_char; + while (*line && (*line == ' ')) + line++; if (*line++ != ':') - continue; + continue; /* Not an error in macros. */ #define node supernode #define inner result BRANCH(":"); @@ -954,6 +968,8 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu SEQUENCE_FULLY_POPPED(stack_orig); stack_ptr--; *end = prev_end_char; + while (*line && (*line == ' ')) + line++; if (*line == '\0') continue; end = line + strlen(line), prev_end_char = *end; diff --git a/src/mds-kbdc/parse-error.c b/src/mds-kbdc/parse-error.c index 1ad5ae1..298c712 100644 --- a/src/mds-kbdc/parse-error.c +++ b/src/mds-kbdc/parse-error.c @@ -82,7 +82,7 @@ void mds_kbdc_parse_error_print(const mds_kbdc_parse_error_t* restrict this, FIL /* Print error information. */ fprintf(output, "\033[01m%s\033[21m:", this->pathname); /* TODO should be relative to the current dir */ if (this->error_is_in_file) - fprintf(output, "%zu:%zu–%zu:", this->line + 1, start + 1, end + 1); + fprintf(output, "%zu:%zu–%zu:", this->line + 1, start, end); switch (this->severity) { case MDS_KBDC_PARSE_ERROR_NOTE: fprintf(output, " \033[01;36mnote:\033[00m "); break; diff --git a/src/mds-kbdc/tree.c b/src/mds-kbdc/tree.c index 9f1085c..b460d04 100644 --- a/src/mds-kbdc/tree.c +++ b/src/mds-kbdc/tree.c @@ -232,7 +232,7 @@ void mds_kbdc_tree_free(mds_kbdc_tree_t* restrict this) 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) + node->loc_line + 1, node->loc_start, node->loc_end) /** @@ -360,7 +360,7 @@ void mds_kbdc_tree_free(mds_kbdc_tree_t* restrict this) #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); \ + this->loc_line + 1, this->loc_start, this->loc_end); \ fprintf(output, ")\n"); \ break diff --git a/src/mds-kbdc/tree.h b/src/mds-kbdc/tree.h index 28d319d..f3ad7f2 100644 --- a/src/mds-kbdc/tree.h +++ b/src/mds-kbdc/tree.h @@ -473,7 +473,11 @@ typedef struct mds_kbdc_tree_let /** * Tree structure for mapping a (possible single element) * sequence of key combinations or strings to another - * combination or string or sequence there of + * combination or string or sequence thereof + * + * Inside functions this can be used for the return value, + * in such case `sequence` should not be `NULL` but + * `sequence.next` and `result` should be `NULL` */ typedef struct mds_kbdc_tree_map { diff --git a/test-files/mds-kbdc/make-tree/valid/assumption b/test-files/mds-kbdc/make-tree/valid/assumption new file mode 100644 index 0000000..1be3caf --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/assumption @@ -0,0 +1,7 @@ +assumption +end assumption + +# (assumption (@ 1 0-10) +# (.inner nil) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/assumption-filled b/test-files/mds-kbdc/make-tree/valid/assumption-filled new file mode 100644 index 0000000..fbf8a3c --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/assumption-filled @@ -0,0 +1,24 @@ +assumption + have " " + have <dead compose> + have_chars ",." + have_range "0" "9" +end assumption + +# (assumption (@ 1 0-10) +# (.inner +# (have (@ 2 2-6) +# (.data +# (string (@ 2 7-10) ‘" "’) +# ) +# ) +# (have (@ 3 2-6) +# (.data +# (keys (@ 3 7-21) ‘<dead compose>’) +# ) +# ) +# (have_chars (@ 4 2-12) ‘",."’) +# (have_range (@ 5 2-12) ‘"0"’ ‘"9"’) +# ) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/break b/test-files/mds-kbdc/make-tree/valid/break new file mode 100644 index 0000000..f6441ce --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/break @@ -0,0 +1,4 @@ +break + +# (break (@ 1 0-5)) + diff --git a/test-files/mds-kbdc/make-tree/valid/continue b/test-files/mds-kbdc/make-tree/valid/continue new file mode 100644 index 0000000..0a7f39f --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/continue @@ -0,0 +1,4 @@ +continue + +# (continue (@ 1 0-8)) + diff --git a/test-files/mds-kbdc/make-tree/valid/function b/test-files/mds-kbdc/make-tree/valid/function new file mode 100644 index 0000000..99b44f7 --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/function @@ -0,0 +1,15 @@ +function add/3 + \add(\1 \add(\2 \3)) +end function + +# (function (@ 1 0-8) ‘add/3’ +# (.inner +# (map (@ 2 2-2) +# (.sequence +# (keys (@ 2 2-22) ‘\add(\1 \add(\2 \3))’) +# ) +# (.result nil) +# ) +# ) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/if b/test-files/mds-kbdc/make-tree/valid/if new file mode 100644 index 0000000..44ca203 --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/if @@ -0,0 +1,18 @@ +if \1 + <letter \1> : "\1" +end if + +# (if (@ 1 0-2) ‘\1’ +# (.inner +# (map (@ 2 2-2) +# (.sequence +# (keys (@ 2 2-13) ‘<letter \1>’) +# ) +# (.result +# (string (@ 2 16-20) ‘"\1"’) +# ) +# ) +# ) +# (.otherwise nil) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/if-else b/test-files/mds-kbdc/make-tree/valid/if-else new file mode 100644 index 0000000..217f478 --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/if-else @@ -0,0 +1,29 @@ +if \1 + <letter \1> : "\1" +else + <letter \2> : "\2" +end if + +# (if (@ 1 0-2) ‘\1’ +# (.inner +# (map (@ 2 2-2) +# (.sequence +# (keys (@ 2 2-13) ‘<letter \1>’) +# ) +# (.result +# (string (@ 2 16-20) ‘"\1"’) +# ) +# ) +# ) +# (.otherwise nil +# (map (@ 4 2-2) +# (.sequence +# (keys (@ 4 2-13) ‘<letter \2>’) +# ) +# (.result +# (string (@ 4 16-20) ‘"\2"’) +# ) +# ) +# ) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/if-else-if b/test-files/mds-kbdc/make-tree/valid/if-else-if new file mode 100644 index 0000000..fe88c43 --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/if-else-if @@ -0,0 +1,36 @@ +if \1 + <letter \1> : "\1" +else + if \2 + <letter \2> : "\2" + end if +end if + +# (if (@ 1 0-2) ‘\1’ +# (.inner +# (map (@ 2 2-2) +# (.sequence +# (keys (@ 2 2-13) ‘<letter \1>’) +# ) +# (.result +# (string (@ 2 16-20) ‘"\1"’) +# ) +# ) +# ) +# (.otherwise +# (if (@ 4 2-4) ‘\2’ +# (.inner +# (map (@ 5 4-4) +# (.sequence +# (keys (@ 5 4-15) ‘<letter \2>’) +# ) +# (.result +# (string (@ 5 18-22) ‘"\2"’) +# ) +# ) +# ) +# (.otherwise nil) +# ) +# ) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/if-elseif b/test-files/mds-kbdc/make-tree/valid/if-elseif new file mode 100644 index 0000000..44d8d1f --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/if-elseif @@ -0,0 +1,34 @@ +if \1 + <letter \1> : "\1" +else if \2 + <letter \2> : "\2" +end if + +# (if (@ 1 0-2) ‘\1’ +# (.inner +# (map (@ 2 2-2) +# (.sequence +# (keys (@ 2 2-13) ‘<letter \1>’) +# ) +# (.result +# (string (@ 2 16-20) ‘"\1"’) +# ) +# ) +# ) +# (.otherwise +# (if (@ 3 3-7) ‘\2’ +# (.inner +# (map (@ 4 4-4) +# (.sequence +# (keys (@ 4 4-15) ‘<letter \2>’) +# ) +# (.result +# (string (@ 4 18-22) ‘"\2"’) +# ) +# ) +# ) +# (.otherwise nil) +# ) +# ) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/if-elseif-else b/test-files/mds-kbdc/make-tree/valid/if-elseif-else new file mode 100644 index 0000000..461ebc7 --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/if-elseif-else @@ -0,0 +1,45 @@ +if \1 + <letter \1> : "\1" +else if \2 + <letter \2> : "\2" +else + <letter \3> : "\3" +end if + +# (if (@ 1 0-2) ‘\1’ +# (.inner +# (map (@ 2 2-2) +# (.sequence +# (keys (@ 2 2-13) ‘<letter \1>’) +# ) +# (.result +# (string (@ 2 16-20) ‘"\1"’) +# ) +# ) +# ) +# (.otherwise +# (if (@ 3 3-7) ‘\2’ +# (.inner +# (map (@ 4 4-4) +# (.sequence +# (keys (@ 4 4-15) ‘<letter \2>’) +# ) +# (.result +# (string (@ 4 18-22) ‘"\2"’) +# ) +# ) +# ) +# (.otherwise +# (map (@ 6 4-4) +# (.sequence +# (keys (@ 6 4-15) ‘<letter \3>’) +# ) +# (.result +# (string (@ 6 18-22) ‘"\3"’) +# ) +# ) +# ) +# ) +# ) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/if-if b/test-files/mds-kbdc/make-tree/valid/if-if new file mode 100644 index 0000000..3a63615 --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/if-if @@ -0,0 +1,25 @@ +if \1 + if \2 + <letter \1> : "\2" + end if +end if + +# (if (@ 1 0-2) ‘\1’ +# (.inner +# (if (@ 2 2-4) ‘\1’ +# (.inner +# (map (@ 3 4-4) +# (.sequence +# (keys (@ 3 4-15) ‘<letter \1>’) +# ) +# (.result +# (string (@ 3 18-22) ‘"\2"’) +# ) +# ) +# ) +# (.otherwise nil) +# ) +# ) +# (.otherwise nil) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/include b/test-files/mds-kbdc/make-tree/valid/include new file mode 100644 index 0000000..32dcdf2 --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/include @@ -0,0 +1,4 @@ +include "assumption-filled" + +# (include (@ 1 0-7) ‘"assumption-filled"’) + diff --git a/test-files/mds-kbdc/make-tree/valid/information b/test-files/mds-kbdc/make-tree/valid/information new file mode 100644 index 0000000..1192eaf --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/information @@ -0,0 +1,7 @@ +information +end information + +# (information (@ 1 0-11) +# (.inner nil) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/information-filled b/test-files/mds-kbdc/make-tree/valid/information-filled new file mode 100644 index 0000000..69ce6dd --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/information-filled @@ -0,0 +1,14 @@ +information + language "Language" # test that the quotes ends where it should + country "Country" + variant "Variant" +end information + +# (information (@ 1 0-11) +# (.inner +# (language (@ 2 2-10) ‘"Language"’) +# (country (@ 3 2-9) ‘"Country"’) +# (variant (@ 4 2-9) ‘"Variant"’) +# ) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/macro b/test-files/mds-kbdc/make-tree/valid/macro new file mode 100644 index 0000000..151417b --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/macro @@ -0,0 +1,17 @@ +macro identity/1 + <letter \1> : "\1" +end macro + +# (macro (@ 1 0-5) ‘identity/1’ +# (.inner +# (map (@ 2 2-2) +# (.sequence +# (keys (@ 2 2-13) ‘<letter \1>’) +# ) +# (.result +# (string (@ 2 16-20) ‘"\1"’) +# ) +# ) +# ) +# ) + diff --git a/test-files/mds-kbdc/make-tree/valid/return b/test-files/mds-kbdc/make-tree/valid/return new file mode 100644 index 0000000..eeee7fa --- /dev/null +++ b/test-files/mds-kbdc/make-tree/valid/return @@ -0,0 +1,4 @@ +return + +# (return (@ 1 0-6)) + |