src
emit_action.cc
Go to the documentation of this file.
1 #include "src/util/c99_stdint.h"
2 #include <stddef.h>
3 #include <set>
4 #include <string>
5 
6 #include "src/codegen/emit.h"
8 #include "src/codegen/output.h"
9 #include "src/conf/opt.h"
10 #include "src/globals.h"
11 #include "src/ir/adfa/action.h"
12 #include "src/ir/adfa/adfa.h"
13 #include "src/ir/regexp/regexp.h"
16 #include "src/parse/code.h"
17 #include "src/parse/loc.h"
18 
19 namespace re2c
20 {
21 
22 class label_t;
23 
24 static void need (OutputFile & o, uint32_t ind, bool & readCh, size_t n, bool bSetMarker);
25 static void emit_match (OutputFile & o, uint32_t ind, bool & readCh, const State * const s);
26 static void emit_initial (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const Initial & init, const std::set<label_t> & used_labels);
27 static void emit_save (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, uint32_t save, bool save_yyaccept);
28 static void emit_accept_binary (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept, size_t l, size_t r);
29 static void emit_accept (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept);
30 static void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName, const Skeleton * skeleton);
31 static void genYYFill (OutputFile & o, size_t need);
32 static void genSetCondition (OutputFile & o, uint32_t ind, const std::string & newcond);
33 static void genSetState (OutputFile & o, uint32_t ind, uint32_t fillIndex);
34 
35 void emit_action
36  ( const Action & action
37  , OutputFile & o
38  , uint32_t ind
39  , bool & readCh
40  , const State * const s
41  , const std::string & condName
42  , const Skeleton * skeleton
43  , const std::set<label_t> & used_labels
44  , bool save_yyaccept
45  )
46 {
47  switch (action.type)
48  {
49  case Action::MATCH:
50  emit_match (o, ind, readCh, s);
51  break;
52  case Action::INITIAL:
53  emit_initial (o, ind, readCh, s, * action.info.initial, used_labels);
54  break;
55  case Action::SAVE:
56  emit_save (o, ind, readCh, s, action.info.save, save_yyaccept);
57  break;
58  case Action::MOVE:
59  break;
60  case Action::ACCEPT:
61  emit_accept (o, ind, readCh, s, * action.info.accepts);
62  break;
63  case Action::RULE:
64  emit_rule (o, ind, s, action.info.rule, condName, skeleton);
65  break;
66  }
67  if (s->isPreCtxt && opts->target != opt_t::DOT)
68  {
70  }
71 }
72 
73 void emit_match (OutputFile & o, uint32_t ind, bool & readCh, const State * const s)
74 {
75  if (opts->target == opt_t::DOT)
76  {
77  return;
78  }
79 
80  const bool read_ahead = s
81  && s->next
82  && s->next->action.type != Action::RULE;
83  if (s->fill != 0)
84  {
85  o.wstring(opts->input_api.stmt_skip (ind));
86  }
87  else if (!read_ahead)
88  {
89  /* do not read next char if match */
90  o.wstring(opts->input_api.stmt_skip (ind));
91  readCh = true;
92  }
93  else
94  {
96  readCh = false;
97  }
98 
99  if (s->fill != 0)
100  {
101  need(o, ind, readCh, s->fill, false);
102  }
103 }
104 
105 void emit_initial (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const Initial & initial, const std::set<label_t> & used_labels)
106 {
107  if (opts->target == opt_t::DOT)
108  {
109  return;
110  }
111 
112  if (used_labels.count(s->label))
113  {
114  if (s->fill != 0)
115  {
116  o.wstring(opts->input_api.stmt_skip (ind));
117  }
118  else
119  {
121  }
122  }
123 
124  if (used_labels.count(initial.label))
125  {
126  o.wstring(opts->labelPrefix).wlabel(initial.label).ws(":\n");
127  }
128 
129  if (opts->dFlag)
130  {
131  o.wind(ind).wstring(opts->yydebug).ws("(").wlabel(initial.label).ws(", *").wstring(opts->yycursor).ws(");\n");
132  }
133 
134  if (s->fill != 0)
135  {
136  need(o, ind, readCh, s->fill, initial.setMarker);
137  }
138  else
139  {
140  if (initial.setMarker)
141  {
142  o.wstring(opts->input_api.stmt_backup (ind));
143  }
144  readCh = false;
145  }
146 }
147 
148 void emit_save (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, uint32_t save, bool save_yyaccept)
149 {
150  if (opts->target == opt_t::DOT)
151  {
152  return;
153  }
154 
155  if (save_yyaccept)
156  {
157  o.wind(ind).wstring(opts->yyaccept).ws(" = ").wu32(save).ws(";\n");
158  }
159 
160  if (s->fill != 0)
161  {
163  need(o, ind, readCh, s->fill, false);
164  }
165  else
166  {
168  readCh = false;
169  }
170 }
171 
172 void emit_accept_binary (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accepts, size_t l, size_t r)
173 {
174  if (l < r)
175  {
176  const size_t m = (l + r) >> 1;
177  o.wind(ind).ws("if (").wstring(opts->yyaccept).ws(r == l+1 ? " == " : " <= ").wu64(m).ws(") {\n");
178  emit_accept_binary (o, ++ind, readCh, s, accepts, l, m);
179  o.wind(--ind).ws("} else {\n");
180  emit_accept_binary (o, ++ind, readCh, s, accepts, m + 1, r);
181  o.wind(--ind).ws("}\n");
182  }
183  else
184  {
185  genGoTo(o, ind, s, accepts[l], readCh);
186  }
187 }
188 
189 void emit_accept (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accepts)
190 {
191  const size_t accepts_size = accepts.size ();
192  if (accepts_size > 0)
193  {
194  if (opts->target != opt_t::DOT)
195  {
197  }
198 
199  if (readCh) // shouldn't be necessary, but might become at some point
200  {
201  o.wstring(opts->input_api.stmt_peek (ind));
202  readCh = false;
203  }
204 
205  if (accepts_size > 1)
206  {
207  if (opts->gFlag && accepts_size >= opts->cGotoThreshold)
208  {
209  o.wind(ind++).ws("{\n");
210  o.wind(ind++).ws("static void *").wstring(opts->yytarget).ws("[").wu64(accepts_size).ws("] = {\n");
211  for (uint32_t i = 0; i < accepts_size; ++i)
212  {
213  o.wind(ind).ws("&&").wstring(opts->labelPrefix).wlabel(accepts[i]->label).ws(",\n");
214  }
215  o.wind(--ind).ws("};\n");
216  o.wind(ind).ws("goto *").wstring(opts->yytarget).ws("[").wstring(opts->yyaccept).ws("];\n");
217  o.wind(--ind).ws("}\n");
218  }
219  else if (opts->sFlag || (accepts_size == 2 && opts->target != opt_t::DOT))
220  {
221  emit_accept_binary (o, ind, readCh, s, accepts, 0, accepts_size - 1);
222  }
223  else if (opts->target == opt_t::DOT)
224  {
225  for (uint32_t i = 0; i < accepts_size; ++i)
226  {
227  o.wlabel(s->label).ws(" -> ").wlabel(accepts[i]->label);
228  o.ws(" [label=\"yyaccept=").wu32(i).ws("\"]\n");
229  }
230  }
231  else
232  {
233  o.wind(ind).ws("switch (").wstring(opts->yyaccept).ws(") {\n");
234  for (uint32_t i = 0; i < accepts_size - 1; ++i)
235  {
236  o.wind(ind).ws("case ").wu32(i).ws(": \t");
237  genGoTo(o, 0, s, accepts[i], readCh);
238  }
239  o.wind(ind).ws("default:\t");
240  genGoTo(o, 0, s, accepts[accepts_size - 1], readCh);
241  o.wind(ind).ws("}\n");
242  }
243  }
244  else
245  {
246  // no need to write if statement here since there is only case 0.
247  genGoTo(o, ind, s, accepts[0], readCh);
248  }
249  }
250 }
251 
252 void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName, const Skeleton * skeleton)
253 {
254  if (opts->target == opt_t::DOT)
255  {
256  o.wlabel(s->label);
257  if (rule->code)
258  {
259  o.ws(" [label=\"").wstring(rule->code->loc.filename).ws(":").wu32(rule->code->loc.line).ws("\"]");
260  }
261  o.ws("\n");
262  return;
263  }
264 
265  uint32_t back = rule->ctx->fixedLength();
266  if (back != 0u && opts->target != opt_t::DOT)
267  {
269  }
270 
271  if (opts->target == opt_t::SKELETON)
272  {
273  skeleton->emit_action (o, ind, rule->rank);
274  }
275  else
276  {
277  if (!rule->newcond.empty () && condName != rule->newcond)
278  {
279  genSetCondition(o, ind, rule->newcond);
280  }
281 
282  if (rule->code)
283  {
284  if (!yySetupRule.empty ())
285  {
286  o.wind(ind).wstring(yySetupRule).ws("\n");
287  }
288  o.wline_info(rule->code->loc.line, rule->code->loc.filename.c_str ())
289  .wind(ind).wstring(rule->code->text).ws("\n")
290  .wdelay_line_info ();
291  }
292  else if (!rule->newcond.empty ())
293  {
295  }
296  }
297 }
298 
299 void need (OutputFile & o, uint32_t ind, bool & readCh, size_t n, bool bSetMarker)
300 {
301  if (opts->target == opt_t::DOT)
302  {
303  return;
304  }
305 
306  uint32_t fillIndex = last_fill_index;
307 
308  if (opts->fFlag)
309  {
310  last_fill_index++;
311  genSetState (o, ind, fillIndex);
312  }
313 
314  if (opts->fill_use && n > 0)
315  {
316  o.wind(ind);
317  if (n == 1)
318  {
319  if (opts->fill_check)
320  {
321  o.ws("if (").wstring(opts->input_api.expr_lessthan_one ()).ws(") ");
322  }
323  genYYFill(o, n);
324  }
325  else
326  {
327  if (opts->fill_check)
328  {
329  o.ws("if (").wstring(opts->input_api.expr_lessthan (n)).ws(") ");
330  }
331  genYYFill(o, n);
332  }
333  }
334 
335  if (opts->fFlag)
336  {
337  o.wstring(opts->yyfilllabel).wu32(fillIndex).ws(":\n");
338  }
339 
340  if (n > 0)
341  {
342  if (bSetMarker)
343  {
345  }
346  else
347  {
348  o.wstring(opts->input_api.stmt_peek (ind));
349  }
350  readCh = false;
351  }
352 }
353 
354 void genYYFill (OutputFile & o, size_t need)
355 {
356  o.wstring(replaceParam (opts->fill, opts->fill_arg, need));
357  if (!opts->fill_naked)
358  {
359  if (opts->fill_arg_use)
360  {
361  o.ws("(").wu64(need).ws(")");
362  }
363  o.ws(";");
364  }
365  o.ws("\n");
366 }
367 
368 void genSetCondition(OutputFile & o, uint32_t ind, const std::string& newcond)
369 {
371  if (!opts->cond_set_naked)
372  {
373  o.ws("(").wstring(opts->condEnumPrefix).wstring(newcond).ws(");");
374  }
375  o.ws("\n");
376 }
377 
378 void genSetState(OutputFile & o, uint32_t ind, uint32_t fillIndex)
379 {
380  o.wind(ind).wstring(replaceParam (opts->state_set, opts->state_set_arg, fillIndex));
381  if (!opts->state_set_naked)
382  {
383  o.ws("(").wu32(fillIndex).ws(");");
384  }
385  o.ws("\n");
386 }
387 
388 } // namespace re2c
void emit_action(const Action &action, OutputFile &o, uint32_t ind, bool &readCh, const State *const s, const std::string &condName, const Skeleton *skeleton, const std::set< label_t > &used_labels, bool save_yyaccept)
Definition: emit_action.cc:36
uint32_t line
Definition: loc.h:14
const Loc loc
Definition: code.h:18
std::string filename
Definition: loc.h:13
bool setMarker
Definition: action.h:20
const accept_t * accepts
Definition: action.h:46
std::string replaceParam(std::string str, const std::string &param, const _Ty &value)
Definition: emit.h:26
std::string condPrefix
Definition: opt.h:118
bool cond_set_naked
Definition: opt.h:118
std::string yytarget
Definition: opt.h:118
static void need(OutputFile &o, uint32_t ind, bool &readCh, size_t n, bool bSetMarker)
Definition: emit_action.cc:299
bool isPreCtxt
Definition: adfa.h:30
const std::string newcond
Definition: regexp_rule.h:25
std::string stmt_restorectx(uint32_t ind) const
Definition: input_api.cc:110
union re2c::Action::@5 info
size_t fill
Definition: adfa.h:28
InputAPI input_api
Definition: opt.h:118
bool fill_naked
Definition: opt.h:118
OutputFile & ws(const char *s)
Definition: output.cc:173
OutputFile & wu32(uint32_t n)
Definition: output.cc:155
std::string stmt_skip_backup(uint32_t ind) const
Definition: input_api.cc:132
OutputFile & wind(uint32_t ind)
Definition: output.cc:191
OutputFile & wlabel(label_t l)
Definition: output.cc:179
std::string stmt_restore(uint32_t ind) const
Definition: input_api.cc:95
const RuleOp * rule
Definition: action.h:47
static void emit_initial(OutputFile &o, uint32_t ind, bool &readCh, const State *const s, const Initial &init, const std::set< label_t > &used_labels)
Definition: emit_action.cc:105
std::string yycursor
Definition: opt.h:118
std::string expr_lessthan_one() const
Definition: input_api.cc:153
static void emit_accept_binary(OutputFile &o, uint32_t ind, bool &readCh, const State *const s, const accept_t &accept, size_t l, size_t r)
Definition: emit_action.cc:172
std::string stmt_backup_peek(uint32_t ind) const
Definition: input_api.cc:139
std::string yySetupRule
Definition: main.cc:20
label_t label
Definition: action.h:19
bool sFlag
Definition: opt.h:118
bool dFlag
Definition: opt.h:118
const Code * code
Definition: regexp_rule.h:24
std::string condEnumPrefix
Definition: opt.h:118
static void genYYFill(OutputFile &o, size_t need)
Definition: emit_action.cc:354
OutputFile & wdelay_line_info()
Definition: output.cc:202
std::string cond_set
Definition: opt.h:118
uint32_t cGotoThreshold
Definition: opt.h:118
opt_t::target_t target
Definition: opt.h:118
bool fill_use
Definition: opt.h:118
OutputFile & wu64(uint64_t n)
Definition: output.cc:161
uniq_vector_t< const State * > accept_t
Definition: action.h:28
bool gFlag
Definition: opt.h:118
std::string state_set
Definition: opt.h:118
std::string fill_arg
Definition: opt.h:118
std::string yyaccept
Definition: opt.h:118
static void emit_match(OutputFile &o, uint32_t ind, bool &readCh, const State *const s)
Definition: emit_action.cc:73
Action action
Definition: adfa.h:33
std::string stmt_skip(uint32_t ind) const
Definition: input_api.cc:50
std::string stmt_skip_peek(uint32_t ind) const
Definition: input_api.cc:125
static void genSetState(OutputFile &o, uint32_t ind, uint32_t fillIndex)
Definition: emit_action.cc:378
std::string labelPrefix
Definition: opt.h:118
virtual uint32_t fixedLength()
Definition: fixed_length.cc:12
std::string stmt_backupctx(uint32_t ind) const
Definition: input_api.cc:80
RegExp * ctx
Definition: regexp_rule.h:22
bool fFlag
Definition: opt.h:118
bool state_set_naked
Definition: opt.h:118
static void emit_accept(OutputFile &o, uint32_t ind, bool &readCh, const State *const s, const accept_t &accept)
Definition: emit_action.cc:189
std::string stmt_backup(uint32_t ind) const
Definition: input_api.cc:65
label_t label
Definition: adfa.h:25
Opt opts
Definition: opt.cc:7
std::string yydebug
Definition: opt.h:118
rule_rank_t rank
Definition: regexp_rule.h:23
std::string state_set_arg
Definition: opt.h:118
void genGoTo(OutputFile &o, uint32_t ind, const State *from, const State *to, bool &readCh)
Definition: emit_dfa.cc:37
std::string stmt_peek(uint32_t ind) const
Definition: input_api.cc:45
std::string fill
Definition: opt.h:118
uint32_t last_fill_index
Definition: main.cc:19
std::string condGotoParam
Definition: opt.h:118
std::string expr_lessthan(size_t n) const
Definition: input_api.cc:160
uint32_t save
Definition: action.h:45
std::string yyfilllabel
Definition: opt.h:118
size_t size() const
Definition: uniq_vector.h:21
static void genSetCondition(OutputFile &o, uint32_t ind, const std::string &newcond)
Definition: emit_action.cc:368
const std::string text
Definition: code.h:19
std::string condGoto
Definition: opt.h:118
bool fill_arg_use
Definition: opt.h:118
void emit_action(OutputFile &o, uint32_t ind, rule_rank_t rank) const
std::string cond_set_arg
Definition: opt.h:118
Definition: bitmap.cc:10
enum re2c::Action::type_t type
static void emit_save(OutputFile &o, uint32_t ind, bool &readCh, const State *const s, uint32_t save, bool save_yyaccept)
Definition: emit_action.cc:148
Initial * initial
Definition: action.h:44
OutputFile & wline_info(uint32_t l, const char *fn)
Definition: output.cc:127
OutputFile & wstring(const std::string &s)
Definition: output.cc:167
std::string stmt_skip_backup_peek(uint32_t ind) const
Definition: input_api.cc:146
bool fill_check
Definition: opt.h:118
static void emit_rule(OutputFile &o, uint32_t ind, const State *const s, const RuleOp *const rule, const std::string &condName, const Skeleton *skeleton)
Definition: emit_action.cc:252
State * next
Definition: adfa.h:27