WONKY



LOG | FILES | OVERVIEW


#ifndef WONKY_AUTOMATA_GENERATOR_C
#define WONKY_AUTOMATA_GENERATOR_C WONKY_AUTOMATA_GENERATOR_C
#include <generator.h>


int main()
{
	wonky_memory_init();

	print_automatas();

	wonky_memory_delete();

	return 0;
}

void print_automatas()
{
	FILE *chonky_c;
	struct Generator_Node *chonky;

	chonky_c=fopen("chonky.c","w");
	if(chonky_c==NULL)
	{
		fprintf(stderr,"Could not write to chonky.c\nAborting!\n");
		exit(1);
	}

	chonky=make_chonky();
	fprintf(chonky_c,"#ifndef WONKY_CHONKY_C\n#define WONKY_CHONKY_C WONKY_CHONKY_C\n#include <stddef.h>\n#include <automata.h>\n\n");
	print_automata(chonky,"chonky",chonky_c);	
	fprintf(chonky_c,"\nstruct Automata_Node *id_node=&chonky[%zd];\n\n",global_id_node->node_number);
	print_lexer_type_to_string_map(chonky_c);
	fprintf(chonky_c,"\n#endif");
}
void print_automata(struct Generator_Node *root,const char *name,FILE *out)
{
	fprintf(out,"struct Automata_Node %s[]=\n{\n",name);
	print_automata_nodes(root,name,out);
	fprintf(out,"\n};",name);
}
void print_automata_nodes(struct Generator_Node *node,const char *name,FILE *out)
{
	int i;
	ssize_t node_number=0;
	struct Queue *node_queue;
	struct Generator_Node *current_node;
	struct Generator_Node *adjacent_node;

	node_queue=wonky_malloc(sizeof(struct Queue));
	Queue_Init(node_queue);

	Queue_Push(node_queue,node);
	node->node_number=0;

	while(node_queue->size>0)
	{
		current_node=Queue_Pop(node_queue);
		fprintf(out,"{ \n.action=%s,\n.keyword=%s,\n.preprocessing_keyword=%s,\n.data=%s,\n.delta={",current_node->action_string,current_node->kw_string,current_node->pkw_string,current_node->data_string);
		for(i=0;i<CHAR_ENUM_END;++i)
			if(current_node->output.delta[i]!=NULL)
			{
				adjacent_node=(struct Generator_Node*)current_node->output.delta[i];
				if(adjacent_node->node_number==NODE_NOT_NUMBERED)
				{
					adjacent_node->node_number=++node_number;
					Queue_Push(node_queue,adjacent_node);
				}
				fprintf(out,"%s+%zd ,",name,adjacent_node->node_number);
			}else
			{
				fprintf(out,"NULL, ");
			}

		fprintf(out,"}\n},\n");
	}


	wonky_assert(node_queue->size==0);
	wonky_free(node_queue);
}
void print_lexer_type_to_string_map(FILE *out)
{
	fprintf(out,"const char *lexer_type_to_string_map[LEXER_TYPE_END]=\n\t{\n",number_of_chonky_keywords);
	for(size_t i=0;i<number_of_chonky_keywords;++i)
	{
		fprintf(out,"\t\t[%s]=\"%s\",\n",chonky_keywords[i].preprocessing_kw_string, chonky_keywords[i].keyword);
	}	
	fprintf(out,"\n\t};");
}
struct Generator_Node* make_chonky()
{
	struct Generator_Node *ret;
	ret=make_generator(chonky_keywords,number_of_chonky_keywords);

	add_finishing_float_nodes(ret,0);
	add_number_nodes(ret);
	add_string_char_nodes(ret);
	add_comment_nodes(ret);
	add_id_nodes(ret);

	return ret;
}
struct Generator_Node* make_generator(const struct Keyword_Entry keywords[],size_t number_of_keywords)
{
	size_t i;
	struct Generator_Node *ret;

	ret=get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);

	for(i=0;i<number_of_keywords;++i)
		insert_keyword(ret,keywords+i);

	return ret;

}
struct Generator_Node* insert_keyword(struct Generator_Node *node,const struct Keyword_Entry *entry)
{
	size_t where_in_keyword;
	struct Generator_Node *current;

