-  
 - #include <stdbool.h>
 - #include <stdio.h>
 - #include <stdlib.h>
 - #include <string.h>
 - // A C program to demonstrate linked list based implementation of queue 
 - // A linked list (LL) node to store a queue entry
 - struct trie_QNode
 - {
 - 	char * rule_name;
 - 	int rule_name_index;
 - 	char * key;
 - 	int index;
 - 	char * rule_next;
 - 	int rule_next_index;
 -     struct trie_QNode *next;
 - };
 -  
 - // The queue, front stores the front node of LL and rear stores ths
 - // last node of LL
 - struct trie_Queue
 - {
 -     struct trie_QNode *front, *rear;
 - };
 -  
 - // A utility function to create a new linked list node.
 - struct trie_QNode* trie_newNode(char * a, int b, char * c, int d, char * e, int f)
 - {
 -     struct trie_QNode *temp = (struct trie_QNode*)malloc(sizeof(struct trie_QNode));
 - 	temp->rule_name = a;
 - 	temp->rule_name_index = b;
 - 	temp->key = c;
 - 	temp->index = d;
 - 	temp->rule_next = e;
 - 	temp->rule_next_index = f;
 -     temp->next = NULL;
 -     return temp;
 - }
 -  
 - // A utility function to create an empty queue
 - struct trie_Queue *trie_createQueue()
 - {
 -     struct trie_Queue *q = (struct trie_Queue*)malloc(sizeof(struct trie_Queue));
 -     q->front = q->rear = NULL;
 -     return q;
 - }
 - 
 - void trie_store_asm(struct trie_Queue *q, char * rule_name, int rule_name_index, char * key, int index, char * rule_next, int rule_next_index)
 - {
 -     // Create a new LL node
 -     struct trie_QNode *temp = trie_newNode(rule_name,rule_name_index,key,index,rule_next,rule_next_index);
 -  
 -     // If queue is empty, then new node is front and rear both
 -     if (q->rear == NULL)
 -     {
 -        q->front = q->rear = temp;
 - 		q->rear->rule_next = NULL;
 - 		q->rear->rule_next_index = -1;
 -        return;
 -     }
 -  
 -     // Add the new node at the end of queue and change rear
 -     if (q->rear) {
 - 		q->rear->rule_next = rule_name;
 - 		q->rear->rule_next_index = rule_name_index;
 - 	}
 -     q->rear->next = temp;
 -     q->rear = temp;
 -     if (q->rear) {
 - 		q->rear->rule_next = NULL;
 - 		q->rear->rule_next_index = -1;
 - 	}
 - }
 - 
 - void trie_store_asm2(struct trie_Queue *q, char * rule_name, int rule_name_index, char * key, int index, char * rule_next, int rule_next_index)
 - {
 -     // Create a new LL node
 -     struct trie_QNode *temp = trie_newNode(rule_name,rule_name_index,key,index,rule_next,rule_next_index);
 -  
 -     // If queue is empty, then new node is front and rear both
 -     if (q->rear == NULL)
 -     {
 -        q->front = q->rear = temp;
 -        return;
 -     }
 -  
 -     // Add the new node at the end of queue and change rear
 -     if (q->rear) {
 - 		q->rear->rule_next = rule_name;
 - 		q->rear->rule_next_index = rule_name_index;
 - 	}
 -     q->rear->next = temp;
 -     q->rear = temp;
 - }
 - 
 - void trie_store_asm3(struct trie_Queue *q, char * rule_name, int rule_name_index, char * key, int index, char * rule_next, int rule_next_index)
 - {
 -     // Create a new LL node
 -     struct trie_QNode *temp = trie_newNode(rule_name,rule_name_index,key,index,rule_next,rule_next_index);
 -  
 -     // If queue is empty, then new node is front and rear both
 -     if (q->rear == NULL)
 -     {
 -        q->front = q->rear = temp;
 -        return;
 -     }
 -  
 -     // Add the new node at the end of queue and change rear
 -     q->rear->next = temp;
 -     q->rear = temp;
 - }
 - 
 - struct trie_QNode * trie_load_asm(struct trie_Queue **q)
 - {
 -     // If queue is empty, return NULL.
 - 	if ((q) == NULL) return NULL;
 - 	if ((*q) == NULL) return NULL;
 -     if ((*q)->front == NULL)
 -        return NULL;
 -  
 -     // Store previous front and move front one node ahead
 -     struct trie_QNode *temp = (*q)->front;
 -     (*q)->front = (*q)->front->next;
 -  
 -     // If front becomes NULL, then change rear also as NULL
 -     if ((*q)->front == NULL)
 -        (*q)->rear = NULL;
 -     return temp;
 - }
 - 
 - int trie_queue_add(struct trie_Queue **q, char * rule_name, int rule_name_index, char * key, int index, char * rule_next, int rule_next_index) {
 -     if (!(*q)) (*q) = trie_createQueue();
 -     trie_store_asm((*q), rule_name,rule_name_index,key,index,rule_next,rule_next_index);
 -     return 0;
 - }
 - 
 - 
 - int trie_queue_add2(struct trie_Queue **q, char * rule_name, int rule_name_index, char * key, int index, char * rule_next, int rule_next_index) {
 -     if (!(*q)) (*q) = trie_createQueue();
 -     trie_store_asm2((*q), rule_name,rule_name_index,key,index,rule_next,rule_next_index);
 -     return 0;
 - }
 - 
 - int trie_queue_add3(struct trie_Queue **q, char * rule_name, int rule_name_index, char * key, int index, char * rule_next, int rule_next_index) {
 -     if (!(*q)) (*q) = trie_createQueue();
 -     trie_store_asm3((*q), rule_name,rule_name_index,key,index,rule_next,rule_next_index);
 -     return 0;
 - }
 - 
 - char * trie_root = "root";
 - char * trie_sub_root = "sub_root";
 - char * trie_rule_prefix = "rule_";
 - 
 - struct trie_Queue * trie_trie = NULL;
 - int rule_index = -1;
 - int actual_index = 0;
 - bool passed_first = false;
 - bool passed_next = false;
 - int update_on_next_pass = false;
 - 
 - int final_rule = 0;
 - int rule_index_tmp = 0;
 - int actual_index_tmp = 0;
 - 
 - bool part_of_branch = false;
 - 
 - int itterations = 0;
 - 
 - char * getbranchcontents(char * s) {
 - 	char * c = malloc(500);
 - 	memset(c,0,500);
 - 	int ci = 0;
 - 	for(; *s; s++) {
 - 		if (*s == 'b') {
 - 			continue;
 - 		}
 - 		if (*s == 'e' || *s == 'C') {
 - 			break;
 - 		}
 - 		if (*s == ' ' || *s == '\n' || *s == '\t') continue;
 - 		if (*s == 's') {
 - 			s++;
 - 			c[ci] = *s;
 - 			ci++;
 - 		}
 - 	}
 - 	printf("c = %s\n", c);
 - 	return c;
 - }
 - 
 - parse_branch(char * co) {
 - 				itterations++;
 - 				int actual_index_tmp = 0;
 - 				char * zrule_name;
 - 				int zrule_name_index;
 - 				char * zkey;
 - 				int zindex;
 - 				if (itterations == 1) {
 - 					zrule_name = trie_trie->rear->rule_name;
 - 					zrule_name_index = trie_trie->rear->rule_name_index;
 - 					zkey = trie_trie->rear->key;
 - 					zindex = trie_trie->rear->index;
 - 					rule_index_tmp = rule_index+1;
 - 					final_rule = rule_index_tmp;
 - 				}
 - 				else if (itterations == 2) rule_index_tmp++;
 - 				actual_index_tmp = actual_index+1;
 - 				printf("zrule_name = %s\n", zrule_name);
 - 				printf("zkey = %s\n", zkey);
 - 				printf("insert(%s%d, \"%s\", %d, %s%d);\n", zrule_name, zrule_name_index, zkey, zindex, trie_rule_prefix, rule_index_tmp-(itterations==1?0:1));
 - 				trie_queue_add3(&trie_trie, zrule_name, zrule_name_index, strdup(zkey), zindex, trie_rule_prefix, rule_index_tmp-(itterations==1?0:1));
 - 				for (int level = 0; co[level]; level++) {
 - 					char tmp[2];
 - 					tmp[0] = co[level];
 - 					tmp[1] = '\0';
 - 					printf("insert(%s%d, \"%s\", %d, %s%d);\n", trie_rule_prefix, rule_index_tmp-1, tmp, actual_index_tmp, trie_rule_prefix, co[level+1]?rule_index_tmp:final_rule);
 - 					if (itterations == 1) {
 - 						if (co[level+1]) {
 - 							puts("RULE");
 - 							trie_queue_add(&trie_trie, trie_rule_prefix, rule_index_tmp-1, strdup(tmp), actual_index_tmp, trie_rule_prefix, rule_index_tmp);
 - 						} else {
 - 							puts("FINAL");
 - 							trie_queue_add2(&trie_trie, trie_rule_prefix, rule_index_tmp-1, strdup(tmp), actual_index_tmp, trie_rule_prefix, final_rule);
 - 						}
 - 					} else {
 - 						puts("RULE FINAL");
 - 						trie_queue_add3(&trie_trie, trie_rule_prefix, rule_index_tmp-1, strdup(tmp), actual_index_tmp, trie_rule_prefix, co[level+1]?rule_index_tmp:final_rule);
 - 					}
 - 					rule_index_tmp++;
 - 					if (itterations == 1 && co[level+1]) final_rule++;
 - 					actual_index_tmp++;
 - 				}
 - }
 - char * co = NULL;
 - int main(int argc, char **argv) {
 - /*
 - def0:
 - 35:NULL
 - 85:NULL
 - 
 - rule1 : |1|2|def0|6|
 - */
 - 
 - 	char * s = "\
 - 	i:\
 - 	s1\
 - 	s2\
 - 	 b\
 - 	  C\
 - 		s3\
 - 		s5\
 - 	  C\
 - 		s8\
 - 		s5\
 - 	 e\
 - 	s6"; // for the sake of simplicity branches contain full strings only, not individual characters
 - 	rule_index++;
 - 	for(; *s; s++) {
 - 		if (*s == 'b') {
 - 			puts("branch start");
 - 			part_of_branch = true;
 - 			itterations = 0;
 - 			for(; *s; s++) {
 - 				if (*s == 'C') {
 - 					s++;
 - 					co = getbranchcontents(s);
 - 					parse_branch(co);
 - 					free(co);
 - 				};
 - 				if (*s == 'e') break;
 - 			}
 - 			if (*s == 'e') s--;
 - 			continue;
 - 		}
 - 		if (*s == 'e') {
 - 			puts("branch end");
 - 			part_of_branch = false;
 - 			itterations = 0;
 - 			if (final_rule) {
 - 				rule_index = final_rule;
 - 				update_on_next_pass = true;
 - 				final_rule = 0;
 - 			}
 - 			continue;
 - 		}
 - 		if (*s == ' ' || *s == '\n' || *s == '\t') continue;
 - 		if (*s == 'i') {
 - 			passed_first = true;
 - 			continue;
 - 		}
 - 		if (*s == 's' || *s == ':') {
 - 			s++;
 - 			printf("key: %c\n", *s);
 - 			if (part_of_branch) {
 - 			}
 - 			if (!part_of_branch) {
 - 				if (!passed_first) {
 - 					if (passed_next) {
 - 						if (update_on_next_pass/* && (tmp.type & STR_TYPE_DIGIT || tmp.type & STR_TYPE_BINARY)*/) {
 - 							rule_index = rule_index_tmp-1;
 - 							update_on_next_pass = false;
 - 						}
 - 						actual_index = 0;
 - 						passed_next = false;
 - 						char tmp[2];
 - 						tmp[0] = *s;
 - 						tmp[1] = '\0';
 - 						trie_queue_add(&trie_trie, trie_sub_root, -1, strdup(tmp), actual_index, trie_rule_prefix, rule_index);
 - 					}
 - 					else {
 - 						rule_index++;
 - 						actual_index++;
 - 						char tmp[2];
 - 						tmp[0] = *s;
 - 						tmp[1] = '\0';
 - 						trie_queue_add(&trie_trie, trie_rule_prefix, rule_index-1, strdup(tmp), actual_index, trie_rule_prefix, rule_index);
 - 					}
 - 				} else {
 - 					passed_first = false;
 - 					passed_next = true;
 - 				}
 - 			}
 - 		}
 - 	}
 - // 	trie_queue_add(&trie_trie, trie_sub_root, -1, NULL, 0, trie_rule_prefix, 0); // root>0
 - // 	trie_queue_add(&trie_trie, trie_rule_prefix, 0, NULL, 1, trie_rule_prefix, 1); // 0>1
 - // 	trie_queue_add(&trie_trie, trie_rule_prefix, 1, NULL, 1, trie_rule_prefix, 2); // 1>2
 - // 	trie_queue_add2(&trie_trie, trie_rule_prefix, 2, NULL, 1, trie_rule_prefix, 3); // 2>3
 - // 	trie_queue_add3(&trie_trie, trie_rule_prefix, 0, NULL, 1, trie_rule_prefix, 1); // 0>1
 - // 	trie_queue_add(&trie_trie, trie_rule_prefix, 1, NULL, 1, trie_rule_prefix, 2); // 1>2
 - // 	trie_queue_add2(&trie_trie, trie_rule_prefix, 2, NULL, 1, trie_rule_prefix, 3); // 2>3
 - // 	trie_queue_add3(&trie_trie, trie_rule_prefix, 3, NULL, 1, NULL, -1); // 3>END
 - 	struct trie_QNode * node = trie_newNode(NULL,0,NULL,0,NULL,0); // this gets freed anyway
 - 	int nodes = 0;
 - 	int start_indent = 0;
 - 	int i = 0;
 - 	for (i = 0; i < start_indent; i++) printf("    ");
 - 	printf("struct TrieNode * %s = getNode(); \n", trie_root);
 - 	for (i = 0; i < start_indent; i++) printf("    ");
 - 	printf("struct TrieNode * %s = getNode(); \n", trie_sub_root);
 - 	while (node != NULL) {
 - 		// drain the list until empty
 - 		if (node->key) free(node->key);
 - 		free(node);
 - 		node = trie_load_asm(&trie_trie);
 - 		if (node == NULL) break;
 - // 			pp(node)
 - // 			pp(node->rule_name)
 - // 			ps(node->rule_name)
 - // 			pi(node->rule_name_index)
 - // 			pp(node->key)
 - // 			ps(node->key)
 - // 			pi(node->index)
 - // 			pp(node->rule_next)
 - // 			ps(node->rule_next)
 - // 			pi(node->rule_next_index)
 - 		if (node->rule_next && node->rule_next_index != -1) {
 - 			bool rule_does_not_exist = false;
 - 			bool next_rule_does_not_exist = false;
 - 			if (node->rule_name_index == -1) {
 - 				// is sub_root
 - 				if (rule_does_not_exist) {
 - 					for (i = 0; i < start_indent+1; i++) printf("    ");
 - 					printf("struct TrieNode * %s%d = getNode(); \n", node->rule_name, node->rule_name_index);
 - 				}
 - 				if (next_rule_does_not_exist) {
 - 					for (i = 0; i < start_indent+1; i++) printf("    ");
 - 					printf("struct TrieNode * %s%d = getNode(); \n", node->rule_next, node->rule_next_index);
 - 				}
 - 				for (i = 0; i < start_indent+1; i++) printf("    ");
 - 				printf("insert(%s, \"%s\", %d, %s%d);\n", node->rule_name, node->key, node->index, node->rule_next, node->rule_next_index);
 - 			}
 - 			else {
 - 				// is rule
 - 				if (rule_does_not_exist) {
 - 					for (i = 0; i < start_indent+2; i++) printf("    ");
 - 					printf("struct TrieNode * %s%d = getNode(); \n", node->rule_name, node->rule_name_index);
 - 				}
 - 				if (next_rule_does_not_exist) {
 - 					for (i = 0; i < start_indent+2; i++) printf("    ");
 - 					printf("struct TrieNode * %s%d = getNode(); \n", node->rule_next, node->rule_next_index);
 - 				}
 - 				for (i = 0; i < start_indent+2; i++) printf("    ");
 - 				printf("insert(%s%d, \"%s\", %d, %s%d);\n", node->rule_name, node->rule_name_index, node->key, node->index, node->rule_next, node->rule_next_index);
 - 			}
 - 		} else {
 - 			if (node->rule_name_index == -1) {
 - 				// is sub_root
 - 				for (i = 0; i < start_indent+1; i++) printf("    ");
 - 				printf("insert(%s, \"%s\", %d, NULL);\n", node->rule_name, node->key, node->index);
 - 			} else {
 - 				// is rule
 - 				for (i = 0; i < start_indent+2; i++) printf("    ");
 - 				printf("insert(%s%d, \"%s\", %d, NULL);\n", node->rule_name, node->rule_name_index, node->key, node->index);
 - 			}
 - 		}
 - 		nodes++;
 - 	}
 - 	return 0;
 - }
 -