aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mds-kbdc/make-tree.c152
-rw-r--r--src/mds-kbdc/mds-kbdc.c1
-rw-r--r--test-files/mds-kbdc/make-tree/valid/macro_call27
3 files changed, 141 insertions, 39 deletions
diff --git a/src/mds-kbdc/make-tree.c b/src/mds-kbdc/make-tree.c
index b5631da..eace624 100644
--- a/src/mds-kbdc/make-tree.c
+++ b/src/mds-kbdc/make-tree.c
@@ -91,6 +91,21 @@
/**
+ * Pointer to the beginning of the current line
+ */
+#define LINE \
+ (source_code.lines[line_i])
+
+
+/**
+ * Update the tip of the stack to point to the address
+ * of the current stack's tip's `next`-member
+ */
+#define NEXT \
+ tree_stack[stack_ptr] = &(tree_stack[stack_ptr][0]->next)
+
+
+/**
* Add an error the to error list
*
* @param ERROR_IS_IN_FILE:int Whether the error is in the layout code
@@ -110,8 +125,8 @@
error->line = line_i; \
error->severity = MDS_KBDC_PARSE_ERROR_##SEVERITY; \
error->error_is_in_file = ERROR_IS_IN_FILE; \
- error->start = (size_t)(line - source_code.lines[line_i]); \
- error->end = (size_t)(end - source_code.lines[line_i]); \
+ error->start = (size_t)(line - LINE); \
+ error->end = (size_t)(end - LINE); \
fail_if ((error->pathname = strdup(pathname)) == NULL); \
if (ERROR_IS_IN_FILE) \
fail_if ((error->code = strdup(source_code.real_lines[line_i])) == NULL); \
@@ -124,13 +139,13 @@
* @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_NODE(LOWERCASE, UPPERCASE) \
- mds_kbdc_tree_##LOWERCASE##_t* node; \
- fail_if (xcalloc(node, 1, mds_kbdc_tree_##LOWERCASE##_t)); \
- node->type = MDS_KBDC_TREE_TYPE_##UPPERCASE; \
- node->loc_line = line_i; \
- node->loc_start = (size_t)(line - source_code.lines[line_i]); \
- node->loc_end = (size_t)(end - source_code.lines[line_i])
+#define NEW_NODE(LOWERCASE, UPPERCASE) \
+ mds_kbdc_tree_##LOWERCASE##_t* node; \
+ fail_if (xcalloc(node, 1, mds_kbdc_tree_##LOWERCASE##_t)); \
+ node->type = MDS_KBDC_TREE_TYPE_##UPPERCASE; \
+ node->loc_line = line_i; \
+ node->loc_start = (size_t)(line - LINE); \
+ node->loc_end = (size_t)(end - LINE)
/**
@@ -144,8 +159,8 @@
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])
+ subnode->loc_start = (size_t)(line - LINE); \
+ subnode->loc_end = (size_t)(end - LINE)
/**
@@ -172,9 +187,9 @@
* This is what should be done when a leaf node has been
* created and should be added to the result tree
*/
-#define LEAF \
- *(tree_stack[stack_ptr]) = (mds_kbdc_tree_t*)node; \
- tree_stack[stack_ptr] = &(tree_stack[stack_ptr][0]->next)
+#define LEAF \
+ *(tree_stack[stack_ptr]) = (mds_kbdc_tree_t*)node; \
+ NEXT
/**
@@ -228,8 +243,8 @@
end_end++; \
prev_end_char = *end_end, *end_end = '\0'; \
NEW_ERROR(1, ERROR, "stray ‘%s’ character", name_end); \
- error->start = (size_t)(name_end - source_code.lines[line_i]); \
- error->end = (size_t)(end_end - source_code.lines[line_i]); \
+ error->start = (size_t)(name_end - LINE); \
+ error->end = (size_t)(end_end - LINE); \
*end_end = prev_end_char; \
stray_char = 1; \
} \
@@ -239,8 +254,8 @@
if (*test && !stray_char) \
{ \
NEW_ERROR(1, ERROR, "too many parameters"); \
- error->start = (size_t)(test - source_code.lines[line_i]); \
- error->end = strlen(source_code.lines[line_i]); \
+ error->start = (size_t)(test - LINE); \
+ error->end = strlen(LINE); \
} \
end = name_end; \
prev_end_char = *end; \
@@ -328,7 +343,7 @@
if (*line) \
{ \
NEW_ERROR(1, ERROR, "too many parameters"); \
- error->end = strlen(source_code.lines[line_i]); \
+ error->end = strlen(LINE); \
} \
while (0)
@@ -350,7 +365,7 @@
while (*arg_end && (*arg_end != ' ')) \
arg_end++; \
NEW_ERROR(1, ERROR, "parameter must be in quotes"); \
- error->end = (size_t)(arg_end - source_code.lines[line_i]); \
+ error->end = (size_t)(arg_end - LINE); \
} \
*end = '\0'; \
line = line_; \
@@ -571,7 +586,7 @@
{ \
NEW_ERROR(1, ERROR, "expected ‘%s’ but got ‘%s’", keyword_stack[stack_ptr], line); \
} \
- tree_stack[stack_ptr] = &(tree_stack[stack_ptr][0]->next); \
+ NEXT; \
} \
*end = prev_end_char; \
line++; \
@@ -582,7 +597,7 @@
NO_JUMP; \
PURE_KEYS(keys); \
LEAF; \
- node->loc_end = (size_t)(line - source_code.lines[line_i]); \
+ node->loc_end = (size_t)(line - LINE); \
} \
else \
{ \
@@ -590,7 +605,7 @@
NO_JUMP; \
CHARS(string); \
LEAF; \
- node->loc_end = (size_t)(line - source_code.lines[line_i]); \
+ node->loc_end = (size_t)(line - LINE); \
} \
} \
while (1)
@@ -684,7 +699,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
size_t max_line_length = 0, cur_line_length;
for (line_i = 0, line_n = source_code.line_count; line_i < line_n; line_i++)
{
- cur_line_length = strlen(source_code.lines[line_i]);
+ cur_line_length = strlen(LINE);
if (max_line_length < cur_line_length)
max_line_length = cur_line_length;
}
@@ -697,7 +712,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
for (line_i = 0, line_n = source_code.line_count; line_i < line_n; line_i++)
{
- char* line = source_code.lines[line_i];
+ char* line = LINE;
char* end;
char prev_end_char;
char* original;
@@ -729,7 +744,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
line = end, prev_end_char = '\0';
in_array = 0;
stack_ptr -= 2;
- tree_stack[stack_ptr] = &(tree_stack[stack_ptr][0]->next);
+ NEXT;
break;
}
else
@@ -739,7 +754,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
NO_JUMP;
CHARS(string);
LEAF;
- node->loc_end = (size_t)(end - source_code.lines[line_i]);
+ node->loc_end = (size_t)(end - LINE);
*end = prev_end_char;
line = end;
#undef node
@@ -848,7 +863,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
mds_kbdc_tree_if_t* supernode = &(tree_stack[stack_ptr - 1][0]->if_);
if (supernode->otherwise)
{
- line = strstr(source_code.lines[line_i], "else");
+ line = strstr(LINE, "else");
end = line + 4, prev_end_char = *end;
NEW_ERROR(1, ERROR, "multiple ‘else’ statements");
mds_kbdc_tree_free(supernode->otherwise);
@@ -914,7 +929,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
NEW_NODE(string, STRING);
NO_JUMP;
CHARS(string);
- node->loc_end = (size_t)(end - source_code.lines[line_i]);
+ node->loc_end = (size_t)(end - LINE);
#undef node
node->value = (mds_kbdc_tree_t*)subnode;
END;
@@ -975,9 +990,9 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
{
NEW_ERROR(1, ERROR, "expected ‘%s’ but got ‘%s’", keyword_stack[stack_ptr], line);
}
- tree_stack[stack_ptr] = &(tree_stack[stack_ptr][0]->next);
+ NEXT;
}
- else if (strchr("\"<([", *line) || strchr(line, '(')) /* TODO macro calls */
+ else if (strchr("\"<([0123456789", *line))
{
size_t stack_orig = stack_ptr + 1;
#define node supernode
@@ -1017,13 +1032,72 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
end = line + strlen(line), prev_end_char = *end;
NEW_ERROR(1, ERROR, "too many parameters");
}
- else if (strchr("}", *line))
- {
- NEW_ERROR(1, ERROR, "runaway ‘%c’", *line);
- }
else
{
- NEW_ERROR(1, ERROR, "invalid syntax ‘%s’", line);
+ char* old_end = end;
+ char old_prev_end_char = prev_end_char;
+ *end = prev_end_char;
+ end = strchrnul(line, '(');
+ prev_end_char = *end, *end = '\0';
+ if (prev_end_char)
+ {
+ NEW_NODE(macro_call, MACRO_CALL);
+ NO_JUMP;
+ CHARS(name);
+#define inner arguments
+ BRANCH(NULL);
+#undef inner
+ line++;
+ for (;;)
+ {
+ *end = prev_end_char;
+ while (*line && (*line == ' '))
+ line++;
+ if (*line == '\0')
+ {
+ NEW_ERROR(1, ERROR, "missing ‘)’");
+ error->start = (size_t)(strchr(LINE, '(') - LINE);
+ error->end = error->start + 1;
+ break;
+ }
+ else if (*line == ')')
+ {
+ line++;
+ while (*line && (*line == ' '))
+ line++;
+ if (*line)
+ {
+ NEW_ERROR(1, ERROR, "extra token after macro call");
+ error->end = strlen(LINE);
+ }
+ break;
+ }
+ else
+ {
+#define node subnode
+ NEW_NODE(string, STRING);
+ NO_JUMP;
+ CHARS(string);
+ LEAF;
+ node->loc_end = (size_t)(line - LINE);
+#undef node
+ }
+ }
+ stack_ptr--;
+ NEXT;
+ goto next;
+ }
+ *old_end = '\0';
+ end = old_end;
+ prev_end_char = old_prev_end_char;
+ if (strchr("}", *line))
+ {
+ NEW_ERROR(1, ERROR, "runaway ‘%c’", *line);
+ }
+ else
+ {
+ NEW_ERROR(1, ERROR, "invalid syntax ‘%s’", line);
+ }
}
next:
@@ -1045,8 +1119,8 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
if (keyword_stack[stack_ptr] == NULL)
continue;
line_i = tree_stack[stack_ptr][0]->loc_line;
- line = source_code.lines[line_i] + tree_stack[stack_ptr][0]->loc_start;
- end = source_code.lines[line_i] + tree_stack[stack_ptr][0]->loc_end;
+ line = LINE + tree_stack[stack_ptr][0]->loc_start;
+ end = LINE + tree_stack[stack_ptr][0]->loc_end;
if (!strcmp(keyword_stack[stack_ptr], "}"))
{
NEW_ERROR(1, NOTE, "missing associated ‘%s’", keyword_stack[stack_ptr]);
@@ -1096,6 +1170,8 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu
#undef BRANCH
#undef NEW_NODE
#undef NEW_ERROR
+#undef NEXT
+#undef LINE
#undef is_name_char
#undef in_range
#undef xasprintf
diff --git a/src/mds-kbdc/mds-kbdc.c b/src/mds-kbdc/mds-kbdc.c
index 82702c4..dc3327f 100644
--- a/src/mds-kbdc/mds-kbdc.c
+++ b/src/mds-kbdc/mds-kbdc.c
@@ -60,7 +60,6 @@ int main(int argc_, char** argv_)
if (fatal)
return mds_kbdc_tree_free(tree), 1;
}
-
mds_kbdc_tree_free(tree);
return 0;
diff --git a/test-files/mds-kbdc/make-tree/valid/macro_call b/test-files/mds-kbdc/make-tree/valid/macro_call
new file mode 100644
index 0000000..b1a1405
--- /dev/null
+++ b/test-files/mds-kbdc/make-tree/valid/macro_call
@@ -0,0 +1,27 @@
+mac0()
+mac1(0)
+mac2(1 "a")
+mac3("x" "y" "z")
+
+# (macro_call (@ 1 0-4) ‘mac0’
+# (.arguments nil)
+# )
+# (macro_call (@ 2 0-4) ‘mac1’
+# (.arguments
+# (string (@ 2 5-6) ‘0’)
+# )
+# )
+# (macro_call (@ 3 0-4) ‘mac2’
+# (.arguments
+# (string (@ 3 5-6) ‘1’)
+# (string (@ 3 7-10) ‘"a"’)
+# )
+# )
+# (macro_call (@ 4 0-4) ‘mac3’
+# (.arguments
+# (string (@ 4 5-8) ‘"x"’)
+# (string (@ 4 9-12) ‘"y"’)
+# (string (@ 4 13-16) ‘"z"’)
+# )
+# )
+