	for(where_in_keyword=0,current=node;
			entry->keyword[where_in_keyword]!='\0' && entry->keyword[where_in_keyword+1]!='\0';
			current=(struct Generator_Node*)current->output.delta[get_ch(entry->keyword+where_in_keyword,1)],++where_in_keyword)
	{
		if(current->output.delta[get_ch(entry->keyword+where_in_keyword,1)]==NULL)
			current->output.delta[get_ch(entry->keyword+where_in_keyword,1)]=(struct Automata_Node*)get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);
	}

	if(current->output.delta[get_ch(entry->keyword+where_in_keyword,1)]==NULL)
		current->output.delta[get_ch(entry->keyword+where_in_keyword,1)]=(struct Automata_Node*)get_generator_node(entry->data_string,entry->kw_string,entry->preprocessing_kw_string,entry->action_string);
	else
	{
		((struct Generator_Node*)current->output.delta[get_ch(entry->keyword+where_in_keyword,1)])->kw_string=entry->kw_string;
		((struct Generator_Node*)current->output.delta[get_ch(entry->keyword+where_in_keyword,1)])->data_string=entry->data_string;
		((struct Generator_Node*)current->output.delta[get_ch(entry->keyword+where_in_keyword,1)])->action_string=entry->action_string;
	}

	return (struct Generator_Node*)current->output.delta[get_ch(entry->keyword+where_in_keyword,1)];
}
struct Generator_Node* get_generator_node(const char *data_string,const char *kw_string,const char *pkw_string,const char *action_string)
{
	struct Generator_Node *ret;

	ret=wonky_calloc(1,sizeof(struct Generator_Node));
	ret->node_number=NODE_NOT_NUMBERED;
	ret->data_string=data_string;
	ret->kw_string=kw_string;
	ret->pkw_string=pkw_string;
	ret->action_string=action_string;

