aboutsummaryrefslogtreecommitdiffstats
path: root/src/mds-kbdc/simplify-tree.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mds-kbdc/simplify-tree.c1283
1 files changed, 634 insertions, 649 deletions
diff --git a/src/mds-kbdc/simplify-tree.c b/src/mds-kbdc/simplify-tree.c
index d559e2e..b3f588c 100644
--- a/src/mds-kbdc/simplify-tree.c
+++ b/src/mds-kbdc/simplify-tree.c
@@ -27,13 +27,13 @@
/**
* This process's value for `mds_kbdc_tree_t.processed`
*/
-#define PROCESS_LEVEL 2
+#define PROCESS_LEVEL 2
/**
* Tree type constant shortener
*/
-#define C(TYPE) MDS_KBDC_TREE_TYPE_##TYPE
+#define C(TYPE) MDS_KBDC_TREE_TYPE_##TYPE
/**
@@ -44,9 +44,9 @@
* @param ...:const char*, ... Error description format string and arguments
* @scope error:mds_kbdc_parse_error_t* Variable where the new error will be stored
*/
-#define NEW_ERROR(NODE, SEVERITY, ...) \
- NEW_ERROR_(result, SEVERITY, 1, (NODE)->loc_line, \
- (NODE)->loc_start, (NODE)->loc_end, 1, __VA_ARGS__)
+#define NEW_ERROR(NODE, SEVERITY, ...)\
+ NEW_ERROR_(result, SEVERITY, 1, (NODE)->loc_line,\
+ (NODE)->loc_start, (NODE)->loc_end, 1, __VA_ARGS__)
@@ -58,25 +58,25 @@
* @scope here:mds_kbdc_tree_t** Help variable that must be available for use
* @scope argument:mds_kbdc_tree_t* Help variable that must be available for use
*/
-#define REMOVE_NOTHING(START) \
- do \
- { \
- long processed = tree->processed; \
- tree->processed = PROCESS_LEVEL; \
- for (here = &(tree->START); *here;) \
- if ((*here)->type != C(NOTHING)) \
- here = &((*here)->next); \
- else \
- while (*here && (*here)->type == C(NOTHING)) \
- { \
- argument = (*here)->next, (*here)->next = NULL; \
- if ((processed != PROCESS_LEVEL) && ((*here)->processed != PROCESS_LEVEL)) \
- NEW_ERROR(*here, WARNING, "‘.’ outside alternation has no effect"); \
- mds_kbdc_tree_free(*here); \
- *here = argument; \
- } \
- } \
- while (0)
+#define REMOVE_NOTHING(START)\
+ do {\
+ long int processed = tree->processed;\
+ tree->processed = PROCESS_LEVEL;\
+ for (here = &(tree->START); *here;) {\
+ if ((*here)->type != C(NOTHING)) {\
+ here = &((*here)->next);\
+ } else {\
+ while (*here && (*here)->type == C(NOTHING)) {\
+ argument = (*here)->next;\
+ (*here)->next = NULL;\
+ if (processed != PROCESS_LEVEL && (*here)->processed != PROCESS_LEVEL)\
+ NEW_ERROR(*here, WARNING, "‘.’ outside alternation has no effect");\
+ mds_kbdc_tree_free(*here);\
+ *here = argument;\
+ }\
+ }\
+ }\
+ } while (0)
@@ -89,38 +89,36 @@
* @scope here:mds_kbdc_tree_t** Pointer to the space where the argument was found
* @scope temp:mds_kbdc_tree_t* Help variable that must be available for use
*/
-#define FLATTEN(argument) \
- do \
- { \
- /* Remember the alternation/subsequence and the argument that follows it. */ \
- mds_kbdc_tree_t* eliminated_argument = argument; \
- temp = argument->next; \
- /* Find the last alternative/element. */ \
- for (argument->next = argument->ordered.inner; argument->next;) \
- argument = argument->next; \
- /* Attach the argument that was after the alternation/subsequence to the */ \
- /* end of the alternation/subsequence, that is, flatten the right side. */ \
- argument->next = temp; \
- /* Flatten the left side. */ \
- *here = eliminated_argument->next; \
- /* Free the memory of the alternation/subsequence. */ \
- eliminated_argument->ordered.inner = NULL; \
- eliminated_argument->next = NULL; \
- mds_kbdc_tree_free(eliminated_argument); \
- } \
- while (0)
+#define FLATTEN(argument)\
+ do {\
+ /* Remember the alternation/subsequence and the argument that follows it. */\
+ mds_kbdc_tree_t *eliminated_argument = argument;\
+ temp = argument->next;\
+ /* Find the last alternative/element. */\
+ for (argument->next = argument->ordered.inner; argument->next;)\
+ argument = argument->next;\
+ /* Attach the argument that was after the alternation/subsequence to the */\
+ /* end of the alternation/subsequence, that is, flatten the right side. */\
+ argument->next = temp;\
+ /* Flatten the left side. */\
+ *here = eliminated_argument->next;\
+ /* Free the memory of the alternation/subsequence. */\
+ eliminated_argument->ordered.inner = NULL;\
+ eliminated_argument->next = NULL;\
+ mds_kbdc_tree_free(eliminated_argument);\
+ } while (0)
/**
* Variable whether the latest created error is stored
*/
-static mds_kbdc_parse_error_t* error;
+static mds_kbdc_parse_error_t *error;
/**
* The parameter of `simplify_tree`
*/
-static mds_kbdc_parsed_t* restrict result;
+static mds_kbdc_parsed_t *restrict result;
@@ -130,7 +128,7 @@ static mds_kbdc_parsed_t* restrict result;
* @param tree The tree
* @return Zero on success, -1 on error
*/
-static int simplify(mds_kbdc_tree_t* restrict tree);
+static int simplify(mds_kbdc_tree_t *restrict tree);
/**
* Simplify an unordered subsequence-subtree
@@ -138,7 +136,7 @@ static int simplify(mds_kbdc_tree_t* restrict tree);
* @param tree The unordered subsequence-subtree
* @return Zero on success, -1 on error
*/
-static int simplify_unordered(mds_kbdc_tree_unordered_t* restrict tree);
+static int simplify_unordered(mds_kbdc_tree_unordered_t *restrict tree);
@@ -150,60 +148,61 @@ static int simplify_unordered(mds_kbdc_tree_unordered_t* restrict tree);
* @param argument_index The index of the argument to eliminate
* @return Zero on sucess, -1 on error
*/
-static int eliminate_alternation(mds_kbdc_tree_t* tree, mds_kbdc_tree_t* argument, size_t argument_index)
+static int
+eliminate_alternation(mds_kbdc_tree_t *tree, mds_kbdc_tree_t *argument, size_t argument_index)
{
- mds_kbdc_tree_t** here;
- mds_kbdc_tree_t* first;
- mds_kbdc_tree_t* last;
- mds_kbdc_tree_t* new_tree;
- mds_kbdc_tree_t* alternative;
- mds_kbdc_tree_t* next_statement;
- mds_kbdc_tree_t* next_alternative;
- mds_kbdc_tree_t* new_argument;
- size_t i;
- int saved_errno;
-
- /* Detach next statement, we do not want to duplicate all following statements. */
- next_statement = tree->next, tree->next = NULL;
- /* Detach alternation, we replace it in all duplcates,
- no need to duplicate all alternatives. */
- alternative = argument->alternation.inner, argument->alternation.inner = NULL;
- /* Eliminate. */
- for (first = last = NULL; alternative; alternative = next_alternative)
- {
- /* Duplicate statement. */
- fail_if (new_tree = mds_kbdc_tree_dup(tree), new_tree == NULL);
- /* Join trees. */
- if (last)
- last->next = new_tree;
- last = new_tree;
- first = first ? first : new_tree;
- /* Jump to the alternation. */
- here = &(new_tree->macro_call.arguments); /* `new_tree->macro_call.arguments` and
- * `new_tree->map.sequence` as the same address. */
- for (new_argument = *here, i = 0; i < argument_index; i++, here = &((*here)->next))
- new_argument = new_argument->next;
- /* Detach alternative. */
- next_alternative = alternative->next;
- /* Right-join alternative. */
- alternative->next = new_argument->next, new_argument->next = NULL;
- mds_kbdc_tree_free(new_argument);
- /* Left-join alternative. */
- *here = alternative;
- }
- /* Replace the statement with the first generated statement without the alternation. */
- mds_kbdc_tree_destroy((mds_kbdc_tree_t*)tree);
- memcpy(tree, first, sizeof(mds_kbdc_tree_t));
- if (first == last) last = (mds_kbdc_tree_t*)tree;
- free(first);
- /* Reattach the statement that followed to the last generated statement. */
- last->next = next_statement;
- return 0;
- fail:
- saved_errno = errno;
- argument->alternation.inner = alternative;
- tree->next = next_statement;
- return errno = saved_errno, -1;
+ mds_kbdc_tree_t **here;
+ mds_kbdc_tree_t *first;
+ mds_kbdc_tree_t *last;
+ mds_kbdc_tree_t *new_tree;
+ mds_kbdc_tree_t *alternative;
+ mds_kbdc_tree_t *next_statement;
+ mds_kbdc_tree_t *next_alternative;
+ mds_kbdc_tree_t *new_argument;
+ size_t i;
+ int saved_errno;
+
+ /* Detach next statement, we do not want to duplicate all following statements. */
+ next_statement = tree->next, tree->next = NULL;
+ /* Detach alternation, we replace it in all duplcates,
+ no need to duplicate all alternatives. */
+ alternative = argument->alternation.inner, argument->alternation.inner = NULL;
+ /* Eliminate. */
+ for (first = last = NULL; alternative; alternative = next_alternative) {
+ /* Duplicate statement. */
+ fail_if (!(new_tree = mds_kbdc_tree_dup(tree)));
+ /* Join trees. */
+ if (last)
+ last->next = new_tree;
+ last = new_tree;
+ first = first ? first : new_tree;
+ /* Jump to the alternation. */
+ here = &(new_tree->macro_call.arguments); /* `new_tree->macro_call.arguments` and
+ * `new_tree->map.sequence` as the same address. */
+ for (new_argument = *here, i = 0; i < argument_index; i++, here = &((*here)->next))
+ new_argument = new_argument->next;
+ /* Detach alternative. */
+ next_alternative = alternative->next;
+ /* Right-join alternative. */
+ alternative->next = new_argument->next, new_argument->next = NULL;
+ mds_kbdc_tree_free(new_argument);
+ /* Left-join alternative. */
+ *here = alternative;
+ }
+ /* Replace the statement with the first generated statement without the alternation. */
+ mds_kbdc_tree_destroy((mds_kbdc_tree_t*)tree);
+ memcpy(tree, first, sizeof(mds_kbdc_tree_t));
+ if (first == last)
+ last = (mds_kbdc_tree_t*)tree;
+ free(first);
+ /* Reattach the statement that followed to the last generated statement. */
+ last->next = next_statement;
+ return 0;
+fail:
+ saved_errno = errno;
+ argument->alternation.inner = alternative;
+ tree->next = next_statement;
+ return errno = saved_errno, -1;
}
@@ -213,118 +212,119 @@ static int eliminate_alternation(mds_kbdc_tree_t* tree, mds_kbdc_tree_t* argumen
* @param tree The macro call-subtree
* @return Zero on success, -1 on error
*/
-static int simplify_macro_call(mds_kbdc_tree_macro_call_t* restrict tree)
+static int
+simplify_macro_call(mds_kbdc_tree_macro_call_t *restrict tree)
{
- mds_kbdc_tree_t* argument;
- mds_kbdc_tree_t* dup_arguments = NULL;
- mds_kbdc_tree_t** here;
- char* full_macro_name;
- size_t argument_index = 0;
- int saved_errno;
-
- /* Simplify arguments. */
- for (argument = tree->arguments; argument; argument = argument->next)
- fail_if (simplify(argument));
-
- /* Remove ‘.’:s. */
- REMOVE_NOTHING(arguments);
-
- /* Copy arguments. */
- if (tree->arguments == NULL)
- goto no_args;
- fail_if (dup_arguments = mds_kbdc_tree_dup(tree->arguments), dup_arguments == NULL);
-
- /* Eliminate alterations. */
- for (argument = dup_arguments; argument; argument = argument->next, argument_index++)
- if (argument->type == C(ALTERNATION))
- fail_if (eliminate_alternation((mds_kbdc_tree_t*)tree, argument, argument_index));
- mds_kbdc_tree_free(dup_arguments), dup_arguments = NULL;
-
- /* Add argument count suffix. */
- no_args:
- for (argument_index = 0, argument = tree->arguments; argument; argument = argument->next)
- argument_index++;
- fail_if (xasprintf(full_macro_name, "%s/%zu", tree->name, argument_index));
- free(tree->name), tree->name = full_macro_name;
-
- /* Example of what will happend:
- *
- * my_macro([1 2] [1 2] [1 2]) ## call 1
- *
- * simplify_macro_call on call 1
- * after processing argument 1
- * my_macro(1 [1 2] [1 2]) ## call 1
- * my_macro(2 [1 2] [1 2]) ## call 5
- * after processing argument 2
- * my_macro(1 1 [1 2]) ## call 1
- * my_macro(1 2 [1 2]) ## call 3
- * my_macro(2 [1 2] [1 2]) ## call 5
- * after processing argument 3
- * my_macro(1 1 1) ## call 1
- * my_macro(1 1 2) ## call 2
- * my_macro(1 2 [1 2]) ## call 3
- * my_macro(2 [1 2] [1 2]) ## call 5
- *
- * no difference after simplify_macro_call on call 2
- *
- * simplify_macro_call on call 3
- * no difference after processing argument 1
- * no difference after processing argument 2
- * after processing argument 3
- * my_macro(1 1 1) ## (call 1)
- * my_macro(1 1 2) ## (call 2)
- * my_macro(1 2 1) ## call 3
- * my_macro(1 2 1) ## call 4
- * my_macro(2 [1 2] [1 2]) ## call 5
- *
- * no difference after simplify_macro_call on call 4
- *
- * simplify_macro_call on call 5
- * no difference after processing argument 1
- * after processing argument 2
- * my_macro(1 1 1) ## (call 1)
- * my_macro(1 1 2) ## (call 2)
- * my_macro(1 2 1) ## (call 3)
- * my_macro(1 2 2) ## (call 4)
- * my_macro(2 1 [1 2]) ## call 5
- * my_macro(2 2 [1 2]) ## call 7
- * after processing argument 3
- * my_macro(1 1 1) ## (call 1)
- * my_macro(1 1 2) ## (call 2)
- * my_macro(1 2 1) ## (call 3)
- * my_macro(1 2 2) ## (call 4)
- * my_macro(2 1 1) ## call 5
- * my_macro(2 1 2) ## call 6
- * my_macro(2 2 [1 2]) ## call 7
- *
- * no difference after simplify_macro_call on call 6
- *
- * simplify_macro_call on call 7
- * no difference after processing argument 1
- * no difference after processing argument 2
- * after processing argument 3
- * my_macro(1 1 1) ## (call 1)
- * my_macro(1 1 2) ## (call 2)
- * my_macro(1 2 1) ## (call 3)
- * my_macro(1 2 2) ## (call 4)
- * my_macro(2 1 1) ## (call 5)
- * my_macro(2 1 2) ## (call 6)
- * my_macro(2 2 1) ## call 7
- * my_macro(2 2 2) ## call 8
- *
- * no difference after simplify_macro_call on call 8
- *
- * Nothings (‘.’) are removed before processing the alternations.
- *
- * It should also be noticed that all macro names are update to
- * with the argument count suffix.
- */
-
- return 0;
- fail:
- saved_errno = errno;
- mds_kbdc_tree_free(dup_arguments);
- return errno = saved_errno, -1;
+ mds_kbdc_tree_t *argument;
+ mds_kbdc_tree_t *dup_arguments = NULL;
+ mds_kbdc_tree_t **here;
+ char *full_macro_name;
+ size_t argument_index = 0;
+ int saved_errno;
+
+ /* Simplify arguments. */
+ for (argument = tree->arguments; argument; argument = argument->next)
+ fail_if (simplify(argument));
+
+ /* Remove ‘.’:s. */
+ REMOVE_NOTHING(arguments);
+
+ /* Copy arguments. */
+ if (!tree->arguments)
+ goto no_args;
+ fail_if (!(dup_arguments = mds_kbdc_tree_dup(tree->arguments)));
+
+ /* Eliminate alterations. */
+ for (argument = dup_arguments; argument; argument = argument->next, argument_index++)
+ if (argument->type == C(ALTERNATION))
+ fail_if (eliminate_alternation((mds_kbdc_tree_t*)tree, argument, argument_index));
+ mds_kbdc_tree_free(dup_arguments), dup_arguments = NULL;
+
+ /* Add argument count suffix. */
+no_args:
+ for (argument_index = 0, argument = tree->arguments; argument; argument = argument->next)
+ argument_index++;
+ fail_if (xasprintf(full_macro_name, "%s/%zu", tree->name, argument_index));
+ free(tree->name), tree->name = full_macro_name;
+
+ /* Example of what will happend:
+ *
+ * my_macro([1 2] [1 2] [1 2]) ## call 1
+ *
+ * simplify_macro_call on call 1
+ * after processing argument 1
+ * my_macro(1 [1 2] [1 2]) ## call 1
+ * my_macro(2 [1 2] [1 2]) ## call 5
+ * after processing argument 2
+ * my_macro(1 1 [1 2]) ## call 1
+ * my_macro(1 2 [1 2]) ## call 3
+ * my_macro(2 [1 2] [1 2]) ## call 5
+ * after processing argument 3
+ * my_macro(1 1 1) ## call 1
+ * my_macro(1 1 2) ## call 2
+ * my_macro(1 2 [1 2]) ## call 3
+ * my_macro(2 [1 2] [1 2]) ## call 5
+ *
+ * no difference after simplify_macro_call on call 2
+ *
+ * simplify_macro_call on call 3
+ * no difference after processing argument 1
+ * no difference after processing argument 2
+ * after processing argument 3
+ * my_macro(1 1 1) ## (call 1)
+ * my_macro(1 1 2) ## (call 2)
+ * my_macro(1 2 1) ## call 3
+ * my_macro(1 2 1) ## call 4
+ * my_macro(2 [1 2] [1 2]) ## call 5
+ *
+ * no difference after simplify_macro_call on call 4
+ *
+ * simplify_macro_call on call 5
+ * no difference after processing argument 1
+ * after processing argument 2
+ * my_macro(1 1 1) ## (call 1)
+ * my_macro(1 1 2) ## (call 2)
+ * my_macro(1 2 1) ## (call 3)
+ * my_macro(1 2 2) ## (call 4)
+ * my_macro(2 1 [1 2]) ## call 5
+ * my_macro(2 2 [1 2]) ## call 7
+ * after processing argument 3
+ * my_macro(1 1 1) ## (call 1)
+ * my_macro(1 1 2) ## (call 2)
+ * my_macro(1 2 1) ## (call 3)
+ * my_macro(1 2 2) ## (call 4)
+ * my_macro(2 1 1) ## call 5
+ * my_macro(2 1 2) ## call 6
+ * my_macro(2 2 [1 2]) ## call 7
+ *
+ * no difference after simplify_macro_call on call 6
+ *
+ * simplify_macro_call on call 7
+ * no difference after processing argument 1
+ * no difference after processing argument 2
+ * after processing argument 3
+ * my_macro(1 1 1) ## (call 1)
+ * my_macro(1 1 2) ## (call 2)
+ * my_macro(1 2 1) ## (call 3)
+ * my_macro(1 2 2) ## (call 4)
+ * my_macro(2 1 1) ## (call 5)
+ * my_macro(2 1 2) ## (call 6)
+ * my_macro(2 2 1) ## call 7
+ * my_macro(2 2 2) ## call 8
+ *
+ * no difference after simplify_macro_call on call 8
+ *
+ * Nothings (‘.’) are removed before processing the alternations.
+ *
+ * It should also be noticed that all macro names are update to
+ * with the argument count suffix.
+ */
+
+ return 0;
+fail:
+ saved_errno = errno;
+ mds_kbdc_tree_free(dup_arguments);
+ return errno = saved_errno, -1;
}
@@ -334,26 +334,27 @@ static int simplify_macro_call(mds_kbdc_tree_macro_call_t* restrict tree)
* @param tree The value statement-tree
* @return Zero on success, -1 on error
*/
-static int check_value_statement_before_simplification(mds_kbdc_tree_map_t* restrict tree)
+static int
+check_value_statement_before_simplification(mds_kbdc_tree_map_t *restrict tree)
{
- again:
- /* Check for alternation. */
- if ((tree->sequence->type == C(ALTERNATION)) && (tree->processed != PROCESS_LEVEL))
- NEW_ERROR(tree->sequence, WARNING,
- "alternated value statement is undefined unless the alternatives are identical");
-
- /* Check for unordered. */
- if (tree->sequence->type != C(UNORDERED))
- return 0;
- if (tree->processed != PROCESS_LEVEL)
- NEW_ERROR(tree->sequence, WARNING, "use of sequence in value statement is discouraged");
-
- /* Simplify argument and start over. */
- fail_if (simplify(tree->sequence));
- goto again;
-
- fail:
- return -1;
+again:
+ /* Check for alternation. */
+ if (tree->sequence->type == C(ALTERNATION) && tree->processed != PROCESS_LEVEL)
+ NEW_ERROR(tree->sequence, WARNING,
+ "alternated value statement is undefined unless the alternatives are identical");
+
+ /* Check for unordered. */
+ if (tree->sequence->type != C(UNORDERED))
+ return 0;
+ if (tree->processed != PROCESS_LEVEL)
+ NEW_ERROR(tree->sequence, WARNING, "use of sequence in value statement is discouraged");
+
+ /* Simplify argument and start over. */
+ fail_if (simplify(tree->sequence));
+ goto again;
+
+fail:
+ return -1;
}
@@ -363,19 +364,20 @@ static int check_value_statement_before_simplification(mds_kbdc_tree_map_t* rest
* @param tree The value statement-tree
* @return Zero on success, -1 on error
*/
-static int check_value_statement_after_simplification(mds_kbdc_tree_map_t* restrict tree)
+static int
+check_value_statement_after_simplification(mds_kbdc_tree_map_t *restrict tree)
{
- /* Check that there is only one value. */
- if (tree->sequence->next)
- NEW_ERROR(tree->sequence->next, ERROR, "more the one value in value statement");
-
- /* Check the type of the value */
- if (tree->sequence->type != C(STRING))
- NEW_ERROR(tree->sequence, ERROR, "bad value type");
-
- return 0;
- fail:
- return -1;
+ /* Check that there is only one value. */
+ if (tree->sequence->next)
+ NEW_ERROR(tree->sequence->next, ERROR, "more the one value in value statement");
+
+ /* Check the type of the value */
+ if (tree->sequence->type != C(STRING))
+ NEW_ERROR(tree->sequence, ERROR, "bad value type");
+
+ return 0;
+fail:
+ return -1;
}
@@ -385,155 +387,154 @@ static int check_value_statement_after_simplification(mds_kbdc_tree_map_t* restr
* @param tree The mapping-subtree
* @return Zero on success, -1 on error
*/
-static int simplify_map(mds_kbdc_tree_map_t* restrict tree)
+static int
+simplify_map(mds_kbdc_tree_map_t *restrict tree)
{
- mds_kbdc_tree_t* argument;
- mds_kbdc_tree_t** here;
- mds_kbdc_tree_t* dup_sequence = NULL;
- mds_kbdc_tree_t* temp;
- size_t argument_index;
- int redo = 0, need_reelimination, saved_errno;
-
- /* Check for bad things in the result. */
- for (argument = tree->result; argument; argument = argument->next)
- if ((argument->type != C(KEYS)) && (argument->type != C(STRING)))
- NEW_ERROR(argument, ERROR, "not allowed in mapping output");
-
- /* Valid value properties. */
- if (tree->result == NULL)
- fail_if (check_value_statement_before_simplification(tree));
-
- /* Simplify sequence. */
- for (argument = tree->sequence; argument; argument = argument->next)
- fail_if (simplify(argument));
-
- /* Test predicted emptyness. */
- for (argument = tree->sequence; argument; argument = argument->next)
- if (argument->type != C(NOTHING))
- goto will_not_be_empty;
- if (tree->sequence->processed != PROCESS_LEVEL)
- {
- if (tree->result)
- NEW_ERROR(tree->sequence, ERROR, "mapping of null sequence");
- else
- NEW_ERROR(tree->sequence, ERROR, "nothing in value statement");
- }
- /* The tree parsing process will not allow a mapping statement
- * to start with a ‘.’. Thus if we select to highlight it we
- * know that it is either an empty alternation, an empty
- * unordered subsequence or a nothing inside an alternation.
- * If it is already been processed by the simplifier, it is an
- * error because it is an empty alternation or empty unordered
- * subsequence, and there is not reason to print an additional
- * error. If however it is a nothing inside an alternation we
- * know that it is the cause of the error, however possibily
- * in conjunction with additional such constructs, but those
- * are harder to locate. */
- return 0;
- will_not_be_empty:
-
- /* Remove ‘.’:s. */
- REMOVE_NOTHING(sequence);
-
- /* Because unordered are simplified to alternations of ordered subsequences, which
- in turn can contain alternations, possibiled from simplification of nested
- unordered sequenceses, we need to reeliminated until there are not alternations. */
- for (need_reelimination = 1; need_reelimination ? (need_reelimination = 0, 1) : 0; redo = 0)
- {
- /* Copy sequence. */
- fail_if (dup_sequence = mds_kbdc_tree_dup(tree->sequence), dup_sequence == NULL);
-
- /* Eliminate alterations, remember, unordered subsequences have
- been simplified to alternations of ordered subsequences. */
- for (argument_index = 0, argument = dup_sequence; argument; argument = argument->next, argument_index++)
- if (argument->type == C(ALTERNATION))
- fail_if (eliminate_alternation((mds_kbdc_tree_t*)tree, argument, argument_index));
-
- mds_kbdc_tree_free(dup_sequence), dup_sequence = NULL;
-
- /* Eliminated ordered subsequences. */
- for (here = &(tree->sequence); (argument = *here); redo ? (redo = 0) : (here = &(argument->next), 0))
- if (argument->type == C(ORDERED))
- {
- FLATTEN(argument);
- redo = 1;
- }
- else if (argument->type == C(ALTERNATION))
- need_reelimination = 1;
- }
-
- /* Valid value properties. */
- if (tree->result == NULL)
- fail_if (check_value_statement_after_simplification(tree));
-
- /* Mapping statements are simplified in a manner similar
- * to how macro calls are simplified. However mapping
- * statements can also contain unordered subsequences,
- * there are translated into alternations of ordered
- * subsequences. Thus after the elimination of alternations,
- * ordered subsequences are eliminated too.
- *
- * Example of what will happen, ‘{ }’ represents an
- * ordered subsequence:
- *
- * (1 2) (3 4) : 0 ## mapping 1
- *
- * simplify_map on mapping 1
- * after simplification
- * [{1 2} {2 1}] [{3 4} {4 3}] ## mapping 1
- * after alternation elimination on argument 1
- * {1 2} [{3 4} {4 3}] ## mapping 1
- * {2 1} [{3 4} {4 3}] ## mapping 3
- * after alternation elimination on argument 2
- * {1 2} {3 4} ## mapping 1
- * {1 2} {4 3} ## mapping 2
- * {2 1} [{3 4} {4 3}] ## mapping 3
- * after ordered subsequence elimination
- * 1 2 3 4 ## mapping 1
- * {1 2} {4 3} ## mapping 2
- * {2 1} [{3 4} {4 3}] ## mapping 3
- *
- * simplify_map on mapping 2
- * no difference after simplification
- * no difference after alternation elimination on argument 1
- * no difference after alternation elimination on argument 2
- * after ordered subsequence elimination
- * 1 2 3 4 ## (mapping 1)
- * 1 2 4 3 ## mapping 2
- * {2 1} [{3 4} {4 3}] ## mapping 3
- *
- * simplify_map on mapping 3
- * no difference after simplification
- * no difference after alternation elimination on argument 1
- * after alternation elimination on argument 2
- * 1 2 3 4 ## (mapping 1)
- * 1 2 4 3 ## (mapping 2)
- * {2 1} {3 4} ## mapping 3
- * {2 1} {4 3} ## mapping 4
- * after ordered subsequence elimination
- * 1 2 3 4 ## (mapping 1)
- * 1 2 4 3 ## (mapping 2)
- * 2 1 3 4 ## mapping 3
- * {2 1} {4 3} ## mapping 4
- *
- * simplify_map on mapping 4
- * no difference after simplification
- * no difference after alternation elimination on argument 1
- * no difference after alternation elimination on argument 2
- * after ordered subsequence elimination
- * 1 2 3 4 ## (mapping 1)
- * 1 2 4 3 ## (mapping 2)
- * 2 1 3 4 ## (mapping 3)
- * 2 1 4 3 ## mapping 4
- *
- * Nothings (‘.’) are removed before processing the alternations.
- */
-
- return 0;
- fail:
- saved_errno = errno;
- mds_kbdc_tree_free(dup_sequence);
- return errno = saved_errno, -1;
+ mds_kbdc_tree_t *argument;
+ mds_kbdc_tree_t **here;
+ mds_kbdc_tree_t *dup_sequence = NULL;
+ mds_kbdc_tree_t *temp;
+ size_t argument_index;
+ int redo = 0, need_reelimination, saved_errno;
+
+ /* Check for bad things in the result. */
+ for (argument = tree->result; argument; argument = argument->next)
+ if (argument->type != C(KEYS) && argument->type != C(STRING))
+ NEW_ERROR(argument, ERROR, "not allowed in mapping output");
+
+ /* Valid value properties. */
+ if (!tree->result)
+ fail_if (check_value_statement_before_simplification(tree));
+
+ /* Simplify sequence. */
+ for (argument = tree->sequence; argument; argument = argument->next)
+ fail_if (simplify(argument));
+
+ /* Test predicted emptyness. */
+ for (argument = tree->sequence; argument; argument = argument->next)
+ if (argument->type != C(NOTHING))
+ goto will_not_be_empty;
+ if (tree->sequence->processed != PROCESS_LEVEL) {
+ if (tree->result)
+ NEW_ERROR(tree->sequence, ERROR, "mapping of null sequence");
+ else
+ NEW_ERROR(tree->sequence, ERROR, "nothing in value statement");
+ }
+ /* The tree parsing process will not allow a mapping statement
+ * to start with a ‘.’. Thus if we select to highlight it we
+ * know that it is either an empty alternation, an empty
+ * unordered subsequence or a nothing inside an alternation.
+ * If it is already been processed by the simplifier, it is an
+ * error because it is an empty alternation or empty unordered
+ * subsequence, and there is not reason to print an additional
+ * error. If however it is a nothing inside an alternation we
+ * know that it is the cause of the error, however possibily
+ * in conjunction with additional such constructs, but those
+ * are harder to locate. */
+ return 0;
+will_not_be_empty:
+
+ /* Remove ‘.’:s. */
+ REMOVE_NOTHING(sequence);
+
+ /* Because unordered are simplified to alternations of ordered subsequences, which
+ in turn can contain alternations, possibiled from simplification of nested
+ unordered sequenceses, we need to reeliminated until there are not alternations. */
+ for (need_reelimination = 1; need_reelimination ? (need_reelimination = 0, 1) : 0; redo = 0) {
+ /* Copy sequence. */
+ fail_if (!(dup_sequence = mds_kbdc_tree_dup(tree->sequence)));
+
+ /* Eliminate alterations, remember, unordered subsequences have
+ been simplified to alternations of ordered subsequences. */
+ for (argument_index = 0, argument = dup_sequence; argument; argument = argument->next, argument_index++)
+ if (argument->type == C(ALTERNATION))
+ fail_if (eliminate_alternation((mds_kbdc_tree_t*)tree, argument, argument_index));
+
+ mds_kbdc_tree_free(dup_sequence), dup_sequence = NULL;
+
+ /* Eliminated ordered subsequences. */
+ for (here = &(tree->sequence); (argument = *here); redo ? (redo = 0) : (here = &(argument->next), 0)) {
+ if (argument->type == C(ORDERED)) {
+ FLATTEN(argument);
+ redo = 1;
+ } else if (argument->type == C(ALTERNATION)) {
+ need_reelimination = 1;
+ }
+ }
+ }
+
+ /* Valid value properties. */
+ if (!tree->result)
+ fail_if (check_value_statement_after_simplification(tree));
+
+ /* Mapping statements are simplified in a manner similar
+ * to how macro calls are simplified. However mapping
+ * statements can also contain unordered subsequences,
+ * there are translated into alternations of ordered
+ * subsequences. Thus after the elimination of alternations,
+ * ordered subsequences are eliminated too.
+ *
+ * Example of what will happen, ‘{ }’ represents an
+ * ordered subsequence:
+ *
+ * (1 2) (3 4) : 0 ## mapping 1
+ *
+ * simplify_map on mapping 1
+ * after simplification
+ * [{1 2} {2 1}] [{3 4} {4 3}] ## mapping 1
+ * after alternation elimination on argument 1
+ * {1 2} [{3 4} {4 3}] ## mapping 1
+ * {2 1} [{3 4} {4 3}] ## mapping 3
+ * after alternation elimination on argument 2
+ * {1 2} {3 4} ## mapping 1
+ * {1 2} {4 3} ## mapping 2
+ * {2 1} [{3 4} {4 3}] ## mapping 3
+ * after ordered subsequence elimination
+ * 1 2 3 4 ## mapping 1
+ * {1 2} {4 3} ## mapping 2
+ * {2 1} [{3 4} {4 3}] ## mapping 3
+ *
+ * simplify_map on mapping 2
+ * no difference after simplification
+ * no difference after alternation elimination on argument 1
+ * no difference after alternation elimination on argument 2
+ * after ordered subsequence elimination
+ * 1 2 3 4 ## (mapping 1)
+ * 1 2 4 3 ## mapping 2
+ * {2 1} [{3 4} {4 3}] ## mapping 3
+ *
+ * simplify_map on mapping 3
+ * no difference after simplification
+ * no difference after alternation elimination on argument 1
+ * after alternation elimination on argument 2
+ * 1 2 3 4 ## (mapping 1)
+ * 1 2 4 3 ## (mapping 2)
+ * {2 1} {3 4} ## mapping 3
+ * {2 1} {4 3} ## mapping 4
+ * after ordered subsequence elimination
+ * 1 2 3 4 ## (mapping 1)
+ * 1 2 4 3 ## (mapping 2)
+ * 2 1 3 4 ## mapping 3
+ * {2 1} {4 3} ## mapping 4
+ *
+ * simplify_map on mapping 4
+ * no difference after simplification
+ * no difference after alternation elimination on argument 1
+ * no difference after alternation elimination on argument 2
+ * after ordered subsequence elimination
+ * 1 2 3 4 ## (mapping 1)
+ * 1 2 4 3 ## (mapping 2)
+ * 2 1 3 4 ## (mapping 3)
+ * 2 1 4 3 ## mapping 4
+ *
+ * Nothings (‘.’) are removed before processing the alternations.
+ */
+
+ return 0;
+fail:
+ saved_errno = errno;
+ mds_kbdc_tree_free(dup_sequence);
+ return errno = saved_errno, -1;
}
@@ -543,69 +544,63 @@ static int simplify_map(mds_kbdc_tree_map_t* restrict tree)
* @param tree The alternation-subtree
* @return Zero on success, -1 on error
*/
-static int simplify_alternation(mds_kbdc_tree_alternation_t* restrict tree)
+static int
+simplify_alternation(mds_kbdc_tree_alternation_t *restrict tree)
{
- mds_kbdc_tree_t* argument;
- mds_kbdc_tree_t* first_nothing = NULL;
- mds_kbdc_tree_t* temp;
- mds_kbdc_tree_t** here;
- int redo = 0;
-
- /* Test emptyness. */
- if (tree->inner == NULL)
- {
- NEW_ERROR(tree, ERROR, "empty alternation");
- tree->type = C(NOTHING);
- tree->processed = PROCESS_LEVEL;
- return 0;
- }
-
- /* Test singletonness. */
- if (tree->inner->next == NULL)
- {
- temp = tree->inner;
- NEW_ERROR(tree, WARNING, "singleton alternation");
- memcpy(tree, temp, sizeof(mds_kbdc_tree_t));
- free(temp);
- fail_if (simplify((mds_kbdc_tree_t*)tree));
- return 0;
- }
-
- /* Simplify. */
- for (here = &(tree->inner); (argument = *here); redo ? (redo = 0) : (here = &(argument->next), 0))
- if ((argument->type == C(NOTHING)) && (argument->processed != PROCESS_LEVEL))
- {
- /* Test multiple nothings. */
- if (first_nothing == NULL)
- first_nothing = argument;
- else
- {
- NEW_ERROR(argument, WARNING, "multiple ‘.’ inside an alternation");
- NEW_ERROR(first_nothing, NOTE, "first ‘.’ was here");
- }
- }
- else if (argument->type == C(ALTERNATION))
- {
- /* Alternation nesting. */
- if (argument->processed != PROCESS_LEVEL)
- NEW_ERROR(argument, WARNING, "alternation inside alternation is unnessary");
- fail_if (simplify_alternation(&(argument->alternation)));
- if (argument->type == C(ALTERNATION))
- FLATTEN(argument);
- redo = 1;
- }
- else if (argument->type == C(UNORDERED))
- {
- /* Nesting unordered subsequence,
- simplifies to alternation of ordered subsequence, or simpler. */
- NEW_ERROR(argument, WARNING, "unordered subsequence inside alternation is discouraged");
- fail_if (simplify_unordered(&(argument->unordered)));
- redo = 1;
- }
-
- return 0;
- fail:
- return -1;
+ mds_kbdc_tree_t *argument;
+ mds_kbdc_tree_t *first_nothing = NULL;
+ mds_kbdc_tree_t *temp;
+ mds_kbdc_tree_t **here;
+ int redo = 0;
+
+ /* Test emptyness. */
+ if (!tree->inner) {
+ NEW_ERROR(tree, ERROR, "empty alternation");
+ tree->type = C(NOTHING);
+ tree->processed = PROCESS_LEVEL;
+ return 0;
+ }
+
+ /* Test singletonness. */
+ if (!tree->inner->next) {
+ temp = tree->inner;
+ NEW_ERROR(tree, WARNING, "singleton alternation");
+ memcpy(tree, temp, sizeof(mds_kbdc_tree_t));
+ free(temp);
+ fail_if (simplify((mds_kbdc_tree_t*)tree));
+ return 0;
+ }
+
+ /* Simplify. */
+ for (here = &(tree->inner); (argument = *here); redo ? (redo = 0) : (here = &(argument->next), 0)) {
+ if (argument->type == C(NOTHING) && argument->processed != PROCESS_LEVEL) {
+ /* Test multiple nothings. */
+ if (!first_nothing) {
+ first_nothing = argument;
+ } else{
+ NEW_ERROR(argument, WARNING, "multiple ‘.’ inside an alternation");
+ NEW_ERROR(first_nothing, NOTE, "first ‘.’ was here");
+ }
+ } else if (argument->type == C(ALTERNATION)) {
+ /* Alternation nesting. */
+ if (argument->processed != PROCESS_LEVEL)
+ NEW_ERROR(argument, WARNING, "alternation inside alternation is unnessary");
+ fail_if (simplify_alternation(&(argument->alternation)));
+ if (argument->type == C(ALTERNATION))
+ FLATTEN(argument);
+ redo = 1;
+ } else if (argument->type == C(UNORDERED)) {
+ /* Nesting unordered subsequence,
+ simplifies to alternation of ordered subsequence, or simpler. */
+ NEW_ERROR(argument, WARNING, "unordered subsequence inside alternation is discouraged");
+ fail_if (simplify_unordered(&(argument->unordered)));
+ redo = 1;
+ }
+ }
+
+ return 0;
+fail:
+ return -1;
}
@@ -616,77 +611,75 @@ static int simplify_alternation(mds_kbdc_tree_alternation_t* restrict tree)
* @param elements The subtrees, chained
* @return Chain of ordered subsequence, `NULL` on error
*/
-static mds_kbdc_tree_t* create_permutations(mds_kbdc_tree_t* elements)
+static mds_kbdc_tree_t *
+create_permutations(mds_kbdc_tree_t *elements)
{
- mds_kbdc_tree_t* first = NULL;
- mds_kbdc_tree_t** here = &first;
- mds_kbdc_tree_t** previous_next = &elements;
- mds_kbdc_tree_t* argument;
- mds_kbdc_tree_t* temp;
- mds_kbdc_tree_t* subperms = NULL;
- mds_kbdc_tree_t* perm;
- mds_kbdc_tree_t ordered;
- int saved_errno, no_perms, stage = 0;
-
- /* Error case. */
- fail_if (elements == NULL);
-
- /* Base case. */
- if (elements->next == NULL)
- {
- fail_if ((first = mds_kbdc_tree_create(C(ORDERED))) == NULL);
- fail_if ((first->ordered.inner = mds_kbdc_tree_dup(elements)) == NULL);
- return first;
- }
-
- stage++;
- for (previous_next = &elements; (argument = *previous_next); previous_next = &((*previous_next)->next))
- {
- /* Created ordered alternative for a permutation prototype. */
- mds_kbdc_tree_initialise(&ordered, C(ORDERED));
- /* Select the first element. */
- temp = argument->next, argument->next = NULL;
- ordered.ordered.inner = mds_kbdc_tree_dup(argument);
- argument->next = temp;
- fail_if (ordered.ordered.inner == NULL);
- /* Create subpermutations. */
- *previous_next = argument->next;
- argument->next = NULL;
- no_perms = (elements == NULL);
- subperms = create_permutations(elements);
- argument->next = *previous_next;
- *previous_next = argument;
- fail_if (no_perms ? 0 : (subperms == NULL));
- /* Join first element with subpermutations. */
- while (subperms)
- {
- /* Join. */
- fail_if (perm = mds_kbdc_tree_dup(&ordered), perm == NULL);
- perm->ordered.inner->next = subperms->ordered.inner;
- subperms->ordered.inner = NULL;
- /* Add the permutation to the chain. */
- *here = perm;
- here = &(perm->next);
- /* Select next permutation. */
- temp = subperms;
- subperms = subperms->next;
- temp->next = NULL;
- mds_kbdc_tree_free(temp);
+ mds_kbdc_tree_t *first = NULL;
+ mds_kbdc_tree_t **here = &first;
+ mds_kbdc_tree_t **previous_next = &elements;
+ mds_kbdc_tree_t *argument;
+ mds_kbdc_tree_t *temp;
+ mds_kbdc_tree_t *subperms = NULL;
+ mds_kbdc_tree_t *perm;
+ mds_kbdc_tree_t ordered;
+ int saved_errno, no_perms, stage = 0;
+
+ /* Error case. */
+ fail_if (!elements);
+
+ /* Base case. */
+ if (!elements->next) {
+ fail_if (!(first = mds_kbdc_tree_create(C(ORDERED))));
+ fail_if (!(first->ordered.inner = mds_kbdc_tree_dup(elements)));
+ return first;
}
- /* Destroy prototype. */
- mds_kbdc_tree_destroy(&ordered);
- }
-
- return first;
-
- fail:
- saved_errno = errno;
- mds_kbdc_tree_free(first);
- mds_kbdc_tree_free(subperms);
- if (stage > 0)
- mds_kbdc_tree_destroy(&ordered);
- errno = saved_errno;
- return NULL;
+
+ stage++;
+ for (previous_next = &elements; (argument = *previous_next); previous_next = &(*previous_next)->next) {
+ /* Created ordered alternative for a permutation prototype. */
+ mds_kbdc_tree_initialise(&ordered, C(ORDERED));
+ /* Select the first element. */
+ temp = argument->next, argument->next = NULL;
+ ordered.ordered.inner = mds_kbdc_tree_dup(argument);
+ argument->next = temp;
+ fail_if (!ordered.ordered.inner);
+ /* Create subpermutations. */
+ *previous_next = argument->next;
+ argument->next = NULL;
+ no_perms = !elements;
+ subperms = create_permutations(elements);
+ argument->next = *previous_next;
+ *previous_next = argument;
+ fail_if (no_perms && !subperms);
+ /* Join first element with subpermutations. */
+ while (subperms) {
+ /* Join. */
+ fail_if (!(perm = mds_kbdc_tree_dup(&ordered)));
+ perm->ordered.inner->next = subperms->ordered.inner;
+ subperms->ordered.inner = NULL;
+ /* Add the permutation to the chain. */
+ *here = perm;
+ here = &perm->next;
+ /* Select next permutation. */
+ temp = subperms;
+ subperms = subperms->next;
+ temp->next = NULL;
+ mds_kbdc_tree_free(temp);
+ }
+ /* Destroy prototype. */
+ mds_kbdc_tree_destroy(&ordered);
+ }
+
+ return first;
+
+fail:
+ saved_errno = errno;
+ mds_kbdc_tree_free(first);
+ mds_kbdc_tree_free(subperms);
+ if (stage > 0)
+ mds_kbdc_tree_destroy(&ordered);
+ errno = saved_errno;
+ return NULL;
}
@@ -696,105 +689,97 @@ static mds_kbdc_tree_t* create_permutations(mds_kbdc_tree_t* elements)
* @param tree The unordered subsequence-subtree
* @return Zero on success, -1 on error
*/
-static int simplify_unordered(mds_kbdc_tree_unordered_t* restrict tree)
+static int
+simplify_unordered(mds_kbdc_tree_unordered_t *restrict tree)
{
- mds_kbdc_tree_t* arguments;
- mds_kbdc_tree_t* argument;
- mds_kbdc_tree_t* temp;
- mds_kbdc_tree_t** here;
- int allow_long = 0;
- size_t argument_count;
-
- /* Test for ‘(( ))’. */
- if (tree->inner && (tree->inner->next == NULL) && (tree->inner->type == C(UNORDERED)))
- {
- tree->loc_end = tree->inner->loc_end;
- temp = tree->inner;
- tree->inner = tree->inner->unordered.inner;
- temp->unordered.inner = NULL;
- mds_kbdc_tree_free(temp);
- allow_long = 1;
- }
-
- /* Test emptyness. */
- if (tree->inner == NULL)
- {
- NEW_ERROR(tree, ERROR, "empty unordered subsequence");
- tree->type = C(NOTHING);
- tree->processed = PROCESS_LEVEL;
- return 0;
- }
-
- /* Test singletonness. */
- if (tree->inner->next == NULL)
- {
- temp = tree->inner;
- NEW_ERROR(tree, WARNING, "singleton unordered subsequence");
- memcpy(tree, temp, sizeof(mds_kbdc_tree_t));
- free(temp);
- fail_if (simplify((mds_kbdc_tree_t*)tree));
- return -1;
- }
-
- /* Remove ‘.’:s. */
- REMOVE_NOTHING(inner);
-
- /* Check that the sequnced contained anything else. */
- if (tree->inner == NULL)
- {
- NEW_ERROR(tree, ERROR, "unordered subsequence contained nothing else than ‘.’");
- tree->type = C(NOTHING);
- tree->processed = PROCESS_LEVEL;
- return 0;
- }
-
- /* Simplify. */
- for (argument = tree->inner, argument_count = 0; argument; argument = argument->next, argument_count++)
- if (argument->type == C(ALTERNATION))
- {
- fail_if (simplify_alternation(&(argument->alternation)));
- argument->processed = PROCESS_LEVEL;
- }
- else if (argument->type == C(UNORDERED))
- {
- NEW_ERROR(argument, WARNING, "unordered subsequence inside unordered subsequence is discouraged");
- fail_if (simplify_unordered(&(argument->unordered)));
- argument->processed = PROCESS_LEVEL;
- }
-
- /* Check the size of the subsequence. */
- if ((argument_count > 5) && (allow_long * argv_force == 0))
- {
- if (allow_long == 0)
- NEW_ERROR(tree->inner, ERROR,
- "unordered subsequence longer than 5 elements need double brackets");
- else if (argv_force == 0)
- NEW_ERROR(tree->inner, ERROR,
- "unordered subsequence of size %zu found, requires ‘--force’ to compile", argument_count);
- return 0;
- }
-
- /* Generate permutations. */
- tree->type = C(ALTERNATION);
- tree->processed = PROCESS_LEVEL;
- arguments = tree->inner;
- if (tree->inner = create_permutations(arguments), tree->inner == NULL)
- {
- if (errno == 0)
- {
- /* `create_permutations` can return `NULL` without setting `errno`
- * if it does not list any permutations. */
- NEW_ERROR_(result, INTERNAL_ERROR, 0, 0, 0, 0, 1,
- "Fail to create permutations of an unordered sequence");
- return 0;
+ mds_kbdc_tree_t *arguments;
+ mds_kbdc_tree_t *argument;
+ mds_kbdc_tree_t *temp;
+ mds_kbdc_tree_t **here;
+ int allow_long = 0;
+ size_t argument_count;
+
+ /* Test for ‘(( ))’. */
+ if (tree->inner && !tree->inner->next && tree->inner->type == C(UNORDERED)) {
+ tree->loc_end = tree->inner->loc_end;
+ temp = tree->inner;
+ tree->inner = tree->inner->unordered.inner;
+ temp->unordered.inner = NULL;
+ mds_kbdc_tree_free(temp);
+ allow_long = 1;
}
- fail_if (tree->inner = arguments, 1);
- }
- mds_kbdc_tree_free(arguments);
-
- return 0;
- fail:
- return -1;
+
+ /* Test emptyness. */
+ if (!tree->inner) {
+ NEW_ERROR(tree, ERROR, "empty unordered subsequence");
+ tree->type = C(NOTHING);
+ tree->processed = PROCESS_LEVEL;
+ return 0;
+ }
+
+ /* Test singletonness. */
+ if (!tree->inner->next) {
+ temp = tree->inner;
+ NEW_ERROR(tree, WARNING, "singleton unordered subsequence");
+ memcpy(tree, temp, sizeof(mds_kbdc_tree_t));
+ free(temp);
+ fail_if (simplify((mds_kbdc_tree_t*)tree));
+ return -1;
+ }
+
+ /* Remove ‘.’:s. */
+ REMOVE_NOTHING(inner);
+
+ /* Check that the sequnced contained anything else. */
+ if (!tree->inner) {
+ NEW_ERROR(tree, ERROR, "unordered subsequence contained nothing else than ‘.’");
+ tree->type = C(NOTHING);
+ tree->processed = PROCESS_LEVEL;
+ return 0;
+ }
+
+ /* Simplify. */
+ for (argument = tree->inner, argument_count = 0; argument; argument = argument->next, argument_count++) {
+ if (argument->type == C(ALTERNATION)) {
+ fail_if (simplify_alternation(&(argument->alternation)));
+ argument->processed = PROCESS_LEVEL;
+ } else if (argument->type == C(UNORDERED)) {
+ NEW_ERROR(argument, WARNING, "unordered subsequence inside unordered subsequence is discouraged");
+ fail_if (simplify_unordered(&(argument->unordered)));
+ argument->processed = PROCESS_LEVEL;
+ }
+ }
+
+ /* Check the size of the subsequence. */
+ if (argument_count > 5 && (!allow_long || !argv_force)) {
+ if (!allow_long)
+ NEW_ERROR(tree->inner, ERROR,
+ "unordered subsequence longer than 5 elements need double brackets");
+ else if (!argv_force)
+ NEW_ERROR(tree->inner, ERROR,
+ "unordered subsequence of size %zu found, requires ‘--force’ to compile", argument_count);
+ return 0;
+ }
+
+ /* Generate permutations. */
+ tree->type = C(ALTERNATION);
+ tree->processed = PROCESS_LEVEL;
+ arguments = tree->inner;
+ if (!(tree->inner = create_permutations(arguments))) {
+ if (!errno) {
+ /* `create_permutations` can return `NULL` without setting `errno`
+ * if it does not list any permutations. */
+ NEW_ERROR_(result, INTERNAL_ERROR, 0, 0, 0, 0, 1,
+ "Fail to create permutations of an unordered sequence");
+ return 0;
+ }
+ fail_if (tree->inner = arguments, 1);
+ }
+ mds_kbdc_tree_free(arguments);
+
+ return 0;
+fail:
+ return -1;
}
@@ -804,34 +789,34 @@ static int simplify_unordered(mds_kbdc_tree_unordered_t* restrict tree)
* @param tree The tree
* @return Zero on success, -1 on error
*/
-static int simplify(mds_kbdc_tree_t* restrict tree)
+static int
+simplify(mds_kbdc_tree_t *restrict tree)
{
-#define s(expr) fail_if (simplify(tree->expr))
-#define S(type) fail_if (simplify_##type(&(tree->type)))
- again:
- if (tree == NULL)
- return 0;
-
- switch (tree->type)
- {
- case C(INFORMATION): s (information.inner); break;
- case C(FUNCTION): s (function.inner); break;
- case C(MACRO): s (macro.inner); break;
- case C(ASSUMPTION): s (assumption.inner); break;
- case C(FOR): s (for_.inner); break;
- case C(IF): s (if_.inner); s (if_.otherwise); break;
- case C(MAP): S (map); break;
- case C(ALTERNATION): S (alternation); break;
- case C(UNORDERED): S (unordered); break;
- case C(MACRO_CALL): S (macro_call); break;
- default:
- break;
- }
-
- tree = tree->next;
- goto again;
+#define s(expr) fail_if (simplify(tree->expr))
+#define S(type) fail_if (simplify_##type(&(tree->type)))
+again:
+ if (!tree)
+ return 0;
+
+ switch (tree->type) {
+ case C(INFORMATION): s (information.inner); break;
+ case C(FUNCTION): s (function.inner); break;
+ case C(MACRO): s (macro.inner); break;
+ case C(ASSUMPTION): s (assumption.inner); break;
+ case C(FOR): s (for_.inner); break;
+ case C(IF): s (if_.inner); s (if_.otherwise); break;
+ case C(MAP): S (map); break;
+ case C(ALTERNATION): S (alternation); break;
+ case C(UNORDERED): S (unordered); break;
+ case C(MACRO_CALL): S (macro_call); break;
+ default:
+ break;
+ }
+
+ tree = tree->next;
+ goto again;
fail:
- return -1;
+ return -1;
#undef s
#undef S
}
@@ -843,10 +828,11 @@ static int simplify(mds_kbdc_tree_t* restrict tree)
* @param result_ `result` from `parse_to_tree`, same sematics, will be updated
* @return -1 if an error occursed that cannot be stored in `result`, zero otherwise
*/
-int simplify_tree(mds_kbdc_parsed_t* restrict result_)
+int
+simplify_tree(mds_kbdc_parsed_t *restrict result_)
{
- result = result_;
- return simplify(result_->tree);
+ result = result_;
+ return simplify(result_->tree);
}
@@ -856,4 +842,3 @@ int simplify_tree(mds_kbdc_parsed_t* restrict result_)
#undef NEW_ERROR
#undef C
#undef PROCESS_LEVEL
-