#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