// load automata for scanning valid identifiers
void Scanner::load_id_machine() {
	// create the id scan automata
	auto id_machine = FSMachinePtr(
	new FiniteMachineContainer(get_token_info(TokType::MP_ID).first,
	true));
	
	// detects ids without two underscores
	id_machine->add_state("0", true, false);
	id_machine->add_state("1", false, true);
	id_machine->add_state("2", false, true);
	id_machine->add_state("3", false, false);
	id_machine->add_state("4", false, false);
	
	// add transitions
	id_machine->add_alphabet("0", "1");
	id_machine->add_alphabet("1", "1");
	id_machine->add_digits("1", "1");
	id_machine->add_transition("1", '_', "4");
	id_machine->add_alphabet("4", "1");
	id_machine->add_digits("4", "1");
	
	// other part
	id_machine->add_transition("0", '_', "3");
	id_machine->add_alphabet("3", "2");
	id_machine->add_digits("3", "2");
	id_machine->add_alphabet("2", "2");
	id_machine->add_digits("2", "2");
	id_machine->add_transition("2", '_', "3");
	
	// set priority
	id_machine->set_priority(2);
	
	// add to finite machines
	this->fsmachines->push_back(FSMachinePtr(id_machine));
}
/**
 * This function takes a unicode string representing a regular expression and
 * compiles it into a .grf file. It returns 1 in case of success; 0 otherwise.
 */
int reg2grf(const unichar* regexp,const char* name_grf, const VersatileEncodingConfig* vec) {
if (regexp[0]=='\0') {
   error("You must specify a non empty regular expression\n");
   return 0;
}
U_FILE* out=u_fopen(vec,name_grf,U_WRITE);
if (out==NULL) {
   error("Cannot open the output file for the regular expression\n");
   return 0;
}
struct reg2grf_info* INFO=new_reg2grf_info();
/* We create the initial and final states that must have numbers 0 and 1 */
add_state(INFO,u_strdup("<E>"));
add_state(INFO,u_strdup(""));
/* We print the grf header */
u_fprintf(out,"#Unigraph\n");
u_fprintf(out,"SIZE 1313 950\n");
u_fprintf(out,"FONT Times New Roman:  12\n");
u_fprintf(out,"OFONT Times New Roman:B 12\n");
u_fprintf(out,"BCOLOR 16777215\n");
u_fprintf(out,"FCOLOR 0\n");
u_fprintf(out,"ACOLOR 12632256\n");
u_fprintf(out,"SCOLOR 16711680\n");
u_fprintf(out,"CCOLOR 255\n");
u_fprintf(out,"DBOXES y\n");
u_fprintf(out,"DFRAME y\n");
u_fprintf(out,"DDATE y\n");
u_fprintf(out,"DFILE y\n");
u_fprintf(out,"DDIR y\n");
u_fprintf(out,"DRIG n\n");
u_fprintf(out,"DRST n\n");
u_fprintf(out,"FITS 100\n");
u_fprintf(out,"PORIENT L\n");
u_fprintf(out,"#\n");

int input_state;
int output_state;
int result=reg_2_grf(regexp,&input_state,&output_state,INFO);
if (result!=1) {
   u_fclose(out);
   af_remove(name_grf);
   free_reg2grf_info(INFO);
   if (result==0) {
      error("Syntax error in regular expression\n");
   }
   return 0;
}
/* If the compilation has successed, we must link the resulting automaton piece
 * to the grf's initial and final states */
add_transition(0,input_state,INFO);
add_transition(output_state,1,INFO);
save_states(out,INFO);
free_reg2grf_info(INFO);
u_fclose(out);
return 1;
}
Exemple #3
0
//==========================================================================================================
//==========================================================================================================
NFA::NFA(Grammar& grammar) {
    // Hold the initials states created from productions for a nonterminal. This is needed for adding the
    // epsilon transitons
    map<Symbol, vector<int>> nonterminals_initial_states;
    int state = 0;

    //------------------------------------------------------------------------------------------------------
    // Add transitions for every production
    //------------------------------------------------------------------------------------------------------
    for(int i = 0; i < grammar.productions.size(); ++i, ++state) {
        if(i > 0) // The start symbol will not have any transitions defined for it
            nonterminals_initial_states[grammar.productions[i][0]].push_back(state);

        for(int j = 1; j < grammar.productions[i].size(); ++j, ++state) {
            // When adding a transition on the last symbol of the production, the state is accepting
            int accepting_val = ((j == grammar.productions[i].size() - 1) ? i : -1);
            add_transition(state, grammar.productions[i][j], state + 1, accepting_val);
        }
    }

    //------------------------------------------------------------------------------------------------------
    // Add the epsilon transitions: whenever there is a transition from state s to state t on a nonterminal
    // N, we add epsilon transitions from s to the initial states of all the NFAs for productions with N on
    // the left-hand side
    //------------------------------------------------------------------------------------------------------
    for(int s = 0; s < table.size(); ++s) {
        for(int sym = 0; sym < NUM_NON_TERMINALS; ++sym) {
            if(not table[s][sym].empty()) { // Transition is defined
                for(auto i: nonterminals_initial_states[Symbol(sym)]) {
                    add_epsilon_transition(s, i);
                }
            }
        }
    }
}
void Scanner::load_num_machines() {
	// create floating point automata for scanning numeric literals
	auto float_machine = FSMachinePtr(
	new FiniteMachineContainer(get_token_info(TokType::MP_FLOAT_LITERAL).first, true));
	
	// add states to this DFA, first and final
	float_machine->add_state("0", true, false);
	float_machine->add_state("1", false, false);
	float_machine->add_state("2", false, true);
	float_machine->add_state("3", false, false);
	float_machine->add_state("4", false, false);
	float_machine->add_state("5", false, true);
	float_machine->add_digits("0", "1");
	float_machine->add_digits("1", "1");
	float_machine->add_transition("1", '.', "2");
	float_machine->add_digits("2", "2");
	float_machine->add_transition("2", 'e', "3");
	float_machine->add_transition("2", 'E', "3");
	float_machine->add_transition("3", '+', "4");
	float_machine->add_transition("3", '-', "4");
	float_machine->add_digits("3", "5");
	float_machine->add_digits("4", "5");
	float_machine->add_digits("5", "5");
	
	// create integer automata
	auto integer_machine = FSMachinePtr(
	new FiniteMachineContainer(get_token_info(TokType::MP_INT_LITERAL).first, true));
	
	// add states to this DFA
	integer_machine->add_state("0", true, false);
	integer_machine->add_state("1", false, true);
	integer_machine->add_digits("0", "1");
	integer_machine->add_digits("1", "1");
	
	// reset both
	float_machine->reset();
	integer_machine->reset();
	
	// set machine priorities
	float_machine->set_priority(1);
	integer_machine->set_priority(1);
	
	// add both to the finite machines list
	this->fsmachines->push_back(FSMachinePtr(float_machine));
	this->fsmachines->push_back(FSMachinePtr(integer_machine));
}
void Scanner::load_strand_machines(unsigned int within) {
	// comments and strings, take that!
	// add nested strings and comments feature using within variable
	auto comment_machine = FSMachinePtr(
	new FiniteMachineContainer(get_token_info(TokType::MP_COMMENT).first, true));
	
	// add states
	comment_machine->add_state("0", true, false);
	comment_machine->add_state("1", false, false);
	comment_machine->add_state("2", false, true);
	
	// for state 1
	comment_machine->add_alphabet("1", "1");
	comment_machine->add_symbols("1", "1");
	comment_machine->add_digits("1", "1");
	comment_machine->add_transition("1", ' ', "1");
	comment_machine->add_transition("1", '\n', "1");
	comment_machine->add_transition("1", '\t', "1");
	comment_machine->add_transition("1", '\v', "1");
	comment_machine->add_transition("1", '\r', "1");
	comment_machine->add_transition("1", '\f', "1");
	comment_machine->remove_transition("1", '{');
	comment_machine->remove_transition("1", '}');
	comment_machine->add_transition("0", '{', "1");
	comment_machine->add_transition("1", '}', "2");
	
	// new machine
	auto string_machine = FSMachinePtr(
	new FiniteMachineContainer(get_token_info(TokType::MP_STRING_LITERAL).first, true));
	
	// add states
	string_machine->add_state("0", true, false);
	string_machine->add_state("1", false, false);
	string_machine->add_state("2", false, true);
	
	// add transitions
	string_machine->add_transition("0", '\'', "1");
	string_machine->add_alphabet("1", "1");
	string_machine->add_symbols("1", "1");
	string_machine->add_digits("1", "1");
	string_machine->add_transition("1", ' ', "1");
	string_machine->remove_transition("1", '\'');
	string_machine->remove_transition("1", '\'');
	string_machine->add_transition("1", '\'', "2");
	
	// set machine priority
	comment_machine->set_priority(1);
	string_machine->set_priority(1);
	
	// add the machines to our FSMachines list
	this->fsmachines->push_back(comment_machine);
	this->fsmachines->push_back(string_machine);
}
typename boost::enable_if<is_transducer<SM>,
                          typename state_machine_traits<SM>::transition>::type
add_transition (SM& sm,
                typename state_machine_traits<SM>::state       from,
                typename state_machine_traits<SM>::state       to,
                typename state_machine_traits<SM>::input_type  input,
                typename state_machine_traits<SM>::output_type output,
                typename state_machine_traits<SM>::weight_type weight)
{
    return add_transition(from, to, input, output, weight);
}
Exemple #7
0
// Reads a line of the file pointed by fptr, and adds the transition to the appropriate state.
// Line should be of the format 'a b c' where a denotes the state to which the transition belongs to, b is the symbol which transitions to the next state c.
int read_transition(state* state_table, FILE* fptr) {
	char line[MAX_LEN+1];
	int cur_state, symbol, next_state;
	
	if((fgets(line, (int)MAX_LEN, fptr)) == NULL)
		return 0;
	sscanf(line, "%d %d %d", &cur_state, &symbol, &next_state);
	state* current = &state_table[cur_state-1];
	if((add_transition(current, symbol, next_state)) == 0)
		return 0;
	return 1;
}
Exemple #8
0
SM&
set_equal (SM& sm, const expression<Expr>& expr)
{
    typename state_machine_traits<SM>::state start, end;
    start = start_state(sm);

    bool final_is_set(false);
    
    typename expression_arg<SM>::connect_const_iterator citr, cend;
    typename expression_arg<SM>::to_const_iterator titr, tend;
    typename expression_arg<SM>::from_const_iterator fitr, fend;
    expression_arg<SM> arg;
    expr.apply(sm,arg);
    citr = arg.connection_begin();
    cend = arg.connection_end();
    for(;citr != cend; ++citr) {
        add_transition(sm,start,end,citr->tok,citr->wt);
    }
    titr = arg.to_begin(); tend = arg.to_end();
    for(;titr != tend; ++titr) {
        if (!final_is_set) {
            end = add_state(sm,true);
            final_is_set=true;
        }
        add_transition(sm,start,titr->to,titr->tok,titr->wt);
    }
    fitr = arg.from_begin(); fend = arg.from_end();
    for(;fitr != fend; ++fitr) {
        if (!final_is_set) {
            end = add_state(sm,true);
            final_is_set=true;
        }
        add_transition(sm,fitr->from,end,fitr->tok,fitr->wt);
    }     
    return sm;
}
/*
Makes the state machine capable of recognizing real and integer numbers.
*/
void
add_number_recognition(STATE_MACHINE* sm)
{
    STATE* numeric_states = (STATE*) malloc(10 * sizeof(STATE));
    STATE* real_states = (STATE*) malloc(10 * sizeof(STATE));
    // State for reading a dot after a number
    STATE s_real_val = { '.', NULL, 0, 0, T_REAL_CONST };
    STATE* s_real = (STATE*) malloc(sizeof(STATE));
    memcpy(s_real, &s_real_val, sizeof(STATE));

    //Constructs states for real numbers after the dot.
    for (size_t i = 0; i < 10; i++)
    {
        STATE s = { numerics[i], NULL, 0, 0, T_REAL_CONST };
        memcpy(real_states + i, &s, sizeof(STATE));
    }
    // Adds recursive transitions to each other real number state
    for (size_t i = 0; i < 10; i++)
    {
        for (size_t j = 0; j < 10; j++)
        {
            // Allows a digit to be followed by a digit.
            add_transition(real_states + i, real_states + j);
        }
    }
    // Allows a dot to be followed by any digit.
    for (size_t i = 0; i < 10; i++)
    {
        add_transition(s_real, real_states + i);
    }
    // Constructs states for integers.
    for (size_t i = 0; i < 10; i++)
    {
        STATE s = { numerics[i], NULL, 0, 0, T_INT_CONST };
        memcpy(numeric_states + i, &s, sizeof(STATE));
    }
    for (size_t i = 0; i < 10; i++)
    {
        for (size_t j = 0; j < 10; j++)
        {
            // Allows a digit to be followed by a digit.
            add_transition(numeric_states + i, numeric_states + j);
        }
        // An integer followed by a dot becomes a real.
        add_transition(numeric_states + i, s_real);
    }
    for (size_t i = 0; i < 10; i++)
    {
        add_transition((sm)->initial_state, numeric_states + i);
    }
    add_transition((sm)->initial_state, s_real);
}
Exemple #10
0
int expand(char c, int from_state, int to_state) {
    int i;
    char weird[] = "~!@#$%^&()_+[{]}\\|;:,<.>/?";
    int W_L = 27;
    switch (c) {
        case 'o':
            for (i = '7'; i >= '0'; --i) {
                add_transition(from_state, i, to_state);
            }
            return 1;
        case 'd':
            for (i = '9'; i >= '0'; --i) {
                add_transition(from_state, i, to_state);
            }
            return 1;
        case 'h':
            for (i = '9'; i >= '0'; --i) {
                add_transition(from_state, i, to_state);
            }
            for (i = 'f'; i >= 'a'; --i) {
                add_transition(from_state, i, to_state);
            }
            for (i = 'F'; i >= 'A'; --i) {
                add_transition(from_state, i, to_state);
            }
            return 1;
        case 'c':
            for (i = 'z'; i >= 'a'; --i) {
                add_transition(from_state, i, to_state);
            }
            for (i = 'Z'; i >= 'A'; --i) {
                add_transition(from_state, i, to_state);
            }
            return 1;
        case 'w':
            for (i = W_L; i >= 0; i --) {
                add_transition(from_state, weird[i], to_state);
            }
        default:
            return 0;
    }
}
Exemple #11
0
/*
Adds the non-conflicting id_alphanumeric_states to s for recognizing
identifiers, such as function names et al.
*/
void
add_identifier_states(STATE* s,
                      STATE* id_alphanumeric_states,
                      size_t num_alphanum)
{
    for (size_t i = 0; i < num_alphanum; i++)
    {
        size_t j;
        for (j = 0; j < s->num_transitions; j++)
        {
            if (s->allowed_transitions[j]->state == alphanumerics[i]) break;
        }
        if (j < s->num_transitions) continue;
        add_transition(s, id_alphanumeric_states + i);
        for (j = 0; j < s->num_transitions; j++)
        {
            add_identifier_states(s->allowed_transitions[i], id_alphanumeric_states, num_alphanum);
        }
    }
}
Exemple #12
0
/*
Makes a state machine recognize any token in unsorted_tokens,
returning T_ID for incomplete tokens.
*/
void
add_basic_tokenizing(STATE_MACHINE* sm,
                     PAIR* unsorted_tokens,
                     size_t num_tokens)
{
    PAIR* tokens = (PAIR*) malloc(num_tokens * sizeof(PAIR));
    memcpy(tokens, unsorted_tokens, num_tokens * sizeof(PAIR));
    qsort(tokens, num_tokens, sizeof(PAIR), compare_string_size);

    for (size_t i = 0; i < num_tokens; i++)
    {
        size_t j;
        for (j = 0; j < i; j++)
        {
            if (tokens[i].token[0] == tokens[j].token[0]) break;
        }
        if (j < i) continue;
        STATE* s = make_basic_tokenizer_state(tokens, num_tokens, tokens[i].token, tokens[i].type, 0);
        add_transition(sm->initial_state, s);
    }
    free(tokens);
//    return sm;
}
Exemple #13
0
/*
Makes a state that recognizes the the string value from
the character in 'depth' onwards, while having branches to
any other tokens that have are the same up to 'depth'
characters. I.e., if depth=0 and value = 'void', and
there are also other tokens starting with 'v', the
returned state will recognize 'v', and have branches to
'void' and all other tokens starting with 'v', creating
a tree structure that can be traversed to find the TOKEN_TYPE
of a string.
*/
STATE*
make_basic_tokenizer_state(const PAIR * tokens,
                           size_t num_tokens,
                           char* value,
                           TOKEN_TYPE type,
                           size_t depth)
{
    STATE initial_state_val = { value[depth], NULL, 0, 0, type  };
    for (size_t i = 0; i < num_tokens; i++)
    {
        char* token = tokens[i].token;
        TOKEN_TYPE next_type = tokens[i].type;

        if (!strncmp(token, value, depth + 1))
        {
            if (token[depth + 1] == '\0') continue;
            else
            {
                size_t j;
                for (j = 0; j < i; j++)
                {
                    char* token_to_check = tokens[j].token;
                    // Comparing until position depth + 1 is the same as comparing depth + 2 positions
                    if (!strncmp(token, token_to_check, depth + 2)) break;
                }
                if (j < i) continue;
            }
            if (strlen(token) > depth + 2) next_type = T_INVALID;
            STATE* to_add = make_basic_tokenizer_state(tokens, num_tokens, token, next_type, depth + 1);
            add_transition(&initial_state_val, to_add);
        }
    }
    STATE* state = (STATE*) malloc(sizeof(STATE));
    memcpy(state, &initial_state_val, sizeof(STATE));
    return state;
}
Exemple #14
0
void main_menu_dlg::on_init_dialog()
{
	h_screen_paradigm scr_paradigm = get_framework()->get_screen_paradigm();
	h_string suffix = get_framework()->get_screen_paradigm_suffix(scr_paradigm);

	scene_manager* scene_manager = get_ctrl()->get_scene_manager();

	int w_scr = get_framework()->get_display_settings().width;
	int h_scr = get_framework()->get_display_settings().height;
	set_size(h_vector((float)w_scr, (float)h_scr));

	h_scene_object_base_ptr background(new h_scene_object_base("background_panel"));
	add_child(background);
	background->add_sprite("/images/menu/dlg_base" + suffix, "background_panel");
	background->set_pos(scene_manager->get_scene_center() - background->get_size() / 2);

	//scene_manager* scene_manager = get_ctrl()->get_scene_manager();

	static const float height_button_t0[3] = { 43, 73, 86 };
	static const float height_button_t1[3] = { 65, 111, 130 };

	static const float width_button[3] = { 165, 280, 329 };

	h_button_ptr button_sel_tree;
	h_button_ptr button_sel_background;
	h_button_ptr button_share_social;
	h_button_ptr button_email;
	h_button_ptr button_to_img;
	h_button_ptr button_clear;


	h_vector offset_img(0, 0);
	// select tree..
	{
		/*button_sel_tree.reset(new h_button("select_tree"));
		add_child(button_sel_tree); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t0[scr_paradigm]) + offset_img;
		button_sel_tree->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_sel_tree->set_action(std::tr1::bind(&scene_manager::on_change_tree, 
													get_ctrl()->get_scene_manager()));
		offset_img += h_vector(0, height_button_t0[scr_paradigm]);*/
	}
	 
	// select background..
	{

		button_sel_background.reset(new h_button("select_background"));
		background->add_child(button_sel_background); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t0[scr_paradigm]) + offset_img;
		button_sel_background->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_sel_background->set_action(std::tr1::bind(&scene_manager::on_change_background, 
												   get_ctrl()->get_scene_manager()));
		offset_img += h_vector(0, height_button_t0[scr_paradigm]);
	}

	// share to social..
	{

		//button_share_social.reset(new h_button("share_social"));
		//background->add_child(button_share_social); 

		//h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		//h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t1[scr_paradigm]) + offset_img;
		//button_share_social->load_images("/images/menu/menu_buttons_0" + suffix, 
		//							 pos_coord_img_tl, pos_coord_img_br,
		//							 pos_coord_img_tl, pos_coord_img_br);
		////button_sel_tree->set_action(std::tr1::bind(&scene_manager::on_select_toys_dlg, 
		////							get_ctrl()->get_scene_manager(), dlg_balls));
		//offset_img += h_vector(0, height_button_t1[scr_paradigm]);
	}


	// export to image..
	{

		button_to_img.reset(new h_button("to_img"));
		background->add_child(button_to_img); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t1[scr_paradigm]) + offset_img;
		button_to_img->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_to_img->set_action(std::tr1::bind(&scene_manager::on_export_image, 
									get_ctrl()->get_scene_manager()));
		offset_img += h_vector(0, height_button_t1[scr_paradigm]);
	}

	// send..
	{

		button_email.reset(new h_button("email"));
		background->add_child(button_email); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t0[scr_paradigm]) + offset_img;
		button_email->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_email->set_action(std::tr1::bind(&scene_manager::send_email, 
									get_ctrl()->get_scene_manager()));
		offset_img += h_vector(0, height_button_t0[scr_paradigm]);
	}


	// clear..
	{
		button_clear.reset(new h_button("clear"));
		background->add_child(button_clear); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t0[scr_paradigm]) + offset_img;
		button_clear->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_clear->set_action(std::tr1::bind(&scene_manager::on_clear, 
									get_ctrl()->get_scene_manager()));
		//offset_img += h_vector(0, height_button_t0[scr_paradigm]);
	}
	h_scene_object_ptr buttons[g_num_buttons] = { button_sel_background, 
												  button_to_img,
												  button_email,
												  button_clear };
	float height_all_buttons = 0;
	for (int i = 0; i < g_num_buttons; i++)	{
		height_all_buttons += buttons[i]->get_size().y;
		buttons[i]->get_sprites()->get_sprite(0)->set_filter(true);
	}

	float w = buttons[0]->get_size().x;

	float menu_height = background->get_size().y;
	float v = menu_height - height_all_buttons;
	float vx = background->get_size().x - w;

	float seg = v / (g_num_buttons + 1);
	float y_offset = background->get_size().y;
	for (int i = 0; i < g_num_buttons; i++)
	{
		float height = buttons[i]->get_size().y;
		y_offset += -height;//seg; 
		buttons[i]->set_pos(h_vector(vx / 2, y_offset - v / 2));
	}
	
	h_vector center = scene_manager->get_scene_center() - get_size() / 2;
	h_vector start_pos = h_vector(center.x, -get_size().y);
	h_vector end_pos(center);
	//static const float offset_from_center[3] = { 35, 70, 0 };
	//offset_pos(h_vector(0, offset_from_center[scr_paradigm]));

	h_transition_ptr trans(new h_transition_position(start_pos, end_pos, 170));
	add_transition(trans, true);
	trans->start();
}
/**
 * This function takes a regular expression and builds the corresponding
 * Thompson automaton. To do that, we use the following grammar:
 *
 * S -> E \0
 * E -> E + E
 * E -> E . E
 * E -> E E
 * E -> E Y E
 * E -> (E)
 * E -> E*
 * E -> TOKEN
 * Y -> SPACE
 * Y -> SPACE Y
 *
 * with priority(*) > priority(.) > priority(+)
 *
 * If we have the following expression:
 *
 * <DET> (very <A>+<E>).<N> of <<es$>>
 *
 * tokens will be "<DET>", "very", "<A>", "<E>", "<N>", "of" and "<<es$>>"
 *
 * See comments in "RegularExpressions.h" for more details.
 *
 * We use two integer stacks: one for the LR analyzer that contains the item automaton
 * states number and another that contains, for each piece of automaton being built, the
 * numbers of the input and output states of this piece.
 * The function returns 1 in case of success; 0 in case of a syntax error in the
 * expression and 2 in case of a malformed token.
 */
int reg_2_grf(const unichar* regexp,int *input_state,int *output_state,struct reg2grf_info* info) {
/* transE represents the transitions tagged with the non terminal E in the LR table.
 * transY does sthe same for Y  */
int transE[19]={4,-1,5,-1,12,12,-1,15,16,-1,-1,-1,12,18,-1,12,12,-1,12};
int transY[19]={-1,-1,-1,-1,13,13,-1,-1,-1,17,-1,-1,13,-1,-1,13,13,-1,13};
struct stack_int* stack=new_stack_int(1024);
struct stack_int* couples=new_stack_int(1024);
int value=-1;
int pos=0;
unichar token[REG_EXP_MAX_LENGTH];
/* We initialize the LR analyze stack */
stacki_push(stack,0);
while (value==-1) {
   int state=stack->stack[stack->stack_pointer];
   switch (state) {
      /* state 0 */
      case 0: {
         switch(regexp[pos]) {
            case '+':
            case ')':
            case '*':
            case '.':
            case ' ':
            case '\0': {
               /* Failure */
               value=0; break;
            }
            case '(': {
               pos++;
               stacki_push(stack,2);
               break;
            }
            default: {
               /* When we read a token, we create a state with this content */
               if (!read_token(regexp,&pos,token)) {
                  /* Failure */
                  value=2; break;
               }
               int n=add_state(info,u_strdup(token));
               stacki_push(couples,n);
               stacki_push(couples,n);
               stacki_push(stack,1);
               break;
            }
         }
         break;
      }
      /* state 1 */
      case 1: {
         /* If we must reduce with the rule E -> TOKEN,
          * there is nothing to pop/push in the couple stack, but
          * we pop 1 right member */
          stacki_pop(stack);
          /* We look in the LR table where to go */
          int next_state=transE[stack->stack[stack->stack_pointer]];
          if (next_state==-1) {
             /* Failure */
             value=0; break;
             }
          stacki_push(stack,next_state);
          break;
      }
      /* state 2 */
      case 2: {
         switch(regexp[pos]) {
            case '+':
            case ')':
            case '*':
            case '.':
            case ' ':
            case '\0': {
               /* Failure */
               value=0; break;
            }
            case '(': {
               pos++;
               stacki_push(stack,2);
               break;
            }
            default: {
               /* When we read a token, we create a state with this content */
               if (!read_token(regexp,&pos,token)) {
                  /* Failure */
                  value=2; break;
               }
               int n=add_state(info,u_strdup(token));
               stacki_push(couples,n);
               stacki_push(couples,n);
               stacki_push(stack,1);
               break;
            }
         }
         break;
      }
      /* state 3 */
      case 3: {
         /* Should not appear, since we quit the automaton when we have read the final '\0' */
         fatal_error("reg_2_grf: illegal position in state 3\n");
      }
      /* state 4 */
      case 4: {
         switch(regexp[pos]) {
            case '+': {
               pos++;
               stacki_push(stack,7);
               break;
            }
            case '.': {
               pos++;
               stacki_push(stack,8);
               break;
            }
            case ' ': {
               pos++;
               stacki_push(stack,9);
               break;
            }
            case '*': {
               pos++;
               stacki_push(stack,10);
               break;
            }
            case '\0': {
               pos++;
               stacki_push(stack,11);
               break;
            }
            case '(': {
               pos++;
               stacki_push(stack,2);
               break;
            }
            case ')': {
               /* Failure */
               value=0; break;
            }
            default: {
               /* When we read a token, we create a state with this content */
               if (!read_token(regexp,&pos,token)) {
                  /* Failure */
                  value=2; break;
               }
               int n=add_state(info,u_strdup(token));
               stacki_push(couples,n);
               stacki_push(couples,n);
               stacki_push(stack,1);
               break;
            }
         }
         break;
      }
      /* state 5 */
      case 5: {
         switch(regexp[pos]) {
            case '+': {
               pos++;
               stacki_push(stack,7);
               break;
            }
            case '.': {
               pos++;
               stacki_push(stack,8);
               break;
            }
            case ' ': {
               pos++;
               stacki_push(stack,9);
               break;
            }
            case '*': {
               pos++;
               stacki_push(stack,10);
               break;
            }
            case '(': {
               pos++;
               stacki_push(stack,2);
               break;
            }
            case ')': {
               pos++;
               stacki_push(stack,14);
               break;
            }
            case '\0': {
               /* Failure */
               value=0; break;
            }
            default: {
               /* When we read a token, we create a state with this content */
               if (!read_token(regexp,&pos,token)) {
                  /* Failure */
                  value=2; break;
               }
               int n=add_state(info,u_strdup(token));
               stacki_push(couples,n);
               stacki_push(couples,n);
               stacki_push(stack,1);
               break;
            }
         }
         break;
      }
      /* state 6 */
      case 6: {
         /* Should not appear, since we quit the automaton when we have read the final '\0' */
         fatal_error("reg_2_grf: illegal position in state 6\n");
      }
      /* state 7 */
      case 7: {
         switch(regexp[pos]) {
            case '+':
            case ')':
            case '*':
            case '.':
            case ' ':
            case '\0': {
               /* Failure */
               value=0; break;
            }
            case '(': {
               pos++;
               stacki_push(stack,2);
               break;
            }
            default: {
               /* When we read a token, we create a state with this content */
               if (!read_token(regexp,&pos,token)) {
                  /* Failure */
                  value=2; break;
               }
               int n=add_state(info,u_strdup(token));
               stacki_push(couples,n);
               stacki_push(couples,n);
               stacki_push(stack,1);
               break;
            }
         }
         break;
      }
      /* state 8 */
      case 8: {
         switch(regexp[pos]) {
            case '+':
            case ')':
            case '*':
            case '.':
            case ' ':
            case '\0': {
               /* Failure */
               value=0; break;
            }
            case '(': {
               pos++;
               stacki_push(stack,2);
               break;
            }
            default: {
               /* When we read a token, we create a state with this content */
               if (!read_token(regexp,&pos,token)) {
                  /* Failure */
                  value=2; break;
               }
               int n=add_state(info,u_strdup(token));
               stacki_push(couples,n);
               stacki_push(couples,n);
               stacki_push(stack,1);
               break;
            }
         }
         break;
      }
      /* state 9 */
      case 9: {
         switch(regexp[pos]) {
            case ' ': {
               pos++;
               stacki_push(stack,9);
               break;
            }
            default:  {
               /* If we must reduce with the rule Y -> SPACE,
                * there is nothing to pop/push in the couple stack, but
                * we pop 1 right member */
               stacki_pop(stack);
               /* We look in the LR table where to go */
               int next_state=transY[stack->stack[stack->stack_pointer]];
               if (next_state==-1) {
                  /* Failure */
                  value=0; break;
               }
               stacki_push(stack,next_state);
            }
         }
         break;
      }
      /* state 10 */
      case 10: {
         /* If we must reduce with the rule rule E -> E*,
          * we pop 2 right members */
         stacki_pop(stack);
         stacki_pop(stack);
         /* We look in the LR table where to go */
         int next_state=transE[stack->stack[stack->stack_pointer]];
         if (next_state==-1) {
            /* Failure */
            value=0;
            break;
         }
         stacki_push(stack, next_state);
         /* We pop the automaton A ->.....-> B */
         int B=stacki_pop(couples);
         int A=stacki_pop(couples);
         /* Then we create 2 empty states */
         int input=add_state(info, u_strdup("<E>"));
         int output=add_state(info, u_strdup("<E>"));
         /* We rely them to A and B */
         add_transition(input, A, info);
         add_transition(B, output, info);
         /* We create a loop relying B to A */
         add_transition(B, A, info);
         /* And we rely input to output since the Kleene star matches the
          * empty word */
         add_transition(input, output, info);
         /* Finally we push the automaton input ->.....-> output */
         stacki_push(couples, input);
         stacki_push(couples, output);
         break;
      }
      /* state 11 */
      case 11: {
         /* If we must reduce by S -> E '0', we have matched the whole expression */
         /* We return the input and output state numbers of the automaton */
         *output_state=stacki_pop(couples);
         *input_state=stacki_pop(couples);
         value=1;
         break;
      }
      /* state 12 */
      case 12: {
         switch(regexp[pos]) {
            case '*': {
               pos++;
               stacki_push(stack,10);
               break;
            }
            default: {
               /* If we must reduce with the rule E -> EE,
                * we pop 2 right members */
               stacki_pop(stack);
               stacki_pop(stack);
               /* We look in the LR table where to go */
               int next_state=transE[stack->stack[stack->stack_pointer]];
               if (next_state==-1) {
                  /* Failure */
                  value=0;
                  break;
               }
               stacki_push(stack, next_state);
               /* We pop 2 automata A ->.....-> B and C ->.....-> D */
               int D=stacki_pop(couples);
               int C=stacki_pop(couples);
               int B=stacki_pop(couples);
               int A=stacki_pop(couples);
               /* We rely B to C */
               add_transition(B, C, info);
               /* And we push the automaton A ->.....-> D */
               stacki_push(couples, A);
               stacki_push(couples, D);
               break;
            }
         }
         break;
      }
      /* state 13 */
      case 13: {
         switch(regexp[pos]) {
            case '+':
            case ')':
            case '*':
            case '.':
            case ' ':
            case '\0': {
               /* Failure */
               value=0; break;
            }
            case '(': {
               pos++;
               stacki_push(stack,2);
               break;
            }
            default: {
               /* When we read a token, we create a state with this content */
               if (!read_token(regexp,&pos,token)) {
                  /* Failure */
                  value=2; break;
               }
               int n=add_state(info,u_strdup(token));
               stacki_push(couples,n);
               stacki_push(couples,n);
               stacki_push(stack,1);
               break;
            }
         }
         break;
      }
      /* state 14 */
      case 14: {
         /* If we must reduce with the rule E -> (E),
          * we pop 3 right members */
         stacki_pop(stack);
         stacki_pop(stack);
         stacki_pop(stack);
         /* We look in the LR table where to go */
         int next_state=transE[stack->stack[stack->stack_pointer]];
         if (next_state==-1) {
            /* Failure */
            value=0; break;
         }
         stacki_push(stack,next_state);
         /* And we have nothing else to do */
         break;
      }
      /* state 15 */
      case 15: {
         switch(regexp[pos]) {
            case '+':
            case ')':
            case '\0': {
               /* If we must reduce with the rule E -> E+E,
                * we pop 3 right members */
               stacki_pop(stack);
               stacki_pop(stack);
               stacki_pop(stack);
               /* We look in the LR table where to go */
               int next_state=transE[stack->stack[stack->stack_pointer]];
               if (next_state==-1) {
                  /* Failure */
                  value=0; break;
               }
               stacki_push(stack,next_state);
               /* We pop 2 automata A ->.....-> B and C ->.....-> D */
               int D=stacki_pop(couples);
               int C=stacki_pop(couples);
               int B=stacki_pop(couples);
               int A=stacki_pop(couples);
               /* Then we create 2 empty states */
               int input=add_state(info,u_strdup("<E>"));
               int output=add_state(info,u_strdup("<E>"));
               /* We rely input to A and C */
               add_transition(input,A,info);
               add_transition(input,C,info);
               /* We rely B and D to output */
               add_transition(B,output,info);
               add_transition(D,output,info);
               /* Finally we push the automaton input ->.....-> output */
               stacki_push(couples,input);
               stacki_push(couples,output);
               break;
            }
            case '*': {
               pos++;
               stacki_push(stack,10);
               break;
            }
            case '.': {
               pos++;
               stacki_push(stack,8);
               break;
            }
            case ' ': {
               pos++;
               stacki_push(stack,9);
               break;
            }
            case '(': {
               pos++;
               stacki_push(stack,2);
               break;
            }
            default: {
               /* When we read a token, we create a state with this content */
               if (!read_token(regexp,&pos,token)) {
                  /* Failure */
                  value=2; break;
               }
               int n=add_state(info,u_strdup(token));
               stacki_push(couples,n);
               stacki_push(couples,n);
               stacki_push(stack,1);
               break;
            }
         }
         break;
      }
      /* state 16 */
      case 16: {
         switch(regexp[pos]) {
            case '*': {
               pos++;
               stacki_push(stack,10);
               break;
            }
            default: {
               /* If we must reduce with the rule E -> E.E,
                * we pop 3 right members */
               stacki_pop(stack);
               stacki_pop(stack);
               stacki_pop(stack);
               /* We look in the LR table where to go */
               int next_state=transE[stack->stack[stack->stack_pointer]];
               if (next_state==-1) {
                  /* Failure */
                  value=0; break;
               }
               stacki_push(stack,next_state);
               /* We pop 2 automata A ->.....-> B and C ->.....-> D */
               int D=stacki_pop(couples);
               int C=stacki_pop(couples);
               int B=stacki_pop(couples);
               int A=stacki_pop(couples);
               /* We rely B to C */
               add_transition(B,C,info);
               /* And we push the automaton A ->.....-> D */
               stacki_push(couples,A);
               stacki_push(couples,D);
               break;
            }
         }
         break;
      }
      /* state 17 */
      case 17: {
         /* If we must reduce with the rule Y -> SPACE Y,
          * there is nothing to pop/push in the couple stack, but
          * we pop 2 right members */
         stacki_pop(stack);
         stacki_pop(stack);
         /* We look in the LR table where to go */
         int next_state=transY[stack->stack[stack->stack_pointer]];
         if (next_state==-1) {
            /* Failure */
            value=0;
            break;
         }
         stacki_push(stack, next_state);
         break;
      }
      /* state 18 */
      case 18: {
         switch(regexp[pos]) {
            case '*': {
               pos++;
               stacki_push(stack,10);
               break;
            }
            default: {
               /* If we must reduce with the rule E -> E Y E,
                * we pop 3 right members */
               stacki_pop(stack);
               stacki_pop(stack);
               stacki_pop(stack);
               /* We look in the LR table where to go */
               int next_state=transE[stack->stack[stack->stack_pointer]];
               if (next_state==-1) {
                  /* Failure */
                  value=0; break;
               }
               stacki_push(stack,next_state);
               /* We pop 2 automata A ->.....-> B and C ->.....-> D */
               int D=stacki_pop(couples);
               int C=stacki_pop(couples);
               int B=stacki_pop(couples);
               int A=stacki_pop(couples);
               /* We rely B to C */
               add_transition(B,C,info);
               /* And we push the automaton A ->.....-> D */
               stacki_push(couples,A);
               stacki_push(couples,D);
               break;
            }
         }
         break;
      }
   }
}
free_stack_int(stack);
free_stack_int(couples);
return value;
}
Exemple #16
0
void
add_keyword_recognition(STATE_MACHINE* sm,
                        PAIR* unsorted_keywords,
                        size_t num_keywords)
{
    size_t num_alpha = strlen(alpha), num_alphanum = strlen(alphanumerics);

    PAIR* keywords = (PAIR*) malloc(num_keywords * sizeof(PAIR));
    memcpy(keywords, unsorted_keywords, num_keywords * sizeof(PAIR));
    qsort(keywords, num_keywords, sizeof(PAIR), compare_string_size);

    add_basic_keyword_tokenizing(sm, unsorted_keywords, num_keywords);

    STATE* id_alpha_states = (STATE*) malloc(num_alpha * sizeof(STATE));
    STATE* id_alphanumeric_states = (STATE*) malloc(num_alphanum * sizeof(STATE));

    for (size_t i = 0; i < num_alpha; i++)
    {
        STATE id_alpha_state_val = { alpha[i], NULL, 0, 0, T_ID };
        memcpy(id_alpha_states + i, &id_alpha_state_val, sizeof(STATE));
    }
    for (size_t i = 0; i < num_alphanum; i++)
    {
        STATE id_alphanum_state_val = { alphanumerics[i], NULL, 0, 0, T_ID };
        memcpy(id_alphanumeric_states + i, &id_alphanum_state_val, sizeof(STATE));
    }
    for (size_t i = 0; i < num_alpha; i++)
    {
        for (size_t j = 0; j < num_alphanum; j++)
        {
            // An alpha can be followed by any alphanum
            add_transition(id_alpha_states + i, id_alphanumeric_states + j);
        }
    }
    for (size_t i = 0; i < num_alphanum; i++)
    {
        for (size_t j = 0; j < num_alphanum; j++)
        {
            // An alphanum can be followed by any alphanum;
            add_transition(id_alphanumeric_states + i, id_alphanumeric_states + j);
        }
    }
    for (size_t i = 0; i < num_alpha; i++)
    {
        size_t j;
        for (j = 0; j < sm->initial_state->num_transitions; j++)
        {
            if (sm->initial_state->allowed_transitions[j]->state == alpha[i]) break;
        }
        if (j < sm->initial_state->num_transitions) continue;
        add_transition(sm->initial_state, id_alpha_states + i);
        for (j = 0; j < sm->initial_state->num_transitions; j++)
        {
            // If the character in the state is an alpha, it should be able to segue
            // into the identifier states.
            if (strchr(alpha, sm->initial_state->allowed_transitions[i]->state))
            {
                // Adds identifier recognition to the first states, recursion will make
                // this bubble up to their transitioned states.
                add_identifier_states(sm->initial_state->allowed_transitions[i], id_alphanumeric_states, num_alphanum);
            }
        }
    }
}
Exemple #17
0
void load_mob_lizard_thief_data()
{
    const EntityType type = ENTITY_MONSTER_LIZARD_THIEF;

    entity_data->begin_attaching_to(type);

    (void)ADD_COMPONENT(PositionMomentum);

    auto mob = ADD_COMPONENT(SpriteMob);
    mob->mob.set_type("lizard_thief");

    auto dims = ADD_COMPONENT(Dimension);
    dims->set_height(t_mob::get_mob_height(mob->mob.type) * 1.9f);
    dims->set_width(t_mob::get_mob_width(mob->mob.type) * 1.9f);

    auto health = ADD_COMPONENT(HitPoints);
    health->health = 80;
    health->health_max = 80;

    #if DC_CLIENT
    auto anim = ADD_COMPONENT(Animation);
    anim->color = Color(21, 150, 21);
    anim->count = 40;
    anim->count_max = 60;
    anim->size = 0.1;
    anim->force = 1.0f;
    #endif

    #if DC_SERVER
    auto dest = ADD_COMPONENT(DestinationTargeting);
    dest->sight_range = 15.0f;
    dest->destination_choice_x = 20;
    dest->destination_choice_y = 20;
    dest->speed = 0.125f;
    dest->max_z_diff = 5;

    auto agent = ADD_COMPONENT(AgentTargeting);
    agent->sight_range = 15.0f;
    agent->speed = 0.18f;
    agent->max_z_diff = 5;
    agent->max_lock_ticks = ONE_SECOND * 10;
    agent->proximity_radius = 2.1f;
    agent->attack_rate = (3 * ONE_SECOND) / 2;
    agent->attack_damage = 2;

    auto waiting = ADD_COMPONENT(Waiting);
    waiting->wait_time = ONE_SECOND * 3;

    auto limiter = ADD_COMPONENT(RateLimit);
    limiter->limit = MOB_BROADCAST_RATE;

    auto item_drop = ADD_COMPONENT(ItemDrop);
    item_drop->drop->set_max_drop_types(3);
    item_drop->drop->set_max_drop_amounts("synthesizer_coin", 3);
    item_drop->drop->add_drop("synthesizer_coin", 1, 0.3f);
    item_drop->drop->add_drop("synthesizer_coin", 2, 0.1f);
    item_drop->drop->add_drop("synthesizer_coin", 3, 0.05f);
    item_drop->drop->set_max_drop_amounts("plasma_grenade", 10);
    item_drop->drop->add_drop_range("plasma_grenade", 1, 10, 0.8f);
    item_drop->drop->set_max_drop_amounts("led_torch", 5);
    item_drop->drop->add_drop_range("led_torch", 1, 5, 0.2f);

    auto state = ADD_COMPONENT(StateMachine);
    auto conf = state->configuration;
    conf->add_state("waiting", &do_wait);
    conf->add_state("chase_agent", &chase_agent);
    conf->add_state("wander", &in_transit);
    conf->add_transition("waiting", "done_waiting", "wander", &go_to_next_destination);
    conf->add_transition("waiting", "agent_targeted", "chase_agent", NULL);
    conf->add_transition("wander", "agent_targeted", "chase_agent", NULL);
    conf->add_transition("waiting", "agent_attacked", "chase_agent", &target_attacker);
    conf->add_transition("wander", "agent_attacked", "chase_agent", &target_attacker);
    conf->add_transition("wander", "at_destination", "waiting", &begin_wait);
    conf->add_transition("chase_agent", "agent_target_lost", "waiting", &begin_wait);

    auto knockback = ADD_COMPONENT(Knockback);
    knockback->weight = 1.0f;
    #endif
}
Exemple #18
0
void build_automata() {
    char line[128];
    // int i, k, j;
    int number_of_states;
    int expanded = 0;
    int state_index, next_state_index, token_type;
    char transition_char, decode_char;
    FILE *spec_file = fopen("automata.data", "r");

    if (!spec_file) {
        printf("automata.data not found\n");
        exit(2);
    }

    do {
        fgets(line, sizeof(line), spec_file);
    } while ((line != NULL) && (line[0] == '\n' || line[0] == '!'));

    if (line == NULL) {
        printf("automata.data is not properly formatted before reading number of states\n");
        exit (3);
    }

    // Get the number of states
    sscanf(line, "%d", &number_of_states);

    // Initialize the nodes array
    nodes = (node_t**)malloc(number_of_states * sizeof (node_t*));

    if (!nodes) {
        printf("could not allocate memory for nodes\n");
        exit(8);
    }

    // Next follow the states
    do {
        fgets(line, sizeof line, spec_file);
        node_t *n;
        if (line == NULL) {
            printf("Could not read %d states from automata.data\n", number_of_states);
            exit(5);
        }
        // Skip empty lines or comments
        if (*line == '\n' || *line == '!') {
            continue;
        }
        n = (node_t*)malloc(sizeof(node_t));
        sscanf(line, "%d : %d", &state_index, &token_type);

        n->type = token_type;
        n->index = state_index;
        nodes[state_index] = n;
        number_of_states--;
    } while(number_of_states != 0); 

    // Here we have created our array of nodes
    // From here 'till EOF come transitions
    while (fgets(line, sizeof(line), spec_file) != NULL) {
        // Skip comments
        if (*line == '\n' || *line == '!' ) continue;
        sscanf(line, "%d %c -> %d", &state_index, &transition_char, &next_state_index);
        
        decode_char = decode(transition_char);

        // If char has been changed
        if (decode_char != transition_char) {
            add_transition(state_index, decode_char, next_state_index);
            continue;
        }

        // If the char has not beed decoded
        // try to expand
        expanded = expand(transition_char, state_index, next_state_index);
        // If char has not been expanded, add it as is
        if (expanded == 0) {
            add_transition(state_index, transition_char, next_state_index); 
        }
    } 

    /*
        Leave this here just for debug
    for (i = 0; i < number_of_states; ++i) {
        printf("Node: %d\n", i);
        for (j = 0; j < 7; ++j) {
            printf("child: %d\n", j);
            k = nodes[i]->sizes[j];
            printf("size(%d, %d) = %d\n", i, j, k);
            while(k) {
                k--;
                printf("next[%d][%d] = %d \n", j, k, nodes[i]->next[j][k]);
            }
            printf("\n");
        }
    }
    */
}
Exemple #19
0
	void atn_state::add_transition(std::shared_ptr<atn::transition> const& transition)
	{
		add_transition(_transitions.size(), transition);
	}
Exemple #20
0
/*
Returns a state machine that skips brace_comments and whitespace.

TODO: This is fully hand-coded. For the love of GodJesusAllah I've got to
automate this for different comment tags.
*/
STATE_MACHINE*
make_nontoken_skipper(void)
{
    size_t num_whitespace = strlen(whitespace);
    STATE_MACHINE* sm = (STATE_MACHINE*) malloc(sizeof(STATE_MACHINE));

    // Fugly, but necessary because this is f*****g c
    STATE* initial_state = (STATE*) malloc(sizeof(STATE));
    STATE* start_comment_brace = (STATE*) malloc(sizeof(STATE));
    STATE* end_comment_brace = (STATE*) malloc(sizeof(STATE));
    STATE* maybe_start_comment_bracket = (STATE*) malloc(sizeof(STATE));
    STATE* start_comment_bracket = (STATE*) malloc(sizeof(STATE));
    STATE* maybe_end_comment_bracket = (STATE*) malloc(sizeof(STATE));
    STATE* end_comment_bracket = (STATE*) malloc(sizeof(STATE));

    STATE initial_state_val = { 0, NULL, 0, 0, T_ID };
    STATE start_comment_brace_val = { '{', NULL, 0, 0, T_INVALID };
    STATE end_comment_brace_val = { '}', NULL, 0, 0, T_ID };
    STATE maybe_start_comment_bracket_val = {'(', NULL, 0, 0, T_REWIND_ONE};
    STATE start_comment_bracket_val = {'*', NULL, 0, 0, T_INVALID};
    STATE maybe_end_comment_bracket_val = {'*', NULL, 0, 0, T_INVALID};
    STATE end_comment_bracket_val = {')', NULL, 0, 0, T_ID};

    memcpy(initial_state, &initial_state_val, sizeof(STATE));
    memcpy(start_comment_brace, &start_comment_brace_val, sizeof(STATE));
    memcpy(end_comment_brace, &end_comment_brace_val, sizeof(STATE));
    memcpy(maybe_end_comment_bracket, &maybe_end_comment_bracket_val, sizeof(STATE));
    memcpy(end_comment_bracket, &end_comment_bracket_val, sizeof(STATE));
    memcpy(start_comment_bracket, &start_comment_bracket_val, sizeof(STATE));
    memcpy(maybe_start_comment_bracket, &maybe_start_comment_bracket_val, sizeof(STATE));

    STATE_MACHINE sm_val = { initial_state, initial_state };
    memcpy(sm, &sm_val, sizeof(STATE_MACHINE));

    add_transition(start_comment_brace, end_comment_brace);
    add_transition(maybe_start_comment_bracket, start_comment_bracket);
    add_transition(start_comment_bracket, maybe_end_comment_bracket);
    add_transition(maybe_end_comment_bracket, end_comment_bracket);

    STATE* states_inside_brace_comments = (STATE*) malloc((0x7e - 0x20 + 4) * sizeof(STATE));

    int c = 0;
    for (char i = 0x20; i <= 0x7e; i++)
    {
        STATE state = { i, NULL, 0, 0, T_INVALID };
        memcpy(states_inside_brace_comments + c, &state, sizeof(STATE));
        if (i != '}')
        {
            add_transition(start_comment_brace, states_inside_brace_comments + c);
            add_transition(states_inside_brace_comments + c, end_comment_brace);
            c++;
        }
    }
    // Allow tabs, newlines, vtabs and carriage returns inside brace_comments.
    for (size_t i = 0; i < 4; i++)
    {
        STATE state = { whitespace[i], NULL, 0, 0, T_INVALID };
        memcpy(states_inside_brace_comments + c, &state, sizeof(STATE));
        add_transition(states_inside_brace_comments + c, end_comment_brace);
        c++;
    }
    for (char i = 0; i < 0x7e - 0x20 + 4; i++)
    {
        for (char j = 0; j < 0x7e - 0x20 + 4; j++)
        {
            add_transition(states_inside_brace_comments + i, states_inside_brace_comments + j);
        }
    }

    STATE* states_inside_bracket_comments = (STATE*) malloc((0x7e - 0x20 + 4) * sizeof(STATE));
    c = 0;
    for (char i = 0x20; i <= 0x7e; i++)
    {
        STATE state = { i, NULL, 0, 0, T_INVALID };
        memcpy(states_inside_bracket_comments + c, &state, sizeof(STATE));
        if (i != '*')
        {
            add_transition(start_comment_bracket, states_inside_bracket_comments + c);
            add_transition(states_inside_bracket_comments + c, maybe_end_comment_bracket);
            // If after *, a ) doesn't segue, we are still inside a comment.
            if (i != ')')
                add_transition(maybe_end_comment_bracket, states_inside_bracket_comments + c);
            c++;
        }
    }
    // Allow tabs, newlines, vtabs and carriage returns inside bracket_comments.
    for (size_t i = 0; i < 4; i++)
    {
        STATE state = { whitespace[i], NULL, 0, 0, T_INVALID };
        memcpy(states_inside_bracket_comments + c, &state, sizeof(STATE));
        add_transition(states_inside_bracket_comments + c, maybe_end_comment_bracket);
        c++;
    }
    for (char i = 0; i < 0x7e - 0x20 + 4; i++)
    {
        for (char j = 0; j < 0x7e - 0x20 + 4; j++)
        {
            add_transition(states_inside_bracket_comments + i, states_inside_bracket_comments + j);
        }
    }
    STATE* whitespace_states = (STATE*) malloc(num_whitespace * sizeof(STATE));
    for (size_t i = 0; i < num_whitespace; i++)
    {
        STATE state = { whitespace[i], NULL, 0, 0, T_ID };
        memcpy(whitespace_states + i, &state, sizeof(STATE));
    }
    for (size_t i = 0; i < num_whitespace; i++)
    {
        for (size_t j = 0; j < num_whitespace; j++)
        {
            add_transition(whitespace_states + i, whitespace_states + j);
        }
        add_transition(whitespace_states + i, start_comment_brace);
        add_transition(whitespace_states + i, maybe_start_comment_bracket);
        add_transition(end_comment_brace, whitespace_states + i);
        add_transition(end_comment_bracket, whitespace_states + i);
    }

    for (size_t i = 0; i < num_whitespace; i++)
    {
        add_transition(sm->initial_state, whitespace_states + i);
    }
    add_transition(sm->initial_state, start_comment_brace);
    add_transition(sm->initial_state, maybe_start_comment_bracket);

    return sm;
}