@@ -930,30 +930,6 @@ static void gen_go(
930
930
}
931
931
}
932
932
933
- static CodeList* emit_accept_binary (Output& output,
934
- const Adfa& dfa,
935
- const char * var,
936
- const uniq_vector_t <AcceptTrans>& acc,
937
- size_t l,
938
- size_t r) {
939
- OutAllocator& alc = output.allocator ;
940
- Scratchbuf& o = output.scratchbuf ;
941
-
942
- CodeList* stmts = code_list (alc);
943
- if (l < r) {
944
- const size_t m = (l + r) >> 1 ;
945
- const char * cmp = output.block ().binops [r == l + 1 ? OP_CMP_EQ : OP_CMP_LE];
946
- const char * if_cond = o.cstr (var).cstr (" " ).cstr (cmp).cstr (" " ).u64 (m).flush ();
947
- CodeList* if_then = emit_accept_binary (output, dfa, var, acc, l, m);
948
- CodeList* if_else = emit_accept_binary (output, dfa, var, acc, m + 1 , r);
949
- append (stmts, code_if_then_else (alc, if_cond, if_then, if_else));
950
- } else {
951
- const CodeJump jump = {acc[l].state , acc[l].tags , false , false , false };
952
- gen_goto (output, dfa, stmts, nullptr , jump);
953
- }
954
- return stmts;
955
- }
956
-
957
933
static void emit_accept (
958
934
Output& output, CodeList* stmts, const Adfa& dfa, const uniq_vector_t <AcceptTrans>& acc) {
959
935
const opt_t * opts = output.block ().opts ;
@@ -1012,7 +988,52 @@ static void emit_accept(
1012
988
1013
989
// nested ifs
1014
990
if (opts->nested_ifs || nacc == 2 ) {
1015
- append (stmts, emit_accept_binary (output, dfa, var, acc, 0 , nacc - 1 ));
991
+ // Stack: store left/right bounds and the intermediate result for left subarray.
992
+ struct Bounds { uint32_t left, right; CodeList* code; };
993
+ std::vector<Bounds> stack;
994
+ stack.push_back ({0 , static_cast <uint32_t >(nacc) - 1 , nullptr });
995
+
996
+ // Return value.
997
+ CodeList* code = nullptr ;
998
+
999
+ // Create another invalid pointer to distinguish 1st and 2nd visit.
1000
+ CodeList* const nullptr2 = reinterpret_cast <CodeList*>(~0lu);
1001
+
1002
+ while (!stack.empty ()) {
1003
+ Bounds& x = stack.back ();
1004
+ uint32_t l = x.left ;
1005
+ uint32_t r = x.right ;
1006
+
1007
+ if (l == r) {
1008
+ // recursion terminates, generate code for transition
1009
+ code = code_list (alc);
1010
+ const CodeJump jump = {acc[l].state , acc[l].tags , false , false , false };
1011
+ gen_goto (output, dfa, code, nullptr , jump);
1012
+ stack.pop_back ();
1013
+ } else {
1014
+ DCHECK (l < r);
1015
+ const uint32_t m = (l + r) / 2 ;
1016
+
1017
+ if (x.code == nullptr ) {
1018
+ // 1st visit: recurse into the left part
1019
+ x.code = nullptr2;
1020
+ stack.push_back ({l, m, nullptr });
1021
+ } else if (x.code == nullptr2) {
1022
+ // 2nd visit: save code for the left part, recurse into the right part
1023
+ x.code = code;
1024
+ stack.push_back ({m + 1 , r, nullptr });
1025
+ } else {
1026
+ // 3rd and final visit: combine code for left and right parts
1027
+ const char * cmp = output.block ().binops [r == l + 1 ? OP_CMP_EQ : OP_CMP_LE];
1028
+ const char * cond = buf.cstr (var).cstr (" " ).cstr (cmp).cstr (" " ).u64 (m).flush ();
1029
+ CodeList* result = code_list (alc);
1030
+ append (result, code_if_then_else (alc, cond, x.code , code));
1031
+ code = result;
1032
+ stack.pop_back ();
1033
+ }
1034
+ }
1035
+ }
1036
+ append (stmts, code);
1016
1037
return ;
1017
1038
}
1018
1039
0 commit comments