diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2020-09-22 04:35:57 -0400 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2020-09-22 04:47:05 -0400 |
commit | 30788806b98ae23151c921ad34c3a6f7ab1d0d76 (patch) | |
tree | d1637c49d04d9e3d7a5cb1088759b8a5326301b7 | |
parent | 6711981a2d7e2fc3e3965156e0cb0887387f202a (diff) | |
download | flex-git-30788806b98ae23151c921ad34c3a6f7ab1d0d76.tar.gz |
gen_next_match() becomes m4 code.
To verify this patch, notice that the non-whitespace changes in the
generated C from the tests are of only three kinds:
1. Addition of comments. I elected to copy the comments from the
generator functions into their corresponding m4 macros in hopes of
making the generated code less nasty to read.
2. Lines like "if ( yy_current_state >= 12 )" changing so the numeric
literal is replaced by YY_JAMSTATE + 1. This was a consequence of the
change in #15 to simplify the C code generators so they could be
translated into static nacros.
3. "YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]" being replaced by
"YY_CHAR yy_c = *(yy_ec+YY_SC_TO_UI(*yy_cp));". The strange way of indexing yy_ec
avoids a syntactic collision with the use of [] as m4 quotes.
#20 in the retargeting patch series
-rw-r--r-- | src/cpp-flex.skl | 89 | ||||
-rw-r--r-- | src/flexdef.h | 3 | ||||
-rw-r--r-- | src/gen.c | 104 |
3 files changed, 89 insertions, 107 deletions
diff --git a/src/cpp-flex.skl b/src/cpp-flex.skl index 90f7c78..25ee2df 100644 --- a/src/cpp-flex.skl +++ b/src/cpp-flex.skl @@ -1209,6 +1209,35 @@ m4_ifdef([[M4_MODE_NO_FULLSPD]], [[ ]]) ]]) +m4_define([[M4_GEN_NEXT_COMPRESSED_STATE]], [[ + YY_CHAR yy_c = $1; + /* Save the backing-up info \before/ computing the next state + * because we always compute one more state than needed - we + * always proceed until we reach a jam state + */ + M4_GEN_BACKING_UP + + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + +m4_ifdef([[M4_MODE_USEMECS]], [[ + /* We've arranged it so that templates are never chained + * to one another. This means we can afford to make a + * very simple test to see if we need to convert to + * yy_c's meta-equivalence class without worrying + * about erroneously looking up the meta-equivalence + * class twice + */ + + /* lastdfa + 2 == YY_JAMSTATE + 1 is the beginning of the templates */ + if (yy_current_state >= YY_JAMSTATE + 1) + yy_c = yy_meta[yy_c]; +]]) + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; +]]) + m4_define([[M4_GEN_START_STATE]], [[ /* Generate the code to find the start state. */ m4_ifdef([[M4_MODE_FULLSPD]], [[ @@ -1226,6 +1255,26 @@ m4_ifdef([[M4_MODE_BOL_NEEDED]], [[yy_current_state += YY_AT_BOL();]]) ]]) ]]) +m4_define([[M4_GEN_NEXT_MATCH_FULLSPD]], [[ + { + const struct yy_trans_info *yy_trans_info; + YY_CHAR yy_c; + + for ( yy_c = $1; + (yy_trans_info = &yy_current_state[yy_c])->yy_verify == yy_c; + yy_c = $2 ) + { + yy_current_state += yy_trans_info->yy_nxt; + + M4_GEN_BACKING_UP + } + } +]]) + +%# Conditional indirection through an equivalence map +m4_ifdef([[M4_MODE_USEECS]], m4_define([[M4_EC]], [[*(yy_ec+$1)]])) +m4_ifdef([[M4_NOT_MODE_USEECS]], [[m4_define([[M4_EC]], [[$1]])]]) + %not-for-header /** The main scanner function which does all the work. */ @@ -1321,6 +1370,46 @@ m4_ifdef( [[M4_MODE_USES_REJECT]], %% [9.0] code to set up and find next match goes here + /* Generate the code to find the next match. */ +m4_ifdef([[M4_MODE_FULLTBL]], [[ +m4_ifdef([[M4_MODE_GENTABLES]], [[ + while ((yy_current_state = yy_nxt[yy_current_state][ M4_EC(YY_SC_TO_UI(*yy_cp)) ]) > 0) { +]]) +m4_ifdef([[M4_MODE_NO_GENTABLES]], [[ + while ((yy_current_state = yy_nxt[yy_current_state*YY_NXT_LOLEN + M4_EC(YY_SC_TO_UI(*yy_cp)) ]) > 0) + { +]]) +M4_GEN_BACKING_UP + yy_cp++; + } + yy_current_state = -yy_current_state; +]]) +m4_ifdef([[M4_MODE_FULLSPD]], [[ + M4_GEN_NEXT_MATCH_FULLSPD(M4_EC(YY_SC_TO_UI(*yy_cp)), M4_EC(YY_SC_TO_UI(*++yy_cp))) +]]) +m4_ifdef([[M4_MODE_NO_FULLSPD_OR_FULLTBL]], [[ + do + { + M4_GEN_NEXT_COMPRESSED_STATE(M4_EC(YY_SC_TO_UI(*yy_cp))) + + m4_ifdef([[M4_MODE_USES_REJECT]], [[*YY_G(yy_state_ptr)++ = yy_current_state;]]) + ++yy_cp; + + } + m4_ifdef([[M4_MODE_INTERACTIVE]], [[while ( yy_base[yy_current_state] != YY_JAMBASE );]]) + m4_ifdef([[M4_MODE_NO_INTERACTIVE]], [[while ( yy_current_state != YY_JAMSTATE );]]) + +m4_ifdef([[M4_MODE_NO_USES_REJECT]], [[ +m4_ifdef([[M4_MODE_NO_INTERACTIVE]], [[ + /* Do the guaranteed-needed backing up to figure out + * the match. + */ + yy_cp = YY_G(yy_last_accepting_cpos); + yy_current_state = YY_G(yy_last_accepting_state); +]]) +]]) +]]) + yy_find_action: %% [10.0] code to find the action number goes here m4_ifdef([[M4_MODE_FULLSPD]], [[yy_act = yy_current_state[-1].yy_nxt;]]) diff --git a/src/flexdef.h b/src/flexdef.h index e84de08..b1de1b6 100644 --- a/src/flexdef.h +++ b/src/flexdef.h @@ -789,9 +789,6 @@ extern void genftbl(void); /* generate full transition table */ /* Generate the code to find the next compressed-table state. */ extern void gen_next_compressed_state(char *); -/* Generate the code to find the next match. */ -extern void gen_next_match(void); - /* Generate the code to find the next state. */ extern void gen_next_state(int); @@ -541,109 +541,6 @@ void gen_next_compressed_state (char *char_map) } -/* Generate the code to find the next match. */ - -void gen_next_match (void) -{ - /* NOTE - changes in here should be reflected in gen_next_state() and - * gen_NUL_trans(). - */ - char *char_map = useecs ? - "yy_ec[YY_SC_TO_UI(*yy_cp)] " : "YY_SC_TO_UI(*yy_cp)"; - - char *char_map_2 = useecs ? - "yy_ec[YY_SC_TO_UI(*++yy_cp)] " : "YY_SC_TO_UI(*++yy_cp)"; - - if (fulltbl) { - if (gentables) - indent_put2s - ("while ( (yy_current_state = yy_nxt[yy_current_state][ %s ]) > 0 )", - char_map); - else - indent_put2s - ("while ( (yy_current_state = yy_nxt[yy_current_state*YY_NXT_LOLEN + %s ]) > 0 )", - char_map); - - ++indent_level; - - if (num_backing_up > 0) { - indent_puts ("{"); - outn ("M4_GEN_BACKING_UP"); - outc ('\n'); - } - - indent_puts ("++yy_cp;"); - - if (num_backing_up > 0) - outn ("M4_GEN_BACKING_UP"); - indent_puts ("}"); - - --indent_level; - - outc ('\n'); - indent_puts ("yy_current_state = -yy_current_state;"); - } - - else if (fullspd) { - indent_puts ("{"); - indent_puts - ("const struct yy_trans_info *yy_trans_info;\n"); - indent_puts ("YY_CHAR yy_c;\n"); - indent_put2s ("for ( yy_c = %s;", char_map); - indent_puts - (" (yy_trans_info = &yy_current_state[yy_c])->"); - indent_puts ("yy_verify == yy_c;"); - indent_put2s (" yy_c = %s )", char_map_2); - - ++indent_level; - - if (num_backing_up > 0) - indent_puts ("{"); - - indent_puts ("yy_current_state += yy_trans_info->yy_nxt;"); - - if (num_backing_up > 0) { - outc ('\n'); - outn ("M4_GEN_BACKING_UP"); - indent_puts ("}"); - } - - --indent_level; - indent_puts ("}"); - } - - else { /* compressed */ - indent_puts ("do"); - - ++indent_level; - indent_puts ("{"); - - gen_next_state (false); - - indent_puts ("++yy_cp;"); - - - indent_puts ("}"); - --indent_level; - - if (interactive) - indent_puts ("while ( yy_base[yy_current_state] != YY_JAMBASE );"); - else - indent_puts ("while ( yy_current_state != YY_JAMSTATE );"); - - if (!reject && !interactive) { - /* Do the guaranteed-needed backing up to figure out - * the match. - */ - indent_puts - ("yy_cp = YY_G(yy_last_accepting_cpos);"); - indent_puts - ("yy_current_state = YY_G(yy_last_accepting_state);"); - } - } -} - - /* Generate the code to find the next state. */ void gen_next_state (int worry_about_NULs) @@ -1677,7 +1574,6 @@ void make_tables (void) /* Note, don't use any indentation. */ outn ("yy_match:"); - gen_next_match (); skelout (); /* %% [10.0] - break point in skel */ set_indent (2); |