	return ret;
}
/*requires that there are no loops in the automata*/
void add_id_nodes(struct Generator_Node *node)
{
	struct Generator_Node *id_node;
	struct Queue *node_queue;
	struct Generator_Node *current_node;
	_Bool push_nodes;

	id_node=get_generator_node(null_str,id_type_str,id_type_str,automata_dispense_token_str);

	node_queue=wonky_malloc(sizeof(struct Queue));
	Queue_Init(node_queue);

	Queue_Push(node_queue,id_node);

	connect_node(node,id_node,node_queue,CHAR_a,CHAR_z,1);
	connect_node(node,id_node,node_queue,CHAR_A,CHAR_Z,1);
	connect_node(node,id_node,node_queue,CHAR_UNDERSCORE,CHAR_UNDERSCORE,1);

	while(node_queue->size>0)
	{
		current_node=Queue_Pop(node_queue);

		if(current_node->kw_string==no_type_str)
		{
			current_node->kw_string=id_type_str;
			current_node->action_string=automata_dispense_token_str;
			push_nodes=1;

		}else
		{
			push_nodes=0;
		}
			connect_node(current_node,id_node,node_queue,CHAR_a,CHAR_z,push_nodes);
			connect_node(current_node,id_node,node_queue,CHAR_A,CHAR_Z,push_nodes);
			connect_node(current_node,id_node,node_queue,CHAR_0,CHAR_9,push_nodes);
			connect_node(current_node,id_node,node_queue,CHAR_UNDERSCORE,CHAR_UNDERSCORE,push_nodes);

	}

	wonky_assert(node_queue->size==0);
	wonky_free(node_queue);

	global_id_node=id_node;
}
void add_number_nodes(struct Generator_Node *node)
{
	struct Generator_Node *oct_hex_split;

	add_integer_suffix(add_decimal_number_nodes(node),"KW_LONG_DECIMAL_CONSTANT","KW_LONG_LONG_DECIMAL_CONSTANT");

	oct_hex_split=get_generator_node(null_str,"KW_OCTAL_CONSTANT","KW_OCTAL_CONSTANT",automata_dispense_token_str);
	connect_node(node,oct_hex_split,NULL,CHAR_0,CHAR_0,0);
	add_integer_suffix(oct_hex_split,"KW_LONG_OCTAL_CONSTANT","KW_LONG_LONG_OCTAL_CONSTANT");

	add_integer_suffix(add_hexadecimal_number_nodes(oct_hex_split),"KW_LONG_HEXADECIMAL_CONSTANT","KW_LONG_LONG_HEXADECIMAL_CONSTANT");
	add_integer_suffix(add_octal_number_nodes(oct_hex_split),"KW_LONG_OCTAL_CONSTANT","KW_LONG_LONG_OCTAL_CONSTANT");
}
void add_comment_nodes(struct Generator_Node *node)
{
	struct Generator_Node *base;
	struct Generator_Node *star;
	struct Generator_Node *star_possible_finish;
	struct Generator_Node *star_finish;
	struct Generator_Node *double_slash;
	struct Generator_Node *double_slash_end;

	wonky_assert(node!=NULL);

	base=get_delta_of(node,CHAR_FORWARD_SLASH);

	wonky_assert(base!=NULL);

	star=get_delta_of(base,CHAR_STAR);
	connect_node(star,star,NULL,CHAR_NONE,CHAR_STAR-1,0);
	connect_node(star,star,NULL,CHAR_STAR+1,CHAR_ENUM_END,1);
	star_possible_finish=get_delta_of(star,CHAR_STAR);
	connect_node(star_possible_finish,star,NULL,CHAR_NONE,CHAR_FORWARD_SLASH-1,0);
	connect_node(star_possible_finish,star,NULL,CHAR_FORWARD_SLASH+1,CHAR_ENUM_END,0);
	star_finish=get_delta_of(star_possible_finish,CHAR_FORWARD_SLASH);
	star_finish->data_string="NULL";
	star_finish->kw_string="KW_COMMENT";
	star_finish->pkw_string="KW_COMMENT";
	star_finish->action_string="AUTOMATA_ACTION_NO_ACTION";

	double_slash=get_delta_of(base,CHAR_FORWARD_SLASH);
	connect_node(double_slash,double_slash,NULL,CHAR_NONE,CHAR_FORM_FEED_TAB-1,0);
	connect_node(double_slash,double_slash,NULL,CHAR_FORM_FEED_TAB+1,CHAR_ENUM_END,0);
	double_slash->data_string="NULL";
	double_slash->kw_string="KW_COMMENT";
	double_slash->pkw_string="KW_COMMENT";
	double_slash->action_string="AUTOMATA_ACTION_NO_ACTION";

	double_slash_end=get_delta_of(double_slash,CHAR_FORM_FEED_TAB);
	double_slash_end->data_string="NULL";
	double_slash_end->kw_string="KW_COMMENT";
	double_slash_end->pkw_string="KW_COMMENT";
	double_slash_end->action_string="AUTOMATA_ACTION_NO_ACTION";



}
struct Generator_Node* get_delta_of(struct Generator_Node *node,enum Source_Chars ch)
{
	if(node->output.delta[ch]!=NULL)
	{
		return (struct Generator_Node*)node->output.delta[ch];
	}else
	{
		return (struct Generator_Node*)(node->output.delta[ch]=(struct Automata_Node*)get_generator_node(null_str,"KW_NOTYPE","KW_NOTYPE",automata_no_action_str));
	}
}
struct Generator_Node* add_decimal_number_nodes(struct Generator_Node *node)
{
	struct Generator_Node *decimal_node;
	decimal_node=get_generator_node(null_str,"KW_DECIMAL_CONSTANT","KW_DECIMAL_CONSTANT",automata_dispense_token_str);
	connect_node(node,decimal_node,NULL,CHAR_1,CHAR_9,0);
	connect_node(decimal_node,decimal_node,NULL,CHAR_0,CHAR_9,0);
	add_finishing_float_nodes(decimal_node,1);
	return decimal_node;
}
/*the leading 0 has been taken from add_number_nodes*/
struct Generator_Node* add_hexadecimal_number_nodes(struct Generator_Node *node)
{
	struct Generator_Node *hexadecimal_node_start;
	struct Generator_Node *hexadecimal_node;

