1 /* $Id: code.cc 861 2008-05-25 13:23:02Z helly $ */
19 // there must be at least one span in list; all spans must cover
22 static std::string
indent(uint ind
)
26 while (!DFlag
&& ind
-- > 0)
33 template<typename _Ty
>
34 std::string
replaceParam(std::string str
, const std::string
& param
, const _Ty
& value
)
36 std::ostringstream strValue
;
40 std::string::size_type pos
;
42 while((pos
= str
.find(param
)) != std::string::npos
)
44 str
.replace(pos
, param
.length(), strValue
.str());
50 static void genYYFill(std::ostream
&o
, uint
, uint need
)
54 o
<< mapCodeName
["YYFILL"];
57 o
<< "(" << need
<< ");";
63 o
<< replaceParam(mapCodeName
["YYFILL"], yyFillLength
, need
);
72 static std::string
genGetState()
74 if (bUseYYGetStateNaked
)
76 return mapCodeName
["YYGETSTATE"];
80 return mapCodeName
["YYGETSTATE"] + "()";
84 static std::string
genGetCondition()
86 if (bUseYYGetConditionNaked
)
88 return mapCodeName
["YYGETCONDITION"];
92 return mapCodeName
["YYGETCONDITION"] + "()";
96 static void genSetCondition(std::ostream
& o
, uint ind
, const std::string
& newcond
)
98 if (bUseYYSetConditionParam
)
100 o
<< indent(ind
) << mapCodeName
["YYSETCONDITION"] << "(" << condEnumPrefix
<< newcond
<< ");\n";
104 o
<< indent(ind
) << replaceParam(mapCodeName
["YYSETCONDITION"], yySetConditionParam
, condEnumPrefix
+ newcond
) << "\n";
108 static std::string
space(uint this_label
)
110 int nl
= next_label
> 999999 ? 6 : next_label
> 99999 ? 5 : next_label
> 9999 ? 4 : next_label
> 999 ? 3 : next_label
> 99 ? 2 : next_label
> 9 ? 1 : 0;
111 int tl
= this_label
> 999999 ? 6 : this_label
> 99999 ? 5 : this_label
> 9999 ? 4 : this_label
> 999 ? 3 : this_label
> 99 ? 2 : this_label
> 9 ? 1 : 0;
113 return std::string(std::max(1, nl
- tl
+ 1), ' ');
118 // arrange so that adjacent spans have different targets
121 for (uint j
= 1; j
< nSpans
; ++j
)
123 if (span
[j
].to
!= span
[i
].to
)
126 span
[i
].to
= span
[j
].to
;
129 span
[i
].ub
= span
[j
].ub
;
135 void Go::unmap(Go
*base
, const State
*x
)
137 Span
*s
= span
, *b
= base
->span
, *e
= &b
[base
->nSpans
];
146 if ((s
->ub
- lb
) > 1)
173 void doGen(const Go
*g
, const State
*s
, uint
*bm
, uint f
, uint m
)
175 Span
*b
= g
->span
, *e
= &b
[g
->nSpans
];
182 for (; lb
< b
->ub
&& lb
< 256; ++lb
)
192 void prt(std::ostream
& o
, const Go
*g
, const State
*s
)
194 Span
*b
= g
->span
, *e
= &b
[g
->nSpans
];
201 printSpan(o
, lb
, b
->ub
);
208 bool matches(const Go
*g1
, const State
*s1
, const Go
*g2
, const State
*s2
)
210 Span
*b1
= g1
->span
, *e1
= &b1
[g1
->nSpans
];
212 Span
*b2
= g2
->span
, *e2
= &b2
[g2
->nSpans
];
217 for (; b1
< e1
&& b1
->to
!= s1
; ++b1
)
222 for (; b2
< e2
&& b2
->to
!= s2
; ++b2
)
237 if (lb1
!= lb2
|| b1
->ub
!= b2
->ub
)
247 BitMap
*BitMap::first
= NULL
;
249 BitMap::BitMap(const Go
*g
, const State
*x
)
264 const BitMap
*BitMap::find(const Go
*g
, const State
*x
)
266 for (const BitMap
*b
= first
; b
; b
= b
->next
)
268 if (matches(b
->go
, b
->on
, g
, x
))
274 return new BitMap(g
, x
);
277 const BitMap
*BitMap::find(const State
*x
)
279 for (const BitMap
*b
= first
; b
; b
= b
->next
)
290 void BitMap::gen(std::ostream
&o
, uint ind
, uint lb
, uint ub
)
292 if (first
&& bLastPass
&& bUsedYYBitmap
)
294 o
<< indent(ind
) << "static const unsigned char " << mapCodeName
["yybm"] << "[] = {";
296 uint c
= 1, n
= ub
- lb
;
297 const BitMap
*cb
= first
;
299 while((cb
= cb
->next
) != NULL
) {
304 uint
*bm
= new uint
[n
];
306 for (uint i
= 0, t
= 1; b
; i
+= n
, t
+= 8)
308 memset(bm
, 0, n
* sizeof(uint
));
310 for (uint m
= 0x80; b
&& m
; m
>>= 1)
314 doGen(b
->go
, b
->on
, bm
, lb
, m
);
315 b
= const_cast<BitMap
*>(b
->next
);
320 o
<< "\n" << indent(ind
+1) << "/* table " << t
<< " .. " << std::min(c
, t
+7) << ": " << i
<< " */";
323 for (uint j
= 0; j
< n
; ++j
)
327 o
<< "\n" << indent(ind
+1);
332 prtHex(o
, bm
[j
], false);
336 o
<< std::setw(3) << (uint
)bm
[j
];
342 o
<< "\n" << indent(ind
) << "};\n";
353 for (const BitMap
*b
= first
; b
; b
= b
->next
)
355 prt(std::cerr
, b
->go
, b
->on
);
356 std::cerr
<< std::endl
;
360 std::cerr
<< n
<< " bitmaps\n";
364 void genGoTo(std::ostream
&o
, uint ind
, const State
*from
, const State
*to
, bool & readCh
)
368 o
<< from
->label
<< " -> " << to
->label
<< "\n";
372 if (readCh
&& from
->label
+ 1 != to
->label
)
374 o
<< indent(ind
) << mapCodeName
["yych"] << " = " << yychConversion
<< "*" << mapCodeName
["YYCURSOR"] << ";\n";
378 o
<< indent(ind
) << "goto " << labelPrefix
<< to
->label
<< ";\n";
379 vUsedLabels
.insert(to
->label
);
382 void genIf(std::ostream
&o
, uint ind
, const char *cmp
, uint v
, bool &readCh
)
384 o
<< indent(ind
) << "if (";
387 o
<< "(" << mapCodeName
["yych"] << " = " << yychConversion
<< "*" << mapCodeName
["YYCURSOR"] << ")";
392 o
<< mapCodeName
["yych"];
395 o
<< " " << cmp
<< " ";
400 static void need(std::ostream
&o
, uint ind
, uint n
, bool & readCh
, bool bSetMarker
)
407 uint fillIndex
= next_fill_index
;
412 if (bUseYYSetStateParam
)
414 o
<< indent(ind
) << mapCodeName
["YYSETSTATE"] << "(" << fillIndex
<< ");\n";
418 o
<< indent(ind
) << replaceParam(mapCodeName
["YYSETSTATE"], yySetStateParam
, fillIndex
) << "\n";
422 if (bUseYYFill
&& n
> 0)
429 o
<< "if (" << mapCodeName
["YYLIMIT"] << " <= " << mapCodeName
["YYCURSOR"] << ") ";
431 genYYFill(o
, ind
, n
);
437 o
<< "if ((" << mapCodeName
["YYLIMIT"] << " - " << mapCodeName
["YYCURSOR"] << ") < " << n
<< ") ";
439 genYYFill(o
, ind
, n
);
445 o
<< mapCodeName
["yyFillLabel"] << fillIndex
<< ":\n";
452 o
<< indent(ind
) << mapCodeName
["yych"] << " = " << yychConversion
<< "*(" << mapCodeName
["YYMARKER"] << " = " << mapCodeName
["YYCURSOR"] << ");\n";
456 o
<< indent(ind
) << mapCodeName
["yych"] << " = " << yychConversion
<< "*" << mapCodeName
["YYCURSOR"] << ";\n";
462 void Match::emit(std::ostream
&o
, uint ind
, bool &readCh
, const std::string
&) const
471 o
<< indent(ind
) << "++" << mapCodeName
["YYCURSOR"] << ";\n";
473 else if (!readAhead())
475 /* do not read next char if match */
476 o
<< indent(ind
) << "++" << mapCodeName
["YYCURSOR"] << ";\n";
481 o
<< indent(ind
) << mapCodeName
["yych"] << " = " << yychConversion
<< "*++" << mapCodeName
["YYCURSOR"] << ";\n";
487 need(o
, ind
, state
->depth
, readCh
, false);
491 void Enter::emit(std::ostream
&o
, uint ind
, bool &readCh
, const std::string
&) const
495 o
<< indent(ind
) << "++" << mapCodeName
["YYCURSOR"] << ";\n";
496 if (vUsedLabels
.count(label
))
498 o
<< labelPrefix
<< label
<< ":\n";
500 need(o
, ind
, state
->depth
, readCh
, false);
504 /* we shouldn't need 'rule-following' protection here */
505 o
<< indent(ind
) << mapCodeName
["yych"] << " = " << yychConversion
<< "*++" << mapCodeName
["YYCURSOR"] << ";\n";
506 if (vUsedLabels
.count(label
))
508 o
<< labelPrefix
<< label
<< ":\n";
514 void Initial::emit(std::ostream
&o
, uint ind
, bool &readCh
, const std::string
&) const
516 if (!cFlag
&& !startLabelName
.empty())
518 o
<< startLabelName
<< ":\n";
521 if (vUsedLabels
.count(1))
525 o
<< indent(ind
) << "++" << mapCodeName
["YYCURSOR"] << ";\n";
529 o
<< indent(ind
) << mapCodeName
["yych"] << " = " << yychConversion
<< "*++" << mapCodeName
["YYCURSOR"] << ";\n";
533 if (!cFlag
&& vUsedLabels
.count(label
))
535 o
<< labelPrefix
<< label
<< ":\n";
544 o
<< indent(ind
) << mapCodeName
["YYDEBUG"] << "(" << label
<< ", *" << mapCodeName
["YYCURSOR"] << ");\n";
549 need(o
, ind
, state
->depth
, readCh
, setMarker
&& bUsedYYMarker
);
553 if (setMarker
&& bUsedYYMarker
)
555 o
<< indent(ind
) << mapCodeName
["YYMARKER"] << " = " << mapCodeName
["YYCURSOR"] << ";\n";
561 void Save::emit(std::ostream
&o
, uint ind
, bool &readCh
, const std::string
&) const
570 o
<< indent(ind
) << mapCodeName
["yyaccept"] << " = " << selector
<< ";\n";
577 o
<< indent(ind
) << mapCodeName
["YYMARKER"] << " = ++" << mapCodeName
["YYCURSOR"] << ";\n";
579 need(o
, ind
, state
->depth
, readCh
, false);
585 o
<< indent(ind
) << mapCodeName
["yych"] << " = " << yychConversion
<< "*(" << mapCodeName
["YYMARKER"] << " = ++" << mapCodeName
["YYCURSOR"] << ");\n";
589 o
<< indent(ind
) << mapCodeName
["yych"] << " = " << yychConversion
<< "*++" << mapCodeName
["YYCURSOR"] << ";\n";
595 Move::Move(State
*s
) : Action(s
)
600 void Move::emit(std::ostream
&, uint
, bool &, const std::string
&) const
605 Accept::Accept(State
*x
, uint n
, uint
*s
, State
**r
)
606 : Action(x
), nRules(n
), saves(s
), rules(r
)
611 void Accept::genRuleMap()
613 for (uint i
= 0; i
< nRules
; ++i
)
617 mapRules
[saves
[i
]] = rules
[i
];
622 void Accept::emitBinary(std::ostream
&o
, uint ind
, uint l
, uint r
, bool &readCh
) const
626 uint m
= (l
+ r
) >> 1;
628 assert(bUsedYYAccept
);
629 o
<< indent(ind
) << "if (" << mapCodeName
["yyaccept"] << " <= " << m
<< ") {\n";
630 emitBinary(o
, ++ind
, l
, m
, readCh
);
631 o
<< indent(--ind
) << "} else {\n";
632 emitBinary(o
, ++ind
, m
+ 1, r
, readCh
);
633 o
<< indent(--ind
) << "}\n";
637 genGoTo(o
, ind
, state
, mapRules
.find(l
)->second
, readCh
);
641 void Accept::emit(std::ostream
&o
, uint ind
, bool &readCh
, const std::string
&) const
643 if (mapRules
.size() > 0)
645 bUsedYYMarker
= true;
648 o
<< indent(ind
) << mapCodeName
["YYCURSOR"] << " = " << mapCodeName
["YYMARKER"] << ";\n";
651 if (readCh
) // shouldn't be necessary, but might become at some point
653 o
<< indent(ind
) << mapCodeName
["yych"] << " = " << yychConversion
<< "*" << mapCodeName
["YYCURSOR"] << ";\n";
657 if (mapRules
.size() > 1)
659 bUsedYYAccept
= true;
661 if (gFlag
&& mapRules
.size() >= cGotoThreshold
)
663 o
<< indent(ind
++) << "{\n";
664 o
<< indent(ind
++) << "static void *" << mapCodeName
["yytarget"] << "[" << mapRules
.size() << "] = {\n";
665 for (RuleMap::const_iterator it
= mapRules
.begin(); it
!= mapRules
.end(); ++it
)
667 o
<< indent(ind
) << "&&" << labelPrefix
<< it
->second
->label
<< ",\n";
668 vUsedLabels
.insert(it
->second
->label
);
670 o
<< indent(--ind
) << "};\n";
671 o
<< indent(ind
) << "goto *" << mapCodeName
["yytarget"] << "[" << mapCodeName
["yyaccept"] << "];\n";
672 o
<< indent(--ind
) << "}\n";
676 emitBinary(o
, ind
, 0, mapRules
.size() - 1, readCh
);
680 for (RuleMap::const_iterator it
= mapRules
.begin(); it
!= mapRules
.end(); ++it
)
682 o
<< state
->label
<< " -> " << it
->second
->label
;
683 o
<< " [label=\"yyaccept=" << it
->first
<< "\"]\n";
688 o
<< indent(ind
) << "switch (" << mapCodeName
["yyaccept"] << ") {\n";
690 for (RuleMap::const_iterator it
= mapRules
.begin(); it
!= mapRules
.end(); ++it
)
692 o
<< indent(ind
) << "case " << it
->first
<< ": \t";
693 genGoTo(o
, 0, state
, it
->second
, readCh
);
696 o
<< indent(ind
) << "}\n";
701 // no need to write if statement here since there is only case 0.
702 genGoTo(o
, ind
, state
, mapRules
.find(0)->second
, readCh
);
707 Rule::Rule(State
*s
, RuleOp
*r
) : Action(s
), rule(r
)
712 void Rule::emit(std::ostream
&o
, uint ind
, bool &, const std::string
& condName
) const
716 o
<< state
->label
<< " [label=\"" << sourceFileInfo
.fname
<< ":" << rule
->code
->line
<< "\"];\n";
720 uint back
= rule
->ctx
->fixedLength();
724 o
<< indent(ind
) << mapCodeName
["YYCURSOR"] << " = " << mapCodeName
["YYCTXMARKER"] << ";\n";
727 if (rule
->code
->newcond
.length() && condName
!= rule
->code
->newcond
)
729 genSetCondition(o
, ind
, rule
->code
->newcond
);
734 if (!yySetupRule
.empty() && !rule
->code
->autogen
)
736 o
<< indent(ind
) << yySetupRule
<< "\n";
739 o
<< file_info(rule
->code
->source
, &rl
);
741 if (rule
->code
->autogen
)
743 o
<< replaceParam(condGoto
, condGotoParam
, condPrefix
+ rule
->code
->newcond
);
747 o
<< rule
->code
->text
;
753 void doLinear(std::ostream
&o
, uint ind
, Span
*s
, uint n
, const State
*from
, const State
*next
, bool &readCh
, uint mask
)
759 while (n
>= 3 && s
[2].to
== bg
&& (s
[1].ub
- s
[0].ub
) == 1)
761 if (s
[1].to
== next
&& n
== 3)
763 if (!mask
|| (s
[0].ub
> 0x00FF))
765 genIf(o
, ind
, "!=", s
[0].ub
, readCh
);
766 genGoTo(o
, 0, from
, bg
, readCh
);
768 if (next
->label
!= from
->label
+ 1 || DFlag
)
770 genGoTo(o
, ind
, from
, next
, readCh
);
776 if (!mask
|| (s
[0].ub
> 0x00FF))
778 genIf(o
, ind
, "==", s
[0].ub
, readCh
);
779 genGoTo(o
, 0, from
, s
[1].to
, readCh
);
790 if (s
[0].to
->label
!= from
->label
+ 1 || DFlag
)
792 genGoTo(o
, ind
, from
, s
[0].to
, readCh
);
797 else if (n
== 2 && bg
== next
)
799 if (!mask
|| (s
[0].ub
> 0x00FF))
801 genIf(o
, ind
, ">=", s
[0].ub
, readCh
);
802 genGoTo(o
, 0, from
, s
[1].to
, readCh
);
804 if (next
->label
!= from
->label
+ 1 || DFlag
)
806 genGoTo(o
, ind
, from
, next
, readCh
);
812 if (!mask
|| ((s
[0].ub
- 1) > 0x00FF))
814 genIf(o
, ind
, "<=", s
[0].ub
- 1, readCh
);
815 genGoTo(o
, 0, from
, bg
, readCh
);
822 if (next
->label
!= from
->label
+ 1 || DFlag
)
824 genGoTo(o
, ind
, from
, next
, readCh
);
828 void Go::genLinear(std::ostream
&o
, uint ind
, const State
*from
, const State
*next
, bool &readCh
, uint mask
) const
830 doLinear(o
, ind
, span
, nSpans
, from
, next
, readCh
, mask
);
833 bool genCases(std::ostream
&o
, uint ind
, uint lb
, Span
*s
, bool &newLine
, uint mask
, const State
*from
, const State
*to
)
846 if (!mask
|| lb
> 0x00FF)
850 o
<< from
->label
<< " -> " << to
->label
;
857 o
<< indent(ind
) << "case ";
877 void Go::genSwitch(std::ostream
&o
, uint ind
, const State
*from
, const State
*next
, bool &readCh
, uint mask
) const
881 if ((mask
? wSpans
: nSpans
) <= 2)
883 genLinear(o
, ind
, from
, next
, readCh
, mask
);
887 State
*def
= span
[nSpans
- 1].to
;
888 Span
**sP
= new Span
* [nSpans
- 1], **r
, **s
, **t
;
892 for (uint i
= 0; i
< nSpans
; ++i
)
894 if (span
[i
].to
!= def
)
904 o
<< indent(ind
) << mapCodeName
["YYDEBUG"] << "(-1, " << mapCodeName
["yych"] << ");\n";
909 o
<< indent(ind
) << "switch ((" << mapCodeName
["yych"] << " = " << yychConversion
<< "*" << mapCodeName
["YYCURSOR"] << ")) {\n";
914 o
<< indent(ind
) << "switch (" << mapCodeName
["yych"] << ") {\n";
924 const State
*to
= (*s
)->to
;
928 used
|= genCases(o
, ind
, 0, *s
, newLine
, mask
, from
, to
);
932 used
|= genCases(o
, ind
, (*s
)[ -1].ub
, *s
, newLine
, mask
, from
, to
);
939 used
|= genCases(o
, ind
, (*s
)[ -1].ub
, *s
, newLine
, mask
, from
, to
);
949 genGoTo(o
, newLine
? ind
+1 : 1, from
, to
, readCh
);
957 o
<< "\n" << from
->label
<< " -> " << def
->label
;
958 o
<< " [label=default]\n" ;
962 o
<< indent(ind
) << "default:";
963 genGoTo(o
, 1, from
, def
, readCh
);
964 o
<< indent(ind
) << "}\n";
971 void doBinary(std::ostream
&o
, uint ind
, Span
*s
, uint n
, const State
*from
, const State
*next
, bool &readCh
, uint mask
)
975 doLinear(o
, ind
, s
, n
, from
, next
, readCh
, mask
);
981 genIf(o
, ind
, "<=", s
[h
- 1].ub
- 1, readCh
);
983 doBinary(o
, ind
+1, &s
[0], h
, from
, next
, readCh
, mask
);
984 o
<< indent(ind
) << "} else {\n";
985 doBinary(o
, ind
+1, &s
[h
], n
- h
, from
, next
, readCh
, mask
);
986 o
<< indent(ind
) << "}\n";
990 void Go::genBinary(std::ostream
&o
, uint ind
, const State
*from
, const State
*next
, bool &readCh
, uint mask
) const
994 Span
* sc
= new Span
[wSpans
];
996 for (uint i
= 0, j
= 0; i
< nSpans
; i
++)
998 if (span
[i
].ub
> 0xFF)
1004 doBinary(o
, ind
, sc
, wSpans
, from
, next
, readCh
, mask
);
1010 doBinary(o
, ind
, span
, nSpans
, from
, next
, readCh
, mask
);
1014 void Go::genBase(std::ostream
&o
, uint ind
, const State
*from
, const State
*next
, bool &readCh
, uint mask
) const
1016 if ((mask
? wSpans
: nSpans
) == 0)
1023 genSwitch(o
, ind
, from
, next
, readCh
, mask
);
1027 if ((mask
? wSpans
: nSpans
) > 8)
1029 Span
*bot
= &span
[0], *top
= &span
[nSpans
- 1];
1032 if (bot
[0].to
== top
[0].to
)
1034 util
= (top
[ -1].ub
- bot
[0].ub
) / (nSpans
- 2);
1038 if (bot
[0].ub
> (top
[0].ub
- top
[ -1].ub
))
1040 util
= (top
[0].ub
- bot
[0].ub
) / (nSpans
- 1);
1044 util
= top
[ -1].ub
/ (nSpans
- 1);
1050 genSwitch(o
, ind
, from
, next
, readCh
, mask
);
1055 if ((mask
? wSpans
: nSpans
) > 5)
1057 genBinary(o
, ind
, from
, next
, readCh
, mask
);
1061 genLinear(o
, ind
, from
, next
, readCh
, mask
);
1065 void Go::genCpGoto(std::ostream
&o
, uint ind
, const State
*from
, const State
*next
, bool &readCh
) const
1071 sYych
= "(" + mapCodeName
["yych"] + " = " + yychConversion
+ "*" + mapCodeName
["YYCURSOR"] + ")";
1075 sYych
= mapCodeName
["yych"];
1081 o
<< indent(ind
) << "if (" << sYych
<<" & ~0xFF) {\n";
1082 genBase(o
, ind
+1, from
, next
, readCh
, 1);
1083 o
<< indent(ind
++) << "} else {\n";
1084 sYych
= mapCodeName
["yych"];
1088 o
<< indent(ind
++) << "{\n";
1090 o
<< indent(ind
++) << "static void *" << mapCodeName
["yytarget"] << "[256] = {\n";
1094 for (uint i
= 0; i
< lSpans
; ++i
)
1096 vUsedLabels
.insert(span
[i
].to
->label
);
1097 for(; ch
< span
[i
].ub
; ++ch
)
1099 o
<< "&&" << labelPrefix
<< span
[i
].to
->label
;
1106 else if (ch
% 8 == 7)
1108 o
<< ",\n" << indent(ind
);
1112 o
<< "," << space(span
[i
].to
->label
);
1116 o
<< indent(--ind
) << "};\n";
1117 o
<< indent(ind
) << "goto *" << mapCodeName
["yytarget"] << "[" << sYych
<< "];\n";
1118 o
<< indent(--ind
) << "}\n";
1121 void Go::genGoto(std::ostream
&o
, uint ind
, const State
*from
, const State
*next
, bool &readCh
)
1123 if ((gFlag
|| wFlag
) && wSpans
== ~0u)
1126 std::set
<uint
> vTargets
;
1130 for (uint i
= 0; i
< nSpans
; ++i
)
1132 if (span
[i
].ub
> 0xFF)
1136 if (span
[i
].ub
< 0x100 || !wFlag
)
1140 State
*to
= span
[i
].to
;
1142 if (to
&& to
->isBase
)
1144 const BitMap
*b
= BitMap::find(to
);
1146 if (b
&& matches(b
->go
, b
->on
, this, to
))
1153 vTargets
.insert(to
->label
);
1159 vTargets
.insert(to
->label
);
1163 lTargets
= vTargets
.size() >> nBitmaps
;
1166 if (gFlag
&& (lTargets
>= cGotoThreshold
|| dSpans
>= cGotoThreshold
))
1168 genCpGoto(o
, ind
, from
, next
, readCh
);
1173 for (uint i
= 0; i
< nSpans
; ++i
)
1175 State
*to
= span
[i
].to
;
1177 if (to
&& to
->isBase
)
1179 const BitMap
*b
= BitMap::find(to
);
1182 if (b
&& matches(b
->go
, b
->on
, this, to
))
1185 go
.span
= new Span
[nSpans
];
1189 sYych
= "(" + mapCodeName
["yych"] + " = " + yychConversion
+ "*" + mapCodeName
["YYCURSOR"] + ")";
1193 sYych
= mapCodeName
["yych"];
1198 o
<< indent(ind
) << "if (" << sYych
<< " & ~0xFF) {\n";
1199 sYych
= mapCodeName
["yych"];
1200 genBase(o
, ind
+1, from
, next
, readCh
, 1);
1201 o
<< indent(ind
) << "} else ";
1207 bUsedYYBitmap
= true;
1208 o
<< "if (" << mapCodeName
["yybm"] << "[" << b
->i
<< "+" << sYych
<< "] & ";
1211 prtHex(o
, b
->m
, false);
1218 genGoTo(o
, ind
+1, from
, to
, readCh
);
1219 o
<< indent(ind
) << "}\n";
1220 go
.genBase(o
, ind
, from
, next
, readCh
, 0);
1228 genBase(o
, ind
, from
, next
, readCh
, 0);
1231 void State::emit(std::ostream
&o
, uint ind
, bool &readCh
, const std::string
& condName
) const
1233 if (vUsedLabels
.count(label
))
1235 o
<< labelPrefix
<< label
<< ":\n";
1237 if (dFlag
&& !action
->isInitial())
1239 o
<< indent(ind
) << mapCodeName
["YYDEBUG"] << "(" << label
<< ", *" << mapCodeName
["YYCURSOR"] << ");\n";
1243 o
<< indent(ind
) << mapCodeName
["YYCTXMARKER"] << " = " << mapCodeName
["YYCURSOR"] << " + 1;\n";
1245 action
->emit(o
, ind
, readCh
, condName
);
1248 uint
merge(Span
*x0
, State
*fg
, State
*bg
)
1250 Span
*x
= x0
, *f
= fg
->go
.span
, *b
= bg
->go
.span
;
1251 uint nf
= fg
->go
.nSpans
, nb
= bg
->go
.nSpans
;
1252 State
*prev
= NULL
, *to
;
1253 // NB: we assume both spans are for same range
1259 to
= f
->to
== b
->to
? bg
: f
->to
;
1277 if (nf
== 0 && nb
== 0)
1283 while (f
->ub
< b
->ub
)
1285 to
= f
->to
== b
->to
? bg
: f
->to
;
1302 while (b
->ub
< f
->ub
)
1304 to
= b
->to
== f
->to
? bg
: f
->to
;
1323 const uint cInfinity
= ~0u;
1334 void traverse(State
*);
1343 SCC
& operator = (const SCC
& oth
)
1352 : top(new State
* [size
])
1362 void SCC::traverse(State
*x
)
1365 uint k
= ++top
- stk
;
1368 for (uint i
= 0; i
< x
->go
.nSpans
; ++i
)
1370 State
*y
= x
->go
.span
[i
].to
;
1379 if (y
->depth
< x
->depth
)
1381 x
->depth
= y
->depth
;
1390 (*--top
)->depth
= cInfinity
;
1397 static bool state_is_in_non_trivial_SCC(const State
* s
)
1400 // does not link to self
1406 // or exists i: (s->go.spans[i].to->link == s)
1408 // Note: (s->go.spans[i].to == s) is allowed, corresponds to s
1409 // looping back to itself.
1411 for (uint i
= 0; i
< s
->go
.nSpans
; ++i
)
1413 const State
* t
= s
->go
.span
[i
].to
;
1415 if (t
&& t
->link
== s
)
1424 uint
maxDist(State
*s
)
1426 if (s
->depth
!= cInfinity
)
1428 // Already calculated, just return result.
1433 for (uint i
= 0; i
< s
->go
.nSpans
; ++i
)
1435 State
*t
= s
->go
.span
[i
].to
;
1441 if (!t
->link
) // marked as non-key state
1443 if (t
->depth
== cInfinity
)
1445 t
->depth
= maxDist(t
);
1461 void calcDepth(State
*head
)
1465 // mark non-key states by s->link = NULL ;
1466 for (s
= head
; s
; s
= s
->next
)
1468 if (s
!= head
&& !state_is_in_non_trivial_SCC(s
))
1472 //else: key state, leave alone
1475 for (s
= head
; s
; s
= s
->next
)
1477 s
->depth
= cInfinity
;
1480 // calculate max number of transitions before guarantied to reach
1482 for (s
= head
; s
; s
= s
->next
)
1488 void DFA::findSCCs()
1493 for (s
= head
; s
; s
= s
->next
)
1499 for (s
= head
; s
; s
= s
->next
)
1510 void DFA::split(State
*s
)
1512 State
*move
= new State
;
1513 (void) new Move(move
);
1514 addState(&s
->next
, move
);
1515 move
->link
= s
->link
;
1516 move
->rule
= s
->rule
;
1520 s
->go
.span
= new Span
[1];
1521 s
->go
.span
[0].ub
= ubChar
;
1522 s
->go
.span
[0].to
= move
;
1525 void DFA::findBaseState()
1527 Span
*span
= new Span
[ubChar
- lbChar
];
1529 for (State
*s
= head
; s
; s
= s
->next
)
1533 for (uint i
= 0; i
< s
->go
.nSpans
; ++i
)
1535 State
*to
= s
->go
.span
[i
].to
;
1537 if (to
&& to
->isBase
)
1539 to
= to
->go
.span
[0].to
;
1540 uint nSpans
= merge(span
, s
, to
);
1542 if (nSpans
< s
->go
.nSpans
)
1544 delete [] s
->go
.span
;
1545 s
->go
.nSpans
= nSpans
;
1546 s
->go
.span
= new Span
[nSpans
];
1547 memcpy(s
->go
.span
, span
, nSpans
*sizeof(Span
));
1564 bUsedYYBitmap
= false;
1571 for (s
= head
; s
; s
= s
->next
)
1573 s
->depth
= maxDist(s
);
1574 if (maxFill
< s
->depth
)
1578 if (s
->rule
&& s
->rule
->accept
>= nRules
)
1580 nRules
= s
->rule
->accept
+ 1;
1585 saves
= new uint
[nRules
];
1586 memset(saves
, ~0, (nRules
)*sizeof(*saves
));
1588 // mark backtracking points
1589 bSaveOnHead
= false;
1591 for (s
= head
; s
; s
= s
->next
)
1595 for (i
= 0; i
< s
->go
.nSpans
; ++i
)
1597 if (s
->go
.span
[i
].to
&& !s
->go
.span
[i
].to
->rule
)
1602 if (saves
[s
->rule
->accept
] == ~0u)
1604 saves
[s
->rule
->accept
] = nSaves
++;
1607 bSaveOnHead
|= s
== head
;
1608 (void) new Save(s
, saves
[s
->rule
->accept
]); // sets s->action
1615 rules
= new State
* [nRules
];
1617 memset(rules
, 0, (nRules
)*sizeof(*rules
));
1619 State
*accept
= NULL
;
1620 Accept
*accfixup
= NULL
;
1622 for (s
= head
; s
; s
= s
->next
)
1632 if (!rules
[s
->rule
->accept
])
1634 State
*n
= new State
;
1635 (void) new Rule(n
, s
->rule
);
1636 rules
[s
->rule
->accept
] = n
;
1637 addState(&s
->next
, n
);
1640 ow
= rules
[s
->rule
->accept
];
1643 for (i
= 0; i
< s
->go
.nSpans
; ++i
)
1645 if (!s
->go
.span
[i
].to
)
1649 ow
= accept
= new State
;
1650 accfixup
= new Accept(accept
, nRules
, saves
, rules
);
1651 addState(&s
->next
, accept
);
1654 s
->go
.span
[i
].to
= ow
;
1661 accfixup
->genRuleMap();
1664 // split ``base'' states into two parts
1665 for (s
= head
; s
; s
= s
->next
)
1671 for (i
= 0; i
< s
->go
.nSpans
; ++i
)
1673 if (s
->go
.span
[i
].to
== s
)
1680 BitMap::find(&s
->next
->go
, s
);
1690 // find ``base'' state, if possible
1693 delete head
->action
;
1694 head
->action
= NULL
;
1698 void DFA::emit(std::ostream
&o
, uint
& ind
, const RegExpMap
* specMap
, const std::string
& condName
, bool isLastCond
, bool& bPrologBrace
)
1700 bool bProlog
= (!cFlag
|| !bWroteCondCheck
);
1704 bUsedYYAccept
= false;
1707 uint start_label
= next_label
;
1709 (void) new Initial(head
, next_label
++, bSaveOnHead
);
1713 if (startLabelName
.empty())
1715 vUsedLabels
.insert(start_label
);
1721 for (s
= head
; s
; s
= s
->next
)
1723 s
->label
= next_label
++;
1726 // Save 'next_fill_index' and compute information about code generation
1727 // while writing to null device.
1728 uint save_fill_index
= next_fill_index
;
1729 null_stream null_dev
;
1731 for (s
= head
; s
; s
= s
->next
)
1733 bool readCh
= false;
1734 s
->emit(null_dev
, ind
, readCh
, condName
);
1735 s
->go
.genGoto(null_dev
, ind
, s
, s
->next
, readCh
);
1737 if (last_fill_index
< next_fill_index
)
1739 last_fill_index
= next_fill_index
;
1741 next_fill_index
= save_fill_index
;
1746 o
<< "\n" << outputFileInfo
;
1750 bPrologBrace
= true;
1751 o
<< "digraph re2c {\n";
1753 else if ((!fFlag
&& bUsedYYAccept
)
1754 || (!fFlag
&& bEmitYYCh
)
1755 || (bFlag
&& !cFlag
&& BitMap::first
)
1756 || (cFlag
&& !bWroteCondCheck
&& gFlag
&& !specMap
->empty())
1757 || (fFlag
&& !bWroteGetState
&& gFlag
)
1760 bPrologBrace
= true;
1761 o
<< indent(ind
++) << "{\n";
1768 if (!fFlag
&& !DFlag
)
1772 o
<< indent(ind
) << mapCodeName
["YYCTYPE"] << " " << mapCodeName
["yych"] << ";\n";
1776 o
<< indent(ind
) << "unsigned int " << mapCodeName
["yyaccept"] << " = 0;\n";
1784 if (bFlag
&& !cFlag
&& BitMap::first
)
1786 BitMap::gen(o
, ind
, lbChar
, ubChar
<= 256 ? ubChar
: 256);
1790 genCondTable(o
, ind
, *specMap
);
1791 genGetStateGoto(o
, ind
, start_label
);
1794 if (vUsedLabels
.count(start_label
))
1796 o
<< labelPrefix
<< start_label
<< ":\n";
1798 if (!startLabelName
.empty())
1800 o
<< startLabelName
<< ":\n";
1803 genCondGoto(o
, ind
, *specMap
);
1806 if (cFlag
&& !condName
.empty())
1808 if (condDivider
.length())
1810 o
<< replaceParam(condDivider
, condDividerParam
, condName
) << "\n";
1815 o
<< condName
<< " -> " << (start_label
+1) << "\n";
1819 o
<< condPrefix
<< condName
<< ":\n";
1822 if (cFlag
&& bFlag
&& BitMap::first
)
1824 o
<< indent(ind
++) << "{\n";
1825 BitMap::gen(o
, ind
, lbChar
, ubChar
<= 256 ? ubChar
: 256);
1828 // TODO: Shouldn't labels 0 and 1 be variable?
1829 if (vUsedLabels
.count(1))
1831 vUsedLabels
.insert(0);
1832 o
<< indent(ind
) << "goto " << labelPrefix
<< "0;\n";
1836 for (s
= head
; s
; s
= s
->next
)
1838 bool readCh
= false;
1839 s
->emit(o
, ind
, readCh
, condName
);
1840 s
->go
.genGoto(o
, ind
, s
, s
->next
, readCh
);
1843 if (cFlag
&& bFlag
&& BitMap::first
)
1845 o
<< indent(--ind
) << "}\n";
1848 if ((!cFlag
|| isLastCond
) && bPrologBrace
)
1850 o
<< indent(--ind
) << "}\n";
1856 delete BitMap::first
;
1857 BitMap::first
= NULL
;
1860 bUseStartLabel
= false;
1863 void genGetStateGotoSub(std::ostream
&o
, uint ind
, uint start_label
, int cMin
, int cMax
)
1869 o
<< indent(ind
) << "goto " << labelPrefix
<< start_label
<< ";\n";
1873 o
<< indent(ind
) << "goto " << mapCodeName
["yyFillLabel"] << cMin
<< ";\n";
1878 int cMid
= cMin
+ ((cMax
- cMin
+ 1) / 2);
1880 o
<< indent(ind
) << "if (" << genGetState() << " < " << cMid
<< ") {\n";
1881 genGetStateGotoSub(o
, ind
+ 1, start_label
, cMin
, cMid
- 1);
1882 o
<< indent(ind
) << "} else {\n";
1883 genGetStateGotoSub(o
, ind
+ 1, start_label
, cMid
, cMax
);
1884 o
<< indent(ind
) << "}\n";
1888 void genGetStateGoto(std::ostream
&o
, uint
& ind
, uint start_label
)
1890 if (fFlag
&& !bWroteGetState
)
1892 vUsedLabels
.insert(start_label
);
1895 o
<< indent(ind
++) << "static void *" << mapCodeName
["yystable"] << "[" << "] = {\n";
1897 for (size_t i
=0; i
<last_fill_index
; ++i
)
1899 o
<< indent(ind
) << "&&" << mapCodeName
["yyFillLabel"] << i
<< ",\n";
1902 o
<< indent(--ind
) << "};\n";
1905 o
<< indent(ind
) << "if (" << genGetState();
1914 o
<< indent(++ind
) << "goto " << labelPrefix
<< start_label
<< ";\n";
1917 o
<< indent(--ind
) << "} else if (" << genGetState() << " < -1) {\n";
1918 o
<< indent(++ind
) << "abort();\n";
1920 o
<< indent(--ind
) << "}\n";
1922 o
<< indent(ind
) << "goto *" << mapCodeName
["yystable"] << "[" << genGetState() << "];\n";
1926 genGetStateGotoSub(o
, ind
, start_label
, -1, last_fill_index
-1);
1929 o
<< indent(ind
) << "abort();\n";
1934 o
<< indent(ind
) << "switch (" << genGetState() << ") {\n";
1937 o
<< indent(ind
) << "default: abort();\n";
1938 o
<< indent(ind
) << "case -1: goto " << labelPrefix
<< start_label
<< ";\n";
1942 o
<< indent(ind
) << "default: goto " << labelPrefix
<< start_label
<< ";\n";
1945 for (size_t i
=0; i
<last_fill_index
; ++i
)
1947 o
<< indent(ind
) << "case " << i
<< ": goto " << mapCodeName
["yyFillLabel"] << i
<< ";\n";
1950 o
<< indent(ind
) << "}\n";
1954 o
<< mapCodeName
["yyNext"] << ":\n";
1956 bWroteGetState
= true;
1960 void genCondTable(std::ostream
&o
, uint ind
, const RegExpMap
& specMap
)
1962 if (cFlag
&& !bWroteCondCheck
&& gFlag
&& specMap
.size())
1964 RegExpIndices
vCondList(specMap
.size());
1966 for(RegExpMap::const_iterator itSpec
= specMap
.begin(); itSpec
!= specMap
.end(); ++itSpec
)
1968 vCondList
[itSpec
->second
.first
] = itSpec
->first
;
1971 o
<< indent(ind
++) << "static void *" << mapCodeName
["yyctable"] << "[" << specMap
.size() << "] = {\n";
1973 for(RegExpIndices::const_iterator it
= vCondList
.begin(); it
!= vCondList
.end(); ++it
)
1975 o
<< indent(ind
) << "&&" << condPrefix
<< *it
<< ",\n";
1977 o
<< indent(--ind
) << "};\n";
1981 static void genCondGotoSub(std::ostream
&o
, uint ind
, RegExpIndices
& vCondList
, uint cMin
, uint cMax
)
1985 o
<< indent(ind
) << "goto " << condPrefix
<< vCondList
[cMin
] << ";\n";
1989 uint cMid
= cMin
+ ((cMax
- cMin
+ 1) / 2);
1991 o
<< indent(ind
) << "if (" << genGetCondition() << " < " << cMid
<< ") {\n";
1992 genCondGotoSub(o
, ind
+ 1, vCondList
, cMin
, cMid
- 1);
1993 o
<< indent(ind
) << "} else {\n";
1994 genCondGotoSub(o
, ind
+ 1, vCondList
, cMid
, cMax
);
1995 o
<< indent(ind
) << "}\n";
1999 void genCondGoto(std::ostream
&o
, uint ind
, const RegExpMap
& specMap
)
2001 if (cFlag
&& !bWroteCondCheck
&& specMap
.size())
2005 o
<< indent(ind
) << "goto *" << mapCodeName
["yyctable"] << "[" << genGetCondition() << "];\n";
2011 RegExpIndices
vCondList(specMap
.size());
2013 for(RegExpMap::const_iterator it
= specMap
.begin(); it
!= specMap
.end(); ++it
)
2015 vCondList
[it
->second
.first
] = it
->first
;
2017 genCondGotoSub(o
, ind
, vCondList
, 0, vCondList
.size() - 1);
2021 for(RegExpMap::const_iterator it
= specMap
.begin(); it
!= specMap
.end(); ++it
)
2023 o
<< "0 -> " << it
->first
<< " [label=\"state=" << it
->first
<< "\"]\n";
2028 o
<< indent(ind
) << "switch (" << genGetCondition() << ") {\n";
2030 for(RegExpMap::const_iterator it
= specMap
.begin(); it
!= specMap
.end(); ++it
)
2032 o
<< indent(ind
) << "case " << condEnumPrefix
<< it
->first
<< ": goto " << condPrefix
<< it
->first
<< ";\n";
2034 o
<< indent(ind
) << "}\n";
2037 bWroteCondCheck
= true;
2041 void genTypes(std::string
& o
, uint ind
, const RegExpMap
& specMap
)
2045 o
+= indent(ind
++) + "enum " + mapCodeName
["YYCONDTYPE"] + " {\n";
2047 RegExpIndices
vCondList(specMap
.size());
2049 for(RegExpMap::const_iterator itSpecMap
= specMap
.begin(); itSpecMap
!= specMap
.end(); ++itSpecMap
)
2051 // If an entry is < 0 then we did the 0/empty correction twice.
2052 assert(itSpecMap
->second
.first
>= 0);
2053 vCondList
[itSpecMap
->second
.first
] = itSpecMap
->first
;
2056 for(RegExpIndices::const_iterator itCondType
= vCondList
.begin(); itCondType
!= vCondList
.end(); ++itCondType
)
2058 o
+= indent(ind
) + condEnumPrefix
+ *itCondType
+ ",\n";
2061 o
+= indent(--ind
) + "};\n";
2064 void genHeader(std::ostream
&o
, uint ind
, const RegExpMap
& specMap
)
2066 o
<< "/* Generated by re2c " PACKAGE_VERSION
;
2067 if (!bNoGenerationDate
)
2070 time_t now
= time(&now
);
2071 o
.write(ctime(&now
), 24);
2074 o
<< headerFileInfo
;
2077 genTypes(typesInline
, ind
, specMap
);
2081 std::ostream
& operator << (std::ostream
& o
, const file_info
& li
)
2083 if (li
.ln
&& !iFlag
)
2085 o
<< "#line " << li
.ln
->get_line() << " \"" << li
.fname
<< "\"\n";
2090 void Scanner::config(const Str
& cfg
, int num
)
2092 if (cfg
.to_string() == "indent:top")
2096 fatal("configuration 'indent:top' must be a positive integer");
2100 else if (cfg
.to_string() == "yybm:hex")
2102 yybmHexTable
= num
!= 0;
2104 else if (cfg
.to_string() == "startlabel")
2106 bUseStartLabel
= num
!= 0;
2107 startLabelName
= "";
2109 else if (cfg
.to_string() == "state:abort")
2111 bUseStateAbort
= num
!= 0;
2113 else if (cfg
.to_string() == "state:nextlabel")
2115 bUseStateNext
= num
!= 0;
2117 else if (cfg
.to_string() == "yyfill:enable")
2119 bUseYYFill
= num
!= 0;
2121 else if (cfg
.to_string() == "yyfill:parameter")
2123 bUseYYFillParam
= num
!= 0;
2125 else if (cfg
.to_string() == "yyfill:check")
2127 bUseYYFillCheck
= num
!= 0;
2129 else if (cfg
.to_string() == "cgoto:threshold")
2131 cGotoThreshold
= num
;
2133 else if (cfg
.to_string() == "yych:conversion")
2137 yychConversion
= "(";
2138 yychConversion
+= mapCodeName
["YYCTYPE"];
2139 yychConversion
+= ")";
2143 yychConversion
= "";
2146 else if (cfg
.to_string() == "yych:emit")
2148 bEmitYYCh
= num
!= 0;
2150 else if (cfg
.to_string() == "define:YYFILL:naked")
2152 bUseYYFillNaked
= num
!= 0;
2154 else if (cfg
.to_string() == "define:YYGETCONDITION:naked")
2156 bUseYYGetConditionNaked
= num
!= 0;
2158 else if (cfg
.to_string() == "define:YYGETSTATE:naked")
2160 bUseYYGetStateNaked
= num
!= 0;
2162 else if (cfg
.to_string() == "define:YYSETSTATE:naked")
2164 bUseYYSetStateNaked
= num
!= 0;
2166 else if (cfg
.to_string() == "flags:u")
2170 fatalf("cannot use configuration name '%s' without -r flag", cfg
.to_string().c_str());
2174 else if (cfg
.to_string() == "flags:w")
2178 fatalf("cannot use configuration name '%s' without -r flag", cfg
.to_string().c_str());
2184 fatalf("unrecognized configuration name '%s' or illegal integer value", cfg
.to_string().c_str());
2188 static std::set
<std::string
> mapVariableKeys
;
2189 static std::set
<std::string
> mapDefineKeys
;
2190 static std::set
<std::string
> mapLabelKeys
;
2192 void Scanner::config(const Str
& cfg
, const Str
& val
)
2194 if (mapDefineKeys
.empty())
2196 mapVariableKeys
.insert("variable:yyaccept");
2197 mapVariableKeys
.insert("variable:yybm");
2198 mapVariableKeys
.insert("variable:yych");
2199 mapVariableKeys
.insert("variable:yyctable");
2200 mapVariableKeys
.insert("variable:yystable");
2201 mapVariableKeys
.insert("variable:yytarget");
2202 mapDefineKeys
.insert("define:YYCONDTYPE");
2203 mapDefineKeys
.insert("define:YYCTXMARKER");
2204 mapDefineKeys
.insert("define:YYCTYPE");
2205 mapDefineKeys
.insert("define:YYCURSOR");
2206 mapDefineKeys
.insert("define:YYDEBUG");
2207 mapDefineKeys
.insert("define:YYFILL");
2208 mapDefineKeys
.insert("define:YYGETCONDITION");
2209 mapDefineKeys
.insert("define:YYGETSTATE");
2210 mapDefineKeys
.insert("define:YYLIMIT");
2211 mapDefineKeys
.insert("define:YYMARKER");
2212 mapDefineKeys
.insert("define:YYSETCONDITION");
2213 mapDefineKeys
.insert("define:YYSETSTATE");
2214 mapLabelKeys
.insert("label:yyFillLabel");
2215 mapLabelKeys
.insert("label:yyNext");
2220 if (val
.len
>= 2 && val
.str
[0] == val
.str
[val
.len
-1]
2221 && (val
.str
[0] == '"' || val
.str
[0] == '\''))
2223 SubStr
tmp(val
.str
+ 1, val
.len
- 2);
2224 unescape(tmp
, strVal
);
2228 strVal
= val
.to_string();
2231 if (cfg
.to_string() == "indent:string")
2235 else if (cfg
.to_string() == "startlabel")
2237 startLabelName
= strVal
;
2238 bUseStartLabel
= !startLabelName
.empty();
2240 else if (cfg
.to_string() == "labelprefix")
2242 labelPrefix
= strVal
;
2244 else if (cfg
.to_string() == "condprefix")
2246 condPrefix
= strVal
;
2248 else if (cfg
.to_string() == "condenumprefix")
2250 condEnumPrefix
= strVal
;
2252 else if (cfg
.to_string() == "cond:divider")
2254 condDivider
= strVal
;
2256 else if (cfg
.to_string() == "cond:divider@cond")
2258 condDividerParam
= strVal
;
2260 else if (cfg
.to_string() == "cond:goto")
2264 else if (cfg
.to_string() == "cond:goto@cond")
2266 condGotoParam
= strVal
;
2268 else if (cfg
.to_string() == "define:YYFILL@len")
2270 yyFillLength
= strVal
;
2271 bUseYYFillParam
= false;
2273 else if (cfg
.to_string() == "define:YYSETCONDITION@cond")
2275 yySetConditionParam
= strVal
;
2276 bUseYYSetConditionParam
= false;
2278 else if (cfg
.to_string() == "define:YYSETSTATE@state")
2280 yySetStateParam
= strVal
;
2281 bUseYYSetStateParam
= false;
2283 else if (mapVariableKeys
.find(cfg
.to_string()) != mapVariableKeys
.end())
2285 if ((bFirstPass
|| rFlag
) && !mapCodeName
.insert(
2286 std::make_pair(cfg
.to_string().substr(sizeof("variable:") - 1), strVal
)
2289 fatalf("variable '%s' already being used and cannot be changed", cfg
.to_string().c_str());
2292 else if (mapDefineKeys
.find(cfg
.to_string()) != mapDefineKeys
.end())
2294 if ((bFirstPass
|| rFlag
) && !mapCodeName
.insert(
2295 std::make_pair(cfg
.to_string().substr(sizeof("define:") - 1), strVal
)
2298 fatalf("define '%s' already being used and cannot be changed", cfg
.to_string().c_str());
2301 else if (mapLabelKeys
.find(cfg
.to_string()) != mapLabelKeys
.end())
2303 if ((bFirstPass
|| rFlag
) && !mapCodeName
.insert(
2304 std::make_pair(cfg
.to_string().substr(sizeof("label:") - 1), strVal
)
2307 fatalf("label '%s' already being used and cannot be changed", cfg
.to_string().c_str());
2312 std::string msg
= "unrecognized configuration name '";
2313 msg
+= cfg
.to_string();
2314 msg
+= "' or illegal string value";
2319 ScannerState::ScannerState()
2320 : tok(NULL
), ptr(NULL
), cur(NULL
), pos(NULL
), ctx(NULL
)
2321 , bot(NULL
), lim(NULL
), top(NULL
), eof(NULL
)
2322 , tchar(0), tline(0), cline(1), iscfg(0)
2327 Scanner::Scanner(std::istream
& i
, std::ostream
& o
)
2328 : ScannerState(), in(i
), out(o
)
2332 char *Scanner::fill(char *cursor
, uint need
)
2337 /* Do not get rid of anything when rFlag is active. Otherwise
2338 * get rid of everything that was already handedout. */
2344 memmove(bot
, tok
, top
- tok
);
2354 /* In crease buffer size. */
2359 if (static_cast<uint
>(top
- lim
) < need
)
2361 char *buf
= new char[(lim
- bot
) + need
];
2364 fatal("Out of memory");
2366 memcpy(buf
, bot
, lim
- bot
);
2367 tok
= &buf
[tok
- bot
];
2368 ptr
= &buf
[ptr
- bot
];
2369 cur
= &buf
[cur
- bot
];
2370 pos
= &buf
[pos
- bot
];
2371 lim
= &buf
[lim
- bot
];
2373 ctx
= &buf
[ctx
- bot
];
2374 cursor
= &buf
[cursor
- bot
];
2378 /* Append to buffer. */
2380 if ((cnt
= in
.gcount()) != need
)
2390 void Scanner::set_in_parse(bool new_in_parse
)
2392 in_parse
= new_in_parse
;
2395 void Scanner::fatal_at(uint line
, uint ofs
, const char *msg
) const
2398 std::cerr
<< "re2c: error: "
2399 << "line " << line
<< ", column " << (tchar
+ ofs
+ 1) << ": "
2400 << msg
<< std::endl
;
2404 void Scanner::fatal(uint ofs
, const char *msg
) const
2406 fatal_at(in_parse
? tline
: cline
, ofs
, msg
);
2409 void Scanner::fatalf_at(uint line
, const char* fmt
, ...) const
2415 va_start(args
, fmt
);
2416 vsnprintf(szBuf
, sizeof(szBuf
), fmt
, args
);
2419 szBuf
[sizeof(szBuf
)-1] = '0';
2421 fatal_at(line
, 0, szBuf
);
2424 void Scanner::fatalf(const char *fmt
, ...) const
2430 va_start(args
, fmt
);
2431 vsnprintf(szBuf
, sizeof(szBuf
), fmt
, args
);
2434 szBuf
[sizeof(szBuf
)-1] = '0';
2447 void Scanner::check_token_length(char *pos
, uint len
) const
2449 if (pos
< bot
|| pos
+ len
> top
)
2451 fatal("Token exceeds limit");
2455 Str
Scanner::raw_token(std::string enclosure
) const
2457 return Str(std::string(enclosure
+ token().to_string() + enclosure
).c_str());
2460 void Scanner::reuse()
2463 next_fill_index
= 0;
2464 bWroteGetState
= false;
2465 bWroteCondCheck
= false;
2466 mapCodeName
.clear();
2469 void Scanner::restore_state(const ScannerState
& state
)
2471 int diff
= bot
- state
.bot
;
2472 char *old_bot
= bot
;
2473 char *old_lim
= lim
;
2474 char *old_top
= top
;
2475 char *old_eof
= eof
;
2476 *(ScannerState
*)this = state
;
2491 } // end namespace re2c