/* Autogenerated with DRAKON Editor 1.31 */
#include "automaton-c.h"

#include <stdio.h>
static int g_initialised = 0;
static obj_list* llong_ops = 0;
static string8* lop_chars = 0;

struct token {
	tobject base;
	int type;
	string8* text; // own
};

static type_info_t token_t = { 
	OBJECT_SIGNATURE,
	"token",
	(destructor_fun)token_destroy
};

struct lexer_data {
	string8* current; // ref
	obj_list* tokens; // ref, token[]
};
static void UnexpectedBranch(
    int value
);

static void add_char(
    lexer_data* data,
    char c
);

static void create_identifier(
    lexer_data* data
);

static void create_number(
    lexer_data* data
);

static void create_operator(
    lexer_data* data
);

static void create_token(
    lexer_data* data,
    int type
);

static void init(void);

static int is_digit(
    char c
);

static int is_letter(
    char c
);

static int is_long_op(
    char first,
    char second
);

static int is_operator(
    char c
);

static int lexer_identifier_digit(
    lexer_data* data,
    char c
);

static int lexer_identifier_letter(
    lexer_data* data,
    char c
);

static int lexer_identifier_operator(
    lexer_data* data,
    char c
);

static int lexer_identifier_whitespace(
    lexer_data* data,
    char c
);

static int lexer_idle_digit(
    lexer_data* data,
    char c
);

static int lexer_idle_letter(
    lexer_data* data,
    char c
);

static int lexer_idle_operator(
    lexer_data* data,
    char c
);

static int lexer_idle_whitespace(
    lexer_data* data,
    char c
);

static int lexer_number_digit(
    lexer_data* data,
    char c
);

static int lexer_number_dummy(
    lexer_data* data,
    char c
);

static int lexer_number_letter(
    lexer_data* data,
    char c
);

static int lexer_number_operator(
    lexer_data* data,
    char c
);

static int lexer_number_whitespace(
    lexer_data* data,
    char c
);

static int lexer_operator_digit(
    lexer_data* data,
    char c
);

static int lexer_operator_letter(
    lexer_data* data,
    char c
);

static int lexer_operator_operator(
    lexer_data* data,
    char c
);

static int lexer_operator_whitespace(
    lexer_data* data,
    char c
);

static int try_make_long_op(
    lexer_data* data,
    char c
);


#define LEXER_IDLE 1
#define LEXER_IDENTIFIER 2
#define LEXER_NUMBER 3
#define LEXER_OPERATOR 4
typedef int (*lexer_callback)(lexer_data* data, char c);
lexer_callback lexer_digit_methods[] = {
    0,
    lexer_idle_digit,
    lexer_identifier_digit,
    lexer_number_digit,
    lexer_operator_digit
};
lexer_callback lexer_dummy_methods[] = {
    0,
    0,
    0,
    lexer_number_dummy,
    0
};
lexer_callback lexer_letter_methods[] = {
    0,
    lexer_idle_letter,
    lexer_identifier_letter,
    lexer_number_letter,
    lexer_operator_letter
};
lexer_callback lexer_operator_methods[] = {
    0,
    lexer_idle_operator,
    lexer_identifier_operator,
    lexer_number_operator,
    lexer_operator_operator
};
lexer_callback lexer_whitespace_methods[] = {
    0,
    lexer_idle_whitespace,
    lexer_identifier_whitespace,
    lexer_number_whitespace,
    lexer_operator_whitespace
};
int lexer_digit(int* machine, lexer_data* data, char c) {
    lexer_callback fun;
    int next;
    if (machine == 0) return 0;
    if (*machine <= 0 || *machine > 4) return 0;
    fun = lexer_digit_methods[*machine];
    if (!fun) return 0;
    next = fun(data, c);
    *machine = next;
    return 1;
}
int lexer_dummy(int* machine, lexer_data* data, char c) {
    lexer_callback fun;
    int next;
    if (machine == 0) return 0;
    if (*machine <= 0 || *machine > 4) return 0;
    fun = lexer_dummy_methods[*machine];
    if (!fun) return 0;
    next = fun(data, c);
    *machine = next;
    return 1;
}
int lexer_letter(int* machine, lexer_data* data, char c) {
    lexer_callback fun;
    int next;
    if (machine == 0) return 0;
    if (*machine <= 0 || *machine > 4) return 0;
    fun = lexer_letter_methods[*machine];
    if (!fun) return 0;
    next = fun(data, c);
    *machine = next;
    return 1;
}
int lexer_operator(int* machine, lexer_data* data, char c) {
    lexer_callback fun;
    int next;
    if (machine == 0) return 0;
    if (*machine <= 0 || *machine > 4) return 0;
    fun = lexer_operator_methods[*machine];
    if (!fun) return 0;
    next = fun(data, c);
    *machine = next;
    return 1;
}
int lexer_whitespace(int* machine, lexer_data* data, char c) {
    lexer_callback fun;
    int next;
    if (machine == 0) return 0;
    if (*machine <= 0 || *machine > 4) return 0;
    fun = lexer_whitespace_methods[*machine];
    if (!fun) return 0;
    next = fun(data, c);
    *machine = next;
    return 1;
}
int make_lexer(void) { return 1; }




static void UnexpectedBranch(
    int value
) {
    // item 343
    printf("Unexpected branch: %d\n", value);
    /* item 344 */
    abort();
    
}

static void add_char(
    lexer_data* data,
    char c
) {
    // item 120
    string8_add(data->current, c);
    
}

static void create_identifier(
    lexer_data* data
) {
    // item 126
    create_token(data, TT_IDENTIFIER);
    
}

static void create_number(
    lexer_data* data
) {
    // item 237
    create_token(data, TT_NUMBER);
    
}

static void create_operator(
    lexer_data* data
) {
    // item 239
    create_token(data, TT_OPERATOR);
    
}

static void create_token(
    lexer_data* data,
    int type
) {
    // item 240
    string8* text; // own
    token* token; // own
    
    // item 132
    if (string8_length(data->current) == 0) {
    } else {
        /* item 135 */
        text = string8_clone(data->current);
        string8_clear(data->current);
        /* item 136 */
        token = token_create(type, text);
        obj_list_add(data->tokens, token);
    }
    
}

static void init(void) {
    // item 277
    int i;
    
    // item 266
    if (g_initialised) {
        goto exit_door;
    } else {
        /* item 265 */
        lop_chars = string8_create();
        llong_ops = obj_list_create(1);
        g_initialised = 1;
        /* item 270 */
        obj_list_add(llong_ops, string8_from_cstr("==", 2));
        obj_list_add(llong_ops, string8_from_cstr("!=", 2));
        obj_list_add(llong_ops, string8_from_cstr("<=", 2));
        obj_list_add(llong_ops, string8_from_cstr(">=", 2));
        /* item 2780001 */
        i = 0;
    }
    
    item_2780002 :
    if (i < 256) {
        /* item 280 */
        string8_add(lop_chars, 0);
        /* item 2780003 */
        i++;
        goto item_2780002;
    } else {
        /* item 269 */
        string8_set(lop_chars, '!', 1);
        string8_set(lop_chars, '=', 1);
        string8_set(lop_chars, '<', 1);
        string8_set(lop_chars, '>', 1);
        string8_set(lop_chars, '-', 1);
        string8_set(lop_chars, '+', 1);
        string8_set(lop_chars, '/', 1);
        string8_set(lop_chars, '\\', 1);
        string8_set(lop_chars, '*', 1);
        string8_set(lop_chars, '%', 1);
        string8_set(lop_chars, '(', 1);
        string8_set(lop_chars, ')', 1);
        string8_set(lop_chars, '[', 1);
        string8_set(lop_chars, ']', 1);
        string8_set(lop_chars, '{', 1);
        string8_set(lop_chars, '}', 1);
        string8_set(lop_chars, ':', 1);
        string8_set(lop_chars, '.', 1);
        string8_set(lop_chars, ';', 1);
        string8_set(lop_chars, ',', 1);
        string8_set(lop_chars, '^', 1);
        string8_set(lop_chars, '|', 1);
        string8_set(lop_chars, '&', 1);
        string8_set(lop_chars, '"', 1);
        string8_set(lop_chars, '\'', 1);
    }
    
    exit_door:;
}

static int is_digit(
    char c
) {
    // item 301
    if ((c >= '0') && (c <= '9')) {
        /* item 309 */
        return 1;
    } else {
        /* item 310 */
        return 0;
    }
    
}

static int is_letter(
    char c
) {
    // item 286
    if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) {
        /* item 294 */
        return 1;
    } else {
        /* item 295 */
        return 0;
    }
    
}

static int is_long_op(
    char first,
    char second
) {
    // item 246
    string8* long_op;
    int i;
    int count;
    /* item 249 */
    count = obj_list_length(llong_ops);
    /* item 2470001 */
    i = 0;
    
    item_2470002 :
    if (i < count) {
        /* item 250 */
        long_op = obj_list_get(llong_ops, i);
    } else {
        /* item 258 */
        return 0;
    }
    
    // item 251
    if ((string8_get(long_op, 0) == first) && (string8_get(long_op, 1) == second)) {
        /* item 257 */
        return 1;
    } else {
        /* item 2470003 */
        i++;
        goto item_2470002;
    }
    
}

static int is_operator(
    char c
) {
    // item 194
    if ((c < 0) || (c >= string8_length(lop_chars))) {
        /* item 197 */
        return 0;
    } else {
        /* item 193 */
        return string8_get(lop_chars, c);
    }
    
}

static int lexer_identifier_digit(
    lexer_data* data,
    char c
) {
    // item 60
    add_char(data, c);
    /* item 63 */
    return LEXER_IDENTIFIER;
    
}

static int lexer_identifier_letter(
    lexer_data* data,
    char c
) {
    // item 59
    add_char(data, c);
    /* item 62 */
    return LEXER_IDENTIFIER;
    
}

static int lexer_identifier_operator(
    lexer_data* data,
    char c
) {
    // item 276
    create_identifier(data);
    /* item 61 */
    add_char(data, c);
    /* item 64 */
    return LEXER_OPERATOR;
    
}

static int lexer_identifier_whitespace(
    lexer_data* data,
    char c
) {
    // item 65
    create_identifier(data);
    /* item 31 */
    return LEXER_IDLE;
    
}

static int lexer_idle_digit(
    lexer_data* data,
    char c
) {
    // item 45
    add_char(data, c);
    /* item 48 */
    return LEXER_NUMBER;
    
}

static int lexer_idle_letter(
    lexer_data* data,
    char c
) {
    // item 44
    add_char(data, c);
    /* item 47 */
    return LEXER_IDENTIFIER;
    
}

static int lexer_idle_operator(
    lexer_data* data,
    char c
) {
    // item 46
    add_char(data, c);
    /* item 49 */
    return LEXER_OPERATOR;
    
}

static int lexer_idle_whitespace(
    lexer_data* data,
    char c
) {
    // item 23
    return LEXER_IDLE;
    
}

static int lexer_number_digit(
    lexer_data* data,
    char c
) {
    // item 77
    add_char(data, c);
    /* item 80 */
    return LEXER_NUMBER;
    
}

static int lexer_number_dummy(
    lexer_data* data,
    char c
) {
    // item 81
    return LEXER_OPERATOR;
    
}

static int lexer_number_letter(
    lexer_data* data,
    char c
) {
    // item 76
    add_char(data, c);
    /* item 79 */
    return LEXER_NUMBER;
    
}

static int lexer_number_operator(
    lexer_data* data,
    char c
) {
    // item 83
    create_number(data);
    /* item 78 */
    add_char(data, c);
    /* item 81 */
    return LEXER_OPERATOR;
    
}

static int lexer_number_whitespace(
    lexer_data* data,
    char c
) {
    // item 82
    create_number(data);
    /* item 34 */
    return LEXER_IDLE;
    
}

static int lexer_operator_digit(
    lexer_data* data,
    char c
) {
    // item 101
    create_operator(data);
    /* item 94 */
    add_char(data, c);
    /* item 97 */
    return LEXER_NUMBER;
    
}

static int lexer_operator_letter(
    lexer_data* data,
    char c
) {
    // item 100
    create_operator(data);
    /* item 93 */
    add_char(data, c);
    /* item 96 */
    return LEXER_IDENTIFIER;
    
}

static int lexer_operator_operator(
    lexer_data* data,
    char c
) {
    // item 103
    if (try_make_long_op(data, c)) {
        /* item 106 */
        return LEXER_IDLE;
    } else {
        /* item 107 */
        create_operator(data);
        /* item 95 */
        add_char(data, c);
        /* item 98 */
        return LEXER_OPERATOR;
    }
    
}

static int lexer_operator_whitespace(
    lexer_data* data,
    char c
) {
    // item 99
    create_operator(data);
    /* item 26 */
    return LEXER_IDLE;
    
}

static int try_make_long_op(
    lexer_data* data,
    char c
) {
    // item 259
    char previous;
    token* token; // own
    string8* text; // own
    /* item 154 */
    previous = string8_get(data->current, 0);
    
    // item 155
    if (is_long_op(previous, c)) {
        /* item 158 */
        string8_clear(data->current);
        text = string8_create();
        string8_add(text, previous);
        string8_add(text, c);
        token = token_create(TT_OPERATOR, text);
        obj_list_add(data->tokens, token);
        /* item 159 */
        return 1;
    } else {
        /* item 160 */
        return 0;
    }
    
}

obj_list* lex(
    const string8* text
) {
    // item 311
    char c;
    int i;
    /* item 315 */
    obj_list* tokens = obj_list_create(1);
    string8* current = string8_create();
    /* item 318 */
    lexer_data data = { current, tokens };
    /* item 167 */
    int lexer = make_lexer();
    int length = string8_length(text);
    /* item 1680001 */
    i = 0;
    
    item_1680002 :
    if (i < length) {
        /* item 319 */
        c = string8_get(text, i);
    } else {
        /* item 347 */
        lexer_whitespace(&lexer, &data, ' ');
        /* item 316 */
        object_destroy(current);
        /* item 170 */
        return tokens;
    }
    
    // item 172
    if ((c == '_') || (is_letter(c))) {
        /* item 181 */
        lexer_letter(&lexer, &data, c);
        goto item_1680003;
    } else {
    }
    
    // item 178
    if (is_digit(c)) {
        /* item 312 */
        lexer_digit(&lexer, &data, c);
        goto item_1680003;
    } else {
    }
    
    // item 183
    if (is_operator(c)) {
        /* item 313 */
        lexer_operator(&lexer, &data, c);
    } else {
        /* item 314 */
        lexer_whitespace(&lexer, &data, ' ');
    }
    
    item_1680003 :
    i++;
    goto item_1680002;
    
}

int main(
    int argc,
    char** argv
) {
    // item 272
    int i, token_count;
    token* token;
    /* item 345 */
    string8* text;
    obj_list* tokens;
    /* item 346 */
    init();
    /* item 161 */
    text = string8_from_cstr(
      "foo.Bar(34 / 4-(18+m * 3)) ==800;", 100);
    
    tokens = lex(text);
    /* item 207 */
    printf("Text:\n%s\n", string8_buffer(text));
    printf("Tokens:\n");
    /* item 273 */
    token_count = obj_list_length(tokens);
    /* item 2040001 */
    i = 0;
    
    item_2040002 :
    if (i < token_count) {
        /* item 206 */
        token = obj_list_get(tokens, i);
        token_print(token);
        /* item 2040003 */
        i++;
        goto item_2040002;
    } else {
        /* item 274 */
        object_destroy(text);
        object_destroy(tokens);
        /* item 271 */
        return 0;
    }
    
}

token* token_create(
    int type,
    string8* text
) {
    // item 213
    token* self = allocate_memory(sizeof(token));
    ENSURE(self)
    
    ENSURE(text)
    
    self->base.type = &token_t;
    self->type = type;
    self->text = text;
    
    return self;
    
}

void token_destroy(
    token* self
) {
    // item 231
    if (self == 0) {
    } else {
        /* item 234 */
        ENSURE(self->base.type == &token_t)
        /* item 235 */
        string8_destroy(self->text);
        free_memory(self, sizeof(token));
    }
    
}

void token_print(
    const token* self
) {
    int _sw3260000_ = 0;
    // item 333
    const char* type;
    /* item 3260000 */
    _sw3260000_ = self->type;
    
    // item 3260001
    if (_sw3260000_ == TT_NUMBER) {
        /* item 325 */
        type = "number    ";
        goto item_337;
    } else {
    }
    
    // item 3260002
    if (_sw3260000_ == TT_IDENTIFIER) {
        /* item 334 */
        type = "identifier";
        goto item_337;
    } else {
    }
    
    // item 3260003
    if (_sw3260000_ == TT_OPERATOR) {
    } else {
        /* item 3260004 */
        UnexpectedBranch(_sw3260000_);
    }
    
    // item 335
    type = "operator  ";
    
    item_337 :
    printf(
      "%s: %s\n", 
      type,
      string8_buffer(self->text)
    );
    
}

const string8* token_text(
    const token* self
) {
    // item 230
    return self->text;
    
}

int token_type(
    const token* self
) {
    // item 224
    return self->type;
    
}