	hexadecimal_node_start=get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);

	connect_node(node,hexadecimal_node_start,NULL,CHAR_x,CHAR_x,0);
	connect_node(node,hexadecimal_node_start,NULL,CHAR_X,CHAR_X,0);

	hexadecimal_node=get_generator_node(null_str,"KW_HEXADECIMAL_CONSTANT","KW_HEXADECIMAL_CONSTANT",automata_dispense_token_str);

	connect_node(hexadecimal_node_start,hexadecimal_node,NULL,CHAR_0,CHAR_9,0);
	connect_node(hexadecimal_node_start,hexadecimal_node,NULL,CHAR_a,CHAR_f,0);
	connect_node(hexadecimal_node_start,hexadecimal_node,NULL,CHAR_A,CHAR_F,0);

	connect_node(hexadecimal_node,hexadecimal_node,NULL,CHAR_0,CHAR_9,0);
	connect_node(hexadecimal_node,hexadecimal_node,NULL,CHAR_a,CHAR_f,0);
	connect_node(hexadecimal_node,hexadecimal_node,NULL,CHAR_A,CHAR_F,0);


	add_finishing_hexadecimal_float_nodes(hexadecimal_node,1);
	return hexadecimal_node;
}
struct Generator_Node* add_octal_number_nodes(struct Generator_Node *node)
{
	struct Generator_Node *octal_node;

	add_finishing_float_nodes(node,1);

	octal_node=get_generator_node(null_str,"KW_OCTAL_CONSTANT","KW_OCTAL_CONSTANT",automata_dispense_token_str);
	connect_node(node,octal_node,NULL,CHAR_0,CHAR_7,0);
	connect_node(octal_node,octal_node,NULL,CHAR_0,CHAR_7,0);

	add_finishing_float_nodes(octal_node,1);
	return octal_node;
}
void add_integer_suffix(struct Generator_Node *tail,const char *l,const char *ll)
{
	struct Generator_Node *long_node;
	struct Generator_Node *long_long_node;

	long_node=get_generator_node(null_str,l,l,automata_dispense_token_str);
	long_long_node=get_generator_node(null_str,ll,ll,automata_dispense_token_str);

	connect_node(tail,long_node,NULL,CHAR_l,CHAR_l,0);
	connect_node(tail,long_node,NULL,CHAR_L,CHAR_L,0);

	connect_node(long_node,long_long_node,NULL,CHAR_l,CHAR_l,0);
	connect_node(long_node,long_long_node,NULL,CHAR_L,CHAR_L,0);
}
void add_string_char_nodes(struct Generator_Node *node)
{
	struct Generator_Node *prefixed_string_node;

	prefixed_string_node=get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);
	connect_node(node,prefixed_string_node,NULL,CHAR_L,CHAR_L,0);

	add_string_char_nodes_inner(prefixed_string_node,"KW_WIDE_STRING","KW_WIDE_CHAR_CONSTANT");
	add_string_char_nodes_inner(node,"KW_STRING","KW_CHAR_CONSTANT");

}
void add_string_char_nodes_inner(struct Generator_Node *node,const char *str_kw,const char *char_kw)
{
	struct Generator_Node *inner_string_node;
	struct Generator_Node *ending_string_node;
	
	struct Generator_Node *inner_char_node;
	struct Generator_Node *ending_char_node;

	inner_string_node=get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);
	ending_string_node=get_generator_node(null_str,str_kw,str_kw,automata_dispense_token_str);

	inner_char_node=get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);
	ending_char_node=get_generator_node(null_str,char_kw,char_kw,automata_dispense_token_str);


	connect_node(node,inner_char_node,NULL,CHAR_SINGLE_QUOTE,CHAR_SINGLE_QUOTE,0);
	connect_node(inner_char_node,ending_char_node,NULL,CHAR_SINGLE_QUOTE,CHAR_SINGLE_QUOTE,0);
	connect_node(inner_char_node,inner_char_node,NULL,0,CHAR_FORM_FEED_TAB-1,0);
	connect_node(inner_char_node,inner_char_node,NULL,CHAR_FORM_FEED_TAB+1,CHAR_ENUM_END,0);

	connect_node(node,inner_string_node,NULL,CHAR_DOUBLE_QUOTE,CHAR_DOUBLE_QUOTE,0);
	connect_node(inner_string_node,ending_string_node,NULL,CHAR_DOUBLE_QUOTE,CHAR_DOUBLE_QUOTE,0);
	connect_node(inner_string_node,inner_string_node,NULL,0,CHAR_FORM_FEED_TAB-1,0);
	connect_node(inner_string_node,inner_string_node,NULL,CHAR_FORM_FEED_TAB+1,CHAR_ENUM_END,0);
}
void add_finishing_float_nodes(struct Generator_Node *node,_Bool has_read_digits)
{
	struct Generator_Node *hold;
	struct Generator_Node *hold2;
	hold=add_fractional_constant(node,has_read_digits);
	hold2=add_exponent_part(hold);
	add_float_suffix(hold,"KW_FLOAT_DECIMAL_CONSTANT","KW_LONG_DOUBLE_DECIMAL_CONSTANT");
	add_float_suffix(hold2,"KW_FLOAT_DECIMAL_CONSTANT","KW_LONG_DOUBLE_DECIMAL_CONSTANT");

}
void add_finishing_hexadecimal_float_nodes(struct Generator_Node *node,_Bool has_read_digits)
{
	struct Generator_Node *hold;
	struct Generator_Node *hold2;

	hold=add_hexadecimal_fractional_constant(node,has_read_digits);
	hold2=add_hexadecimal_exponent_part(hold);
	add_float_suffix(hold,"KW_FLOAT_HEXADECIMAL_CONSTANT","KW_LONG_DOUBLE_HEXADECIMAL_CONSTANT");
	add_float_suffix(hold2,"KW_FLOAT_HEXADECIMAL_CONSTANT","KW_LONG_DOUBLE_HEXADECIMAL_CONSTANT");
}
void add_float_suffix(struct Generator_Node *node,const char *f,const char *l)
{
	struct Generator_Node *float_node;
	struct Generator_Node *long_double_node;
	
	float_node=get_generator_node(null_str,f,f,automata_dispense_token_str);
	long_double_node=get_generator_node(null_str,l,l,automata_dispense_token_str);

	connect_node(node,float_node,NULL,CHAR_f,CHAR_f,0);
	connect_node(node,float_node,NULL,CHAR_F,CHAR_F,0);

	connect_node(node,long_double_node,NULL,CHAR_l,CHAR_l,0);
	connect_node(node,long_double_node,NULL,CHAR_L,CHAR_L,0);
}
struct Generator_Node* add_fractional_constant(struct Generator_Node *node,_Bool has_read_digits)
{
	struct Generator_Node *dot_node;
	struct Generator_Node *digit_node;

	if(has_read_digits)
	{
		dot_node=get_generator_node(null_str,"KW_DOUBLE_DECIMAL_CONSTANT","KW_DOUBLE_DECIMAL_CONSTANT",automata_dispense_token_str);
		connect_node(node,dot_node,NULL,CHAR_DOT,CHAR_DOT,0);
		connect_node(dot_node,dot_node,NULL,CHAR_0,CHAR_9,0);

		return dot_node;
	}else
	{
		dot_node=get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);
		digit_node=get_generator_node(null_str,"KW_DOUBLE_DECIMAL_CONSTANT","KW_DOUBLE_DECIMAL_CONSTANT",automata_dispense_token_str);
		connect_node(node,dot_node,NULL,CHAR_DOT,CHAR_DOT,0);
		connect_node(dot_node,digit_node,NULL,CHAR_0,CHAR_9,0);
		connect_node(digit_node,digit_node,NULL,CHAR_0,CHAR_9,0);
		return digit_node;
	}


}
struct Generator_Node* add_hexadecimal_fractional_constant(struct Generator_Node *node,_Bool has_read_digits)
{
	struct Generator_Node *dot_node;
	struct Generator_Node *digit_node;

	if(has_read_digits)
	{
		dot_node=get_generator_node(null_str,"KW_DOUBLE_HEXADECIMAL_CONSTANT","KW_DOUBLE_HEXADECIMAL_CONSTANT",automata_dispense_token_str);
		connect_node(node,dot_node,NULL,CHAR_DOT,CHAR_DOT,0);
		connect_node(dot_node,dot_node,NULL,CHAR_0,CHAR_9,0);
		connect_node(dot_node,dot_node,NULL,CHAR_a,CHAR_f,0);
		connect_node(dot_node,dot_node,NULL,CHAR_A,CHAR_F,0);

		return dot_node;
	}else
	{
		dot_node=get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);
		digit_node=get_generator_node(null_str,"KW_DOUBLE_HEXADECIMAL_CONSTANT","KW_DOUBLE_HEXADECIMAL_CONSTANT",automata_dispense_token_str);
		connect_node(node,dot_node,NULL,CHAR_DOT,CHAR_DOT,0);
		connect_node(dot_node,digit_node,NULL,CHAR_0,CHAR_9,0);
		connect_node(dot_node,digit_node,NULL,CHAR_a,CHAR_f,0);
		connect_node(dot_node,digit_node,NULL,CHAR_A,CHAR_F,0);

		connect_node(digit_node,digit_node,NULL,CHAR_0,CHAR_9,0);
		connect_node(digit_node,digit_node,NULL,CHAR_a,CHAR_f,0);
		connect_node(digit_node,digit_node,NULL,CHAR_A,CHAR_F,0);
		return digit_node;
	}


}
struct Generator_Node* add_exponent_part(struct Generator_Node *node)
{
	struct Generator_Node *digit_node;
	struct Generator_Node *e_node;

	e_node=get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);
	digit_node=get_generator_node(null_str,"KW_DOUBLE_DECIMAL_CONSTANT","KW_DOUBLE_DECIMAL_CONSTANT",automata_dispense_token_str);

	connect_node(node,e_node,NULL,CHAR_e,CHAR_e,0);
	connect_node(node,e_node,NULL,CHAR_E,CHAR_E,0);

	connect_node(e_node,digit_node,NULL,CHAR_PLUS,CHAR_PLUS,0);
	connect_node(e_node,digit_node,NULL,CHAR_MINUS,CHAR_MINUS,0);
	connect_node(e_node,digit_node,NULL,CHAR_0,CHAR_9,0);

	connect_node(digit_node,digit_node,NULL,CHAR_0,CHAR_9,0);

	return digit_node;
}
struct Generator_Node* add_hexadecimal_exponent_part(struct Generator_Node *node)
{
	struct Generator_Node *digit_node;
	struct Generator_Node *p_node;

	p_node=get_generator_node(null_str,no_type_str,no_type_str,automata_no_action_str);
	digit_node=get_generator_node(null_str,"KW_DOUBLE_HEXADECIMAL_CONSTANT","KW_DOUBLE_HEXADECIMAL_CONSTANT",automata_dispense_token_str);

	connect_node(node,p_node,NULL,CHAR_p,CHAR_p,0);
	connect_node(node,p_node,NULL,CHAR_P,CHAR_P,0);

	connect_node(p_node,digit_node,NULL,CHAR_PLUS,CHAR_PLUS,0);
	connect_node(p_node,digit_node,NULL,CHAR_MINUS,CHAR_MINUS,0);
	connect_node(p_node,digit_node,NULL,CHAR_0,CHAR_9,0);

	connect_node(digit_node,digit_node,NULL,CHAR_0,CHAR_9,0);

	return digit_node;
}
void connect_node(struct Generator_Node *node,struct Generator_Node *target_node,struct Queue *node_queue,enum Source_Chars begin,enum Source_Chars end,_Bool push_nodes)
{
	int i;
	for(i=begin;i<=end;++i)
		if(node->output.delta[i]==NULL)
			node->output.delta[i]=(struct Automata_Node*)target_node;
		else if(push_nodes) 
			Queue_Push(node_queue,node->output.delta[i]);

}
#endif