void closure_leftmost(ldetctx_t &ctx)
{
- const closure_t &init = ctx.reach;
- closure_t &done = ctx.state;
- std::stack<clos_t> &todo = ctx.stack_dfs;
-
- // enqueue all initial states
+ closure_t &done = ctx.state, &todo = ctx.reach;
done.clear();
- for (rcclositer_t c = init.rbegin(); c != init.rend(); ++c) {
- todo.push(*c);
- }
// DFS; linear complexity
for (; !todo.empty(); ) {
- const clos_t &x = todo.top();
+ const clos_t &x = todo.back();
nfa_state_t *n = x.state;
- todo.pop();
+ todo.pop_back();
if (n->clos != NOCLOS) continue;
switch (n->type) {
case nfa_state_t::NIL:
- todo.push(clos_t(x, n->nil.out));
+ todo.push_back(clos_t(x, n->nil.out));
break;
case nfa_state_t::ALT:
- todo.push(clos_t(x, n->alt.out2));
- todo.push(clos_t(x, n->alt.out1));
+ todo.push_back(clos_t(x, n->alt.out2));
+ todo.push_back(clos_t(x, n->alt.out1));
break;
case nfa_state_t::TAG:
- todo.push(clos_t(x, n->tag.out, ctx.history.link(ctx, x)));
+ todo.push_back(clos_t(x, n->tag.out, ctx.history.link(ctx, x)));
break;
default:
break;
--- /dev/null
+#ifndef _RE2C_DFA_CLOSURE_LEFTMOST_
+#define _RE2C_DFA_CLOSURE_LEFTMOST_
+
+#include "src/dfa/determinization.h"
+#include "src/nfa/nfa.h"
+
+
+namespace re2c {
+
+template<typename ctx_t> static void closure_leftmost_dfs(ctx_t &ctx);
+
+inline void closure_leftmost(ldetctx_t &ctx)
+{
+ closure_leftmost_dfs(ctx);
+
+ // cleanup
+ for (clositer_t i = ctx.state.begin(); i != ctx.state.end(); ++i) {
+ i->state->clos = NOCLOS;
+ }
+}
+
+template<typename ctx_t>
+void closure_leftmost_dfs(ctx_t &ctx)
+{
+ typename ctx_t::confset_t &state = ctx.state, &stack = ctx.reach;
+ state.clear();
+
+ // DFS; linear complexity
+ for (; !stack.empty(); ) {
+ typedef typename ctx_t::conf_t conf_t;
+ const conf_t x = stack.back();
+ stack.pop_back();
+ nfa_state_t *n = x.state;
+
+ if (n->clos != NOCLOS) continue;
+
+ n->clos = static_cast<uint32_t>(state.size());
+ state.push_back(x);
+
+ switch (n->type) {
+ case nfa_state_t::NIL:
+ stack.push_back(conf_t(x, n->nil.out));
+ break;
+ case nfa_state_t::ALT:
+ stack.push_back(conf_t(x, n->alt.out2));
+ stack.push_back(conf_t(x, n->alt.out1));
+ break;
+ case nfa_state_t::TAG:
+ stack.push_back(conf_t(x, n->tag.out, ctx.history.link(ctx, x)));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+} // namespace re2c
+
+#endif // _RE2C_DFA_CLOSURE_LEFTMOST_
void reach_on_symbol(ctx_t &ctx, uint32_t sym)
{
ctx.dc_symbol = sym;
- const uint32_t symbol = ctx.dfa.charset[ctx.dc_symbol];
+ const uint32_t symbol = ctx.dfa.charset[sym];
const kernel_t *kernel = ctx.dc_kernels[ctx.dc_origin];
ctx.oldprectbl = kernel->prectbl;
closure_t &reach = ctx.reach;
reach.clear();
- for (uint32_t i = 0; i < kernel->size; ++i) {
+ // Add configurations in reverse order: leftmost greedy closure uses
+ // the resulting array as stack, and POSIX closure doesn't care (GOR1
+ // pre-sorts configurations, and GTOP uses priority queue).
+ for (uint32_t i = static_cast<uint32_t>(kernel->size); i --> 0; ) {
nfa_state_t *s = transition(kernel->state[i], symbol);
if (s) {
const clos_t c(s, i, kernel->tvers[i], kernel->thist[i], HROOT);
, dc_tagcount()
, reach()
, state()
- , stack_dfs()
, gor1_topsort()
, gor1_linear()
, gtop_buffer()
// tagged epsilon-closure
confset_t reach;
confset_t state;
- std::stack<clos_t> stack_dfs; // stack used for DFS in leftmost greedy closure
std::vector<nfa_state_t*> gor1_topsort; // stack used in GOR1 (POSIX closure)
std::vector<nfa_state_t*> gor1_linear; // stack used in GOR1 (POSIX closure)
std::vector<nfa_state_t*> gtop_buffer; // buffer used for heap in GTOP (POSIX closure)