4coder/meta/4ed_fsm_table_generator.cpp

989 lines
31 KiB
C++
Raw Normal View History

2016-03-24 01:05:28 +00:00
/*
* FSM table generator:
* Generate FSM tables as ".c" files from FSM functions.
*
* 23.03.2016 (dd.mm.yyyy)
*/
// TOP
2019-06-01 23:58:28 +00:00
#include "../4coder_base_types.h"
#include "../4coder_base_types.cpp"
2017-04-17 23:34:54 +00:00
#include <string.h>
2016-03-24 01:05:28 +00:00
#include <stdlib.h>
#include <stdio.h>
2016-03-24 14:01:53 +00:00
#define LEXER_TABLE_FILE "4coder_lib/4cpp_lexer_tables.c"
#include "../4coder_lib/4cpp_lexer_types.h"
#include "../4ed_mem.cpp"
2016-03-24 01:05:28 +00:00
struct Whitespace_FSM{
2016-08-30 19:30:41 +00:00
unsigned char pp_state;
unsigned char white_done;
};
2016-05-18 23:22:58 +00:00
2016-03-24 01:05:28 +00:00
Whitespace_FSM
whitespace_skip_fsm(Whitespace_FSM wfsm, char c){
if (wfsm.pp_state != LSPP_default){
if (c == '\n') wfsm.pp_state = LSPP_default;
}
if (!(c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f' || c == '\v')){
wfsm.white_done = 1;
}
return(wfsm);
}
2019-06-01 23:58:28 +00:00
#define FSM_SIG(n) Cpp_Lex_FSM n(Cpp_Lex_FSM fsm, char c, b32 get_flags)
2017-04-17 23:34:54 +00:00
typedef FSM_SIG(FSM_Function);
FSM_SIG(int_fsm){
switch (fsm.state){
2016-03-24 01:05:28 +00:00
case LSINT_default:
2017-04-17 23:34:54 +00:00
{
switch (c){
case 'u': case 'U': fsm.state = LSINT_u; break;
case 'l': fsm.state = LSINT_l; break;
case 'L': fsm.state = LSINT_L; break;
default: fsm.emit_token = true; break;
}
}break;
2016-03-24 01:05:28 +00:00
case LSINT_u:
2017-04-17 23:34:54 +00:00
{
switch (c){
case 'l': fsm.state = LSINT_ul; break;
case 'L': fsm.state = LSINT_uL; break;
default: fsm.emit_token = true; break;
}
}break;
2016-03-24 01:05:28 +00:00
case LSINT_l:
2017-04-17 23:34:54 +00:00
{
switch (c){
case 'l': fsm.state = LSINT_ll; break;
case 'U': case 'u': fsm.state = LSINT_extra; break;
default: fsm.emit_token = true; break;
}
}break;
2016-03-24 01:05:28 +00:00
case LSINT_L:
2017-04-17 23:34:54 +00:00
{
switch (c){
case 'L': fsm.state = LSINT_ll; break;
case 'U': case 'u': fsm.state = LSINT_extra; break;
default: fsm.emit_token = true; break;
}
}break;
2016-03-24 01:05:28 +00:00
case LSINT_ul:
2017-04-17 23:34:54 +00:00
{
switch (c){
case 'l': fsm.state = LSINT_extra; break;
default: fsm.emit_token = true; break;
}
}break;
2016-03-24 01:05:28 +00:00
case LSINT_uL:
2017-04-17 23:34:54 +00:00
{
switch (c){
case 'L': fsm.state = LSINT_extra; break;
default: fsm.emit_token = true; break;
}
}break;
2016-03-24 01:05:28 +00:00
case LSINT_ll:
2017-04-17 23:34:54 +00:00
{
switch (c){
case 'u': case 'U': fsm.state = LSINT_extra; break;
default: fsm.emit_token = true; break;
}
}break;
2016-03-24 01:05:28 +00:00
case LSINT_extra:
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
2016-03-24 01:05:28 +00:00
break;
}
return(fsm);
}
2017-04-17 23:34:54 +00:00
FSM_SIG(normal_str_fsm){
if (!get_flags){
switch (fsm.state){
case LSSTR_default:
case LSSTR_multiline:
{
switch (c){
case '\n': case 0: fsm.state = LSSTR_error; fsm.emit_token = true; break;
case '\\': fsm.state = LSSTR_escape; break;
case '"': fsm.emit_token = true; break;
default: break;
}
}break;
case LSSTR_escape:
{
switch (c){
case '\n': fsm.state = LSSTR_multiline; break;
default: fsm.state = LSSTR_default; break;
}
}break;
}
}
else{
switch (fsm.state){
case LSSTR_multiline:
{
fsm.flags = 1;
}break;
}
}
return(fsm);
}
FSM_SIG(normal_char_fsm){
if (!get_flags){
switch (fsm.state){
case LSSTR_default:
case LSSTR_multiline:
{
switch (c){
case '\n': case 0: fsm.state = LSSTR_error; fsm.emit_token = true; break;
case '\\': fsm.state = LSSTR_escape; break;
case '\'': fsm.emit_token = true; break;
default: break;
}
}break;
case LSSTR_escape:
{
switch (c){
case '\n': fsm.state = LSSTR_multiline; break;
default: fsm.state = LSSTR_default; break;
}
}break;
}
}
else{
switch (fsm.state){
case LSSTR_multiline:
{
fsm.flags = 1;
}break;
}
}
return(fsm);
}
FSM_SIG(raw_str_fsm){
if (!get_flags){
switch (fsm.state){
case LSSTR_default:
{
switch (c){
2017-05-02 15:51:35 +00:00
case 0: case ')': case '\\': case ' ': case '\n': fsm.emit_token = true; break;
2017-04-17 23:34:54 +00:00
case '(': fsm.state = LSSTR_get_delim; fsm.emit_token = true; break;
default: break;
}
}break;
case LSSTR_get_delim:
case LSSTR_multiline:
{
switch (c){
case '\n': fsm.state = LSSTR_multiline; break;
case 0: case '"': fsm.state = LSSTR_check_delim; fsm.emit_token = true; break;
default: break;
}
}break;
}
}
else{
switch (fsm.state){
case LSSTR_multiline:
{
fsm.flags = 1;
}break;
}
}
return(fsm);
}
FSM_SIG(include_str_fsm){
switch (fsm.state){
case LSSTR_default:
{
switch (c){
case '\n': case 0: fsm.state = LSSTR_error; fsm.emit_token = true; break;
case '>': fsm.emit_token = true; break;
default: break;
}
}break;
}
return(fsm);
}
2019-06-01 23:58:28 +00:00
b32
is_identifier_char(u8 c, b32 ignore_string_delims){
b32 result = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c >= 128 || (ignore_string_delims && (c == '\'' || c == '"'));
2017-04-17 23:34:54 +00:00
return(result);
}
2019-06-01 23:58:28 +00:00
b32
is_identifier_char_restricted(u8 c, b32 ignore_string_delims){
b32 result = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c >= 128 || (ignore_string_delims && (c == '\'' || c == '"'));
2017-04-17 23:34:54 +00:00
return(result);
}
2019-06-01 23:58:28 +00:00
b32
is_identifier_char_non_numeric(u8 c, b32 ignore_string_delims){
b32 result = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c >= 128 || (ignore_string_delims && (c == '\'' || c == '"'));
2017-04-17 23:34:54 +00:00
return(result);
}
Cpp_Lex_FSM
2019-06-01 23:58:28 +00:00
main_fsm(Cpp_Lex_FSM fsm, uint8_t pp_state, uint8_t c, b32 ignore_string_delims){
2016-08-30 19:30:41 +00:00
if (c == 0){
2017-05-02 15:51:35 +00:00
switch (fsm.state){
case LS_string_R:
case LS_string_LUu8:
2017-05-02 21:35:48 +00:00
case LS_string_u:
2017-05-02 15:51:35 +00:00
{
fsm.state = LS_identifier;
}break;
}
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
2016-08-30 19:30:41 +00:00
}
else{
2016-03-24 01:05:28 +00:00
switch (pp_state){
2016-08-30 19:30:41 +00:00
case LSPP_error:
2017-04-17 23:34:54 +00:00
{
fsm.state = LS_error_message;
if (c == '\n'){
fsm.emit_token = true;
}
}break;
2016-08-30 19:30:41 +00:00
default:
switch (fsm.state){
case LS_default:
2017-11-27 21:13:17 +00:00
if (!ignore_string_delims && c == 'R'){
2017-04-17 23:34:54 +00:00
fsm.state = LS_string_R;
}
2017-11-27 21:13:17 +00:00
else if (!ignore_string_delims && (c == 'U' || c == 'L')){
2017-04-17 23:34:54 +00:00
fsm.state = LS_string_LUu8;
}
2017-11-27 21:13:17 +00:00
else if (!ignore_string_delims && c == 'u'){
2017-04-17 23:34:54 +00:00
fsm.state = LS_string_u;
}
else if (is_identifier_char_non_numeric(c, ignore_string_delims)){
2016-08-30 19:30:41 +00:00
fsm.state = LS_identifier;
}
else if (c >= '1' && c <= '9'){
fsm.state = LS_number;
}
else if (c == '0'){
fsm.state = LS_number0;
}
2016-08-30 21:23:34 +00:00
else{
switch (c){
2017-04-15 21:47:23 +00:00
case '\'':
{
if (ignore_string_delims){
fsm.state = LS_identifier;
}
else{
fsm.state = LS_char;
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
2017-04-15 21:47:23 +00:00
}
}break;
case '"':
{
if (ignore_string_delims){
fsm.state = LS_identifier;
}
else{
2017-04-17 23:34:54 +00:00
fsm.state = LS_string_normal;
fsm.emit_token = true;
2017-04-15 21:47:23 +00:00
}
}break;
2016-08-30 21:23:34 +00:00
case '/': fsm.state = LS_comment_pre; break;
case '.': fsm.state = LS_dot; break;
case '<':
2017-04-15 21:47:23 +00:00
if (pp_state == LSPP_include && !ignore_string_delims){
2017-04-17 23:34:54 +00:00
fsm.state = LS_string_include;
fsm.emit_token = true;
2016-08-30 21:23:34 +00:00
}
else{
fsm.state = LS_less;
}
break;
case '>': fsm.state = LS_more; break;
case '-': fsm.state = LS_minus; break;
case '&': fsm.state = LS_and; break;
case '|': fsm.state = LS_or; break;
case '+': fsm.state = LS_plus; break;
case ':': fsm.state = LS_colon; break;
2017-04-17 23:34:54 +00:00
case '*': case '%': case '^': case '=':
case '!': fsm.state = LS_single_op; break;
2016-08-30 21:23:34 +00:00
case '#':
if (pp_state == LSPP_default){
fsm.state = LS_pp;
}
else{
fsm.state = LS_pound;
}
break;
2017-04-17 23:34:54 +00:00
#define OperCase(op,type) case op: fsm.emit_token = true; break;
2016-08-30 21:23:34 +00:00
OperCase('{', CPP_TOKEN_BRACE_OPEN);
OperCase('}', CPP_TOKEN_BRACE_CLOSE);
OperCase('[', CPP_TOKEN_BRACKET_OPEN);
OperCase(']', CPP_TOKEN_BRACKET_CLOSE);
OperCase('(', CPP_TOKEN_PARENTHESE_OPEN);
OperCase(')', CPP_TOKEN_PARENTHESE_CLOSE);
OperCase('~', CPP_TOKEN_TILDE);
OperCase(',', CPP_TOKEN_COMMA);
OperCase(';', CPP_TOKEN_SEMICOLON);
OperCase('?', CPP_TOKEN_TERNARY_QMARK);
OperCase('@', CPP_TOKEN_JUNK);
OperCase('\\', CPP_TOKEN_JUNK);
2016-08-30 19:30:41 +00:00
#undef OperCase
2016-08-30 21:23:34 +00:00
}
2016-08-30 19:30:41 +00:00
}
break;
2016-08-30 19:30:41 +00:00
case LS_identifier:
{
2019-06-01 23:58:28 +00:00
b32 is_ident = is_identifier_char(c, ignore_string_delims);
if (!is_ident){
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
}
2016-08-30 19:30:41 +00:00
}
break;
2016-08-30 19:30:41 +00:00
case LS_pound:
{
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
}break;
2016-08-30 19:30:41 +00:00
case LS_pp:
{
if (c == ' ' || c == '\r' || c == '\v' || c == '\f'){
// NOTE(allen): do nothing
}
2017-04-17 23:34:54 +00:00
else if (is_identifier_char_restricted(c, ignore_string_delims)){
fsm.state = LS_ppdef;
}
else{
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_ppdef:
{
2017-04-17 23:34:54 +00:00
int is_ident = is_identifier_char_restricted(c, ignore_string_delims);
if (!is_ident){
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
2017-04-15 21:47:23 +00:00
}
}break;
2017-04-17 23:34:54 +00:00
case LS_string_R:
2017-04-15 21:47:23 +00:00
{
if (ignore_string_delims){
2017-04-17 23:34:54 +00:00
fsm.state = LS_count;
fsm.emit_token = true;
2017-04-15 21:47:23 +00:00
}
else{
switch (c){
2017-04-17 23:34:54 +00:00
case '"': fsm.state = LS_string_raw; fsm.emit_token = true; break;
default:
{
fsm.state = LS_identifier;
2019-06-01 23:58:28 +00:00
b32 is_ident = is_identifier_char(c, ignore_string_delims);
2017-04-17 23:34:54 +00:00
if (!is_ident){
fsm.emit_token = true;
}
}break;
2017-04-15 21:47:23 +00:00
}
}
}break;
2017-04-17 23:34:54 +00:00
case LS_string_LUu8:
2017-04-15 21:47:23 +00:00
{
if (ignore_string_delims){
2017-04-17 23:34:54 +00:00
fsm.state = LS_count;
fsm.emit_token = true;
2016-08-30 21:23:34 +00:00
}
2017-04-15 21:47:23 +00:00
else{
2017-04-17 23:34:54 +00:00
switch (c){
case '"': fsm.state = LS_string_normal; fsm.emit_token = true; break;
case '\'': fsm.state = LS_char; fsm.emit_token = true; break;
case 'R': fsm.state = LS_string_R; break;
default:
{
fsm.state = LS_identifier;
2019-06-01 23:58:28 +00:00
b32 is_ident = is_identifier_char(c, ignore_string_delims);
2017-04-17 23:34:54 +00:00
if (!is_ident){
fsm.emit_token = true;
}
}break;
2017-04-15 21:47:23 +00:00
}
}
}break;
2017-04-17 23:34:54 +00:00
case LS_string_u:
2017-04-15 21:47:23 +00:00
{
if (ignore_string_delims){
2017-04-17 23:34:54 +00:00
fsm.state = LS_count;
fsm.emit_token = true;
2017-04-15 21:47:23 +00:00
}
else{
switch (c){
2017-04-17 23:34:54 +00:00
case '"': fsm.state = LS_string_normal; fsm.emit_token = true; break;
case '\'': fsm.state = LS_char; fsm.emit_token = true; break;
case '8': fsm.state = LS_string_LUu8; break;
case 'R': fsm.state = LS_string_R; break;
default:
{
fsm.state = LS_identifier;
2019-06-01 23:58:28 +00:00
b32 is_ident = is_identifier_char(c, ignore_string_delims);
2017-04-17 23:34:54 +00:00
if (!is_ident){
fsm.emit_token = true;
}
}break;
2017-04-15 21:47:23 +00:00
}
}
}break;
2016-08-30 19:30:41 +00:00
case LS_number:
if (c >= '0' && c <= '9'){
fsm.state = LS_number;
}
else{
switch (c){
case '.': fsm.state = LS_float; break;
2017-04-17 23:34:54 +00:00
default: fsm.emit_token = true; break;
2016-08-30 19:30:41 +00:00
}
}
break;
2016-08-30 19:30:41 +00:00
case LS_number0:
if (c >= '0' && c <= '9'){
fsm.state = LS_number;
}
else if (c == 'x'){
fsm.state = LS_hex;
}
else if (c == '.'){
fsm.state = LS_float;
}
else{
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
2016-08-30 19:30:41 +00:00
}
break;
2016-08-30 19:30:41 +00:00
case LS_float:
if (!(c >= '0' && c <= '9')){
switch (c){
case 'e': fsm.state = LS_crazy_float0; break;
2017-04-17 23:34:54 +00:00
default: fsm.emit_token = true; break;
2016-08-30 19:30:41 +00:00
}
}
break;
case LS_crazy_float0:
{
if (('0' <= c && c <= '9') || c == '-' || c == '+'){
2016-08-30 19:30:41 +00:00
fsm.state = LS_crazy_float1;
}
else{
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
2016-08-30 19:30:41 +00:00
}
}
break;
case LS_crazy_float1:
{
if (!(c >= '0' && c <= '9')){
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
2016-08-30 19:30:41 +00:00
}
}
break;
case LS_hex:
{
int is_hex = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c >= 128;
if (!is_hex){
2017-04-17 23:34:54 +00:00
fsm.emit_token = true;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_dot:
{
if (c >= '0' && c <= '9'){
fsm.state = LS_float;
}
else{
switch (c){
case '.': fsm.state = LS_ellipsis; break;
2017-04-17 23:34:54 +00:00
case '*': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}
}break;
2017-04-17 23:34:54 +00:00
case LS_ellipsis: fsm.emit_token = true; break;
2016-08-30 19:30:41 +00:00
case LS_less:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '<': fsm.state = LS_single_op; break;
2017-04-17 23:34:54 +00:00
case '=': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}break;
case LS_more:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '>': fsm.state = LS_single_op; break;
2017-04-17 23:34:54 +00:00
case '=': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_comment_pre:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '/': fsm.state = LS_comment; break;
case '*': fsm.state = LS_comment_block; break;
case '=': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_comment:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '\\': fsm.state = LS_comment_slashed; break;
case '\n': fsm.emit_token = true; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_comment_slashed:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '\r': case '\f': case '\v': break;
default: fsm.state = LS_comment; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_comment_block:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '*': fsm.state = LS_comment_block_ending; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_comment_block_ending:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '*': fsm.state = LS_comment_block_ending; break;
case '/': fsm.emit_token = true; break;
default: fsm.state = LS_comment_block; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_minus:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '>': fsm.state = LS_arrow; break;
case '-': fsm.emit_token = true; break;
case '=': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_arrow:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '*': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_and:
switch (c){
2017-04-17 23:34:54 +00:00
case '&': fsm.emit_token = true; break;
case '=': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
2016-08-30 19:30:41 +00:00
}
break;
case LS_or:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '|': fsm.emit_token = true; break;
case '=': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_plus:
2017-04-17 23:34:54 +00:00
{
switch (c){
case '+': fsm.emit_token = true; break;
case '=': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}break;
2016-08-30 19:30:41 +00:00
case LS_colon:
2017-04-17 23:34:54 +00:00
{
switch (c){
case ':': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}break;
2016-08-30 19:30:41 +00:00
2017-04-17 23:34:54 +00:00
case LS_single_op:
{
switch (c){
case '=': fsm.emit_token = true; break;
default: fsm.emit_token = true; break;
}
}break;
2016-03-24 01:05:28 +00:00
}
break;
}
}
return(fsm);
}
2016-08-29 01:03:26 +00:00
static void
2016-03-24 14:01:53 +00:00
begin_table(FILE *file, char *type, char *group_name, char *table_name){
2016-08-29 01:03:26 +00:00
fprintf(file, "%s %s_%s[] = {\n", type, group_name, table_name);
2016-03-24 14:01:53 +00:00
}
2016-08-29 01:03:26 +00:00
static void
2016-03-24 01:05:28 +00:00
begin_table(FILE *file, char *type, char *table_name){
2016-08-29 01:03:26 +00:00
fprintf(file, "%s %s[] = {\n", type, table_name);
2016-03-24 01:05:28 +00:00
}
2016-08-29 01:03:26 +00:00
static void
2016-03-24 14:01:53 +00:00
begin_ptr_table(FILE *file, char *type, char *table_name){
2016-08-29 01:03:26 +00:00
fprintf(file, "%s * %s[] = {\n", type, table_name);
2016-03-24 14:01:53 +00:00
}
2016-08-29 01:03:26 +00:00
static void
do_table_item(FILE *file, uint16_t item){
2017-04-17 23:34:54 +00:00
fprintf(file, "%3d,", (int32_t)item);
}
static void
do_table_item_binary(FILE *file, uint16_t item){
if (item == 0){
fprintf(file, "0x00,");
}
else{
fprintf(file, "%#04x,", item);
}
2016-03-24 14:01:53 +00:00
}
2016-08-29 01:03:26 +00:00
static void
2016-03-24 14:01:53 +00:00
do_table_item_direct(FILE *file, char *item, char *tail){
fprintf(file, "%s%s,", item, tail);
2016-03-24 01:05:28 +00:00
}
2016-08-29 01:03:26 +00:00
static void
2016-03-24 01:05:28 +00:00
end_row(FILE *file){
fprintf(file, "\n");
}
2016-08-29 01:03:26 +00:00
static void
2016-03-24 01:05:28 +00:00
end_table(FILE *file){
fprintf(file, "};\n\n");
}
struct FSM_Tables{
2019-06-01 23:58:28 +00:00
u8 *full_transition_table;
u8 *marks;
u8 *eq_class;
u8 *eq_class_rep;
u8 *reduced_transition_table;
u8 *flags;
2016-08-29 01:03:26 +00:00
2019-06-01 23:58:28 +00:00
u8 eq_class_counter;
u16 state_count;
};
2016-08-29 01:03:26 +00:00
static void
allocate_full_tables(FSM_Tables *table, uint8_t state_count){
table->full_transition_table = (uint8_t*)malloc(state_count * 256);
table->marks = (uint8_t*)malloc(state_count * 256);
table->eq_class = (uint8_t*)malloc(state_count * 256);
table->eq_class_rep = (uint8_t*)malloc(state_count * 256);
2016-03-31 04:05:47 +00:00
table->state_count = state_count;
2016-08-30 21:23:34 +00:00
block_zero(table->marks, 256);
2016-03-31 04:05:47 +00:00
}
2016-08-29 01:03:26 +00:00
static void
do_table_reduction(FSM_Tables *table, uint16_t state_count){
2016-03-26 08:06:41 +00:00
{
table->eq_class_counter = 0;
2016-08-29 01:03:26 +00:00
uint8_t *c_line = table->full_transition_table;
for (uint16_t c = 0; c < 256; ++c){
2016-03-26 08:06:41 +00:00
if (table->marks[c] == 0){
table->eq_class[c] = table->eq_class_counter;
2016-08-29 01:03:26 +00:00
table->eq_class_rep[table->eq_class_counter] = (uint8_t)c;
uint8_t *c2_line = c_line + state_count;
for (uint16_t c2 = c + 1; c2 < 256; ++c2){
2016-08-30 21:23:34 +00:00
if (block_compare(c_line, c2_line, state_count) == 0){
2016-03-26 08:06:41 +00:00
table->marks[c2] = 1;
table->eq_class[c2] = table->eq_class_counter;
}
c2_line += state_count;
}
++table->eq_class_counter;
}
c_line += state_count;
}
}
2016-08-29 01:03:26 +00:00
table->reduced_transition_table = (uint8_t*)malloc(state_count * table->eq_class_counter);
2016-03-26 08:06:41 +00:00
{
2016-08-29 01:03:26 +00:00
uint8_t *r_line = table->reduced_transition_table;
for (uint16_t eq = 0; eq < table->eq_class_counter; ++eq){
uint8_t *u_line = table->full_transition_table + state_count * table->eq_class_rep[eq];
2016-08-30 21:23:34 +00:00
block_copy(r_line, u_line, state_count);
2016-03-26 08:06:41 +00:00
r_line += state_count;
}
}
}
2016-08-29 01:03:26 +00:00
static FSM_Tables
2016-03-24 14:01:53 +00:00
generate_whitespace_skip_table(){
2016-08-29 01:03:26 +00:00
uint8_t state_count = LSPP_count;
FSM_Tables table = {};
2016-03-31 04:05:47 +00:00
allocate_full_tables(&table, state_count);
2016-08-29 01:03:26 +00:00
int32_t i = 0;
Whitespace_FSM wfsm = {};
2016-03-24 14:01:53 +00:00
Whitespace_FSM new_wfsm;
2016-08-29 01:03:26 +00:00
for (uint16_t c = 0; c < 256; ++c){
for (uint8_t state = 0; state < state_count; ++state){
2016-03-24 14:01:53 +00:00
wfsm.pp_state = state;
wfsm.white_done = 0;
2016-08-29 01:03:26 +00:00
new_wfsm = whitespace_skip_fsm(wfsm, (uint8_t)c);
2016-03-24 14:01:53 +00:00
table.full_transition_table[i++] = new_wfsm.pp_state + state_count*new_wfsm.white_done;
}
}
2016-08-29 01:03:26 +00:00
2016-03-26 08:06:41 +00:00
do_table_reduction(&table, state_count);
2016-08-29 01:03:26 +00:00
2016-03-26 08:06:41 +00:00
return(table);
}
2016-08-29 01:03:26 +00:00
static FSM_Tables
2019-06-01 23:58:28 +00:00
generate_table(u8 state_count, FSM_Function *fsm_call){
FSM_Tables table = {};
2016-03-31 04:05:47 +00:00
allocate_full_tables(&table, state_count);
2016-08-29 01:03:26 +00:00
2019-06-01 23:58:28 +00:00
i32 i = 0;
Cpp_Lex_FSM fsm = {};
Cpp_Lex_FSM new_fsm = {};
2016-08-29 01:03:26 +00:00
for (uint16_t c = 0; c < 256; ++c){
2019-06-01 23:58:28 +00:00
for (u8 state = 0; state < state_count; ++state){
2017-04-17 23:34:54 +00:00
fsm.state = state;
fsm.emit_token = false;
2019-06-01 23:58:28 +00:00
new_fsm = fsm_call(fsm, (u8)c, false);
2017-04-17 23:34:54 +00:00
table.full_transition_table[i++] = new_fsm.state + state_count*new_fsm.emit_token;
}
}
2019-06-01 23:58:28 +00:00
for (u8 state = 0; state < state_count; ++state){
2017-04-17 23:34:54 +00:00
fsm.state = state;
fsm.emit_token = false;
fsm.flags = 0;
new_fsm = fsm_call(fsm, 0, true);
if (new_fsm.flags != 0){
if (table.flags == 0){
2019-06-01 23:58:28 +00:00
table.flags = (u8*)malloc(state_count);
2017-04-17 23:34:54 +00:00
memset(table.flags, 0, state_count);
}
table.flags[state] = new_fsm.flags;
2016-03-24 14:01:53 +00:00
}
}
2016-08-29 01:03:26 +00:00
2016-03-26 08:06:41 +00:00
do_table_reduction(&table, state_count);
2016-08-29 01:03:26 +00:00
2016-03-24 14:01:53 +00:00
return(table);
}
2016-08-29 01:03:26 +00:00
static FSM_Tables
2019-06-01 23:58:28 +00:00
generate_fsm_table(uint8_t pp_state, b32 ignore_string_delims){
2016-08-29 01:03:26 +00:00
uint8_t state_count = LS_count;
FSM_Tables table = {};
2016-03-31 04:05:47 +00:00
allocate_full_tables(&table, state_count);
2016-08-29 01:03:26 +00:00
int32_t i = 0;
Cpp_Lex_FSM fsm = {};
Cpp_Lex_FSM new_fsm = {};
2016-08-29 01:03:26 +00:00
for (uint16_t c = 0; c < 256; ++c){
for (uint8_t state = 0; state < state_count; ++state){
2016-03-24 01:05:28 +00:00
fsm.state = state;
2017-04-17 23:34:54 +00:00
fsm.emit_token = false;
2017-04-15 21:47:23 +00:00
new_fsm = main_fsm(fsm, pp_state, (uint8_t)c, ignore_string_delims);
2016-03-24 14:01:53 +00:00
table.full_transition_table[i++] = new_fsm.state + state_count*new_fsm.emit_token;
2016-03-24 01:05:28 +00:00
}
}
2016-08-29 01:03:26 +00:00
2016-03-26 08:06:41 +00:00
do_table_reduction(&table, state_count);
2016-08-29 01:03:26 +00:00
2016-03-24 14:01:53 +00:00
return(table);
}
2016-03-24 01:05:28 +00:00
2016-08-29 01:03:26 +00:00
static void
2016-03-24 14:01:53 +00:00
render_fsm_table(FILE *file, FSM_Tables tables, char *group_name){
2019-06-01 23:58:28 +00:00
begin_table(file, "u16", group_name, "eq_classes");
for (u16 c = 0; c < 256; ++c){
2017-04-17 23:34:54 +00:00
if ((c % 16) == 0 && c > 0){
end_row(file);
}
2016-03-24 14:01:53 +00:00
do_table_item(file, tables.eq_class[c]*tables.state_count);
2016-03-24 01:05:28 +00:00
}
end_row(file);
end_table(file);
2016-08-29 01:03:26 +00:00
2019-06-01 23:58:28 +00:00
fprintf(file, "const i32 num_%s_eq_classes = %d;\n\n", group_name, tables.eq_class_counter);
2016-08-29 01:03:26 +00:00
2019-06-01 23:58:28 +00:00
i32 i = 0;
begin_table(file, "u8", group_name, "table");
for (u16 c = 0; c < tables.eq_class_counter; ++c){
for (u8 state = 0; state < tables.state_count; ++state){
2016-03-24 14:01:53 +00:00
do_table_item(file, tables.reduced_transition_table[i++]);
}
end_row(file);
}
end_table(file);
2017-04-17 23:34:54 +00:00
if (tables.flags != 0){
2019-06-01 23:58:28 +00:00
begin_table(file, "u8", group_name, "flags");
for (u8 state = 0; state < tables.state_count; ++state){
2017-04-17 23:34:54 +00:00
if ((state % 4) == 0 && state > 0){
end_row(file);
}
do_table_item_binary(file, tables.flags[state]);
}
end_row(file);
end_table(file);
}
2016-03-24 14:01:53 +00:00
}
2016-08-29 01:03:26 +00:00
static void
render_variable(FILE *file, char *type, char *variable, uint32_t x){
2016-03-31 04:05:47 +00:00
fprintf(file, "%s %s = %d;\n\n", type, variable, x);
}
2016-08-29 01:03:26 +00:00
static void
render_comment(FILE *file, char *comment){
fprintf(file, "/*\n%s*/\n", comment);
}
struct PP_Names{
2016-08-29 01:03:26 +00:00
uint8_t pp_state;
2016-03-24 14:01:53 +00:00
char *name;
2019-06-01 23:58:28 +00:00
b32 ignore_string_delims;
};
2016-03-24 14:01:53 +00:00
2016-08-29 01:03:26 +00:00
static PP_Names pp_names[] = {
2017-04-15 21:47:23 +00:00
{LSPP_default, "main_fsm", false},
{LSPP_include, "pp_include_fsm", false},
{LSPP_macro_identifier, "pp_macro_fsm", false},
{LSPP_identifier, "pp_identifier_fsm", false},
{LSPP_body_if, "pp_body_if_fsm", false},
{LSPP_body, "pp_body_fsm", false},
{LSPP_number, "pp_number_fsm", false},
{LSPP_error, "pp_error_fsm", false},
{LSPP_junk, "pp_junk_fsm", false},
2017-04-17 23:34:54 +00:00
{LSPP_default, "no_string_fsm", true },
2016-03-24 14:01:53 +00:00
};
2016-03-31 04:05:47 +00:00
int
main(){
2017-04-15 21:47:23 +00:00
FILE *file = fopen(LEXER_TABLE_FILE, "wb");
2016-03-24 01:05:28 +00:00
2016-03-24 14:01:53 +00:00
FSM_Tables wtables = generate_whitespace_skip_table();
render_fsm_table(file, wtables, "whitespace_fsm");
2016-03-24 01:05:28 +00:00
2017-04-17 23:34:54 +00:00
FSM_Tables itables = generate_table(LSINT_count, int_fsm);
2016-03-26 08:06:41 +00:00
render_fsm_table(file, itables, "int_fsm");
2017-04-17 23:34:54 +00:00
{
struct{
char *name;
uint8_t count;
FSM_Function *fsm_call;
} static tables[] = {
{"raw_str", LSSTR_count, raw_str_fsm },
{"normal_str", LSSTR_count, normal_str_fsm },
{"include_str", LSSTR_include_count, include_str_fsm },
{"normal_char", LSSTR_count, normal_char_fsm }
};
2019-06-01 23:58:28 +00:00
for (u32 i = 0; i < ArrayCount(tables); ++i){
2017-04-17 23:34:54 +00:00
FSM_Tables str_tables = generate_table(tables[i].count, tables[i].fsm_call);
render_fsm_table(file, str_tables, tables[i].name);
}
2016-03-24 14:01:53 +00:00
}
2016-08-29 01:03:26 +00:00
for (int32_t i = 0; i < ArrayCount(pp_names); ++i){
2017-04-15 21:47:23 +00:00
FSM_Tables tables = generate_fsm_table(pp_names[i].pp_state, pp_names[i].ignore_string_delims);
2016-03-24 14:01:53 +00:00
render_fsm_table(file, tables, pp_names[i].name);
}
2016-08-29 01:03:26 +00:00
begin_ptr_table(file, "uint16_t", "get_eq_classes");
for (int32_t i = 0; i < ArrayCount(pp_names); ++i){
2016-03-24 14:01:53 +00:00
do_table_item_direct(file, pp_names[i].name, "_eq_classes");
2016-03-24 01:05:28 +00:00
end_row(file);
2016-03-24 14:01:53 +00:00
}
2016-03-24 01:05:28 +00:00
end_table(file);
2016-08-29 01:03:26 +00:00
begin_ptr_table(file, "uint8_t", "get_table");
for (int32_t i = 0; i < ArrayCount(pp_names); ++i){
2016-03-24 14:01:53 +00:00
do_table_item_direct(file, pp_names[i].name, "_table");
2016-03-24 01:05:28 +00:00
end_row(file);
}
end_table(file);
fclose(file);
return(0);
}
// BOTTOM