114 typedef typename Encoding::Ch Ch;
118 ownAllocator_(allocator ? 0 :
RAPIDJSON_NEW(
Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
119 states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
120 anchorBegin_(), anchorEnd_()
132 bool IsValid()
const {
133 return root_ != kRegexInvalidState;
147 static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
148 static const unsigned kRangeNegationFlag = 0x80000000;
172 return states_.template Bottom<State>()[index];
175 const State& GetState(
SizeType index)
const {
177 return states_.template Bottom<State>()[index];
182 return ranges_.template Bottom<Range>()[index];
185 const Range& GetRange(
SizeType index)
const {
187 return ranges_.template Bottom<Range>()[index];
190 template <
typename InputStream>
191 void Parse(DecodedStream<InputStream, Encoding>& ds) {
192 Stack<Allocator> operandStack(allocator_, 256);
193 Stack<Allocator> operatorStack(allocator_, 256);
194 Stack<Allocator> atomCountStack(allocator_, 256);
196 *atomCountStack.template Push<unsigned>() = 0;
199 while (ds.Peek() != 0) {
200 switch (codepoint = ds.Take()) {
210 while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
211 if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
213 *operatorStack.template Push<Operator>() = kAlternation;
214 *atomCountStack.template Top<unsigned>() = 0;
218 *operatorStack.template Push<Operator>() = kLeftParenthesis;
219 *atomCountStack.template Push<unsigned>() = 0;
223 while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
224 if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
226 if (operatorStack.Empty())
228 operatorStack.template Pop<Operator>(1);
229 atomCountStack.template Pop<unsigned>(1);
230 ImplicitConcatenation(atomCountStack, operatorStack);
234 if (!Eval(operandStack, kZeroOrOne))
239 if (!Eval(operandStack, kZeroOrMore))
244 if (!Eval(operandStack, kOneOrMore))
251 if (!ParseUnsigned(ds, &n))
254 if (ds.Peek() ==
',') {
256 if (ds.Peek() ==
'}')
257 m = kInfinityQuantifier;
258 else if (!ParseUnsigned(ds, &m) || m < n)
264 if (!EvalQuantifier(operandStack, n, m) || ds.Peek() !=
'}')
272 ImplicitConcatenation(atomCountStack, operatorStack);
278 if (!ParseRange(ds, &range))
280 SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
281 GetState(s).rangeStart = range;
282 *operandStack.template Push<Frag>() = Frag(s, s, s);
284 ImplicitConcatenation(atomCountStack, operatorStack);
288 if (!CharacterEscape(ds, &codepoint))
291 RAPIDJSON_DELIBERATE_FALLTHROUGH;
294 PushOperand(operandStack, codepoint);
295 ImplicitConcatenation(atomCountStack, operatorStack);
299 while (!operatorStack.Empty())
300 if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
304 if (operandStack.GetSize() ==
sizeof(Frag)) {
305 Frag* e = operandStack.template Pop<Frag>(1);
306 Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
309#if RAPIDJSON_REGEX_VERBOSE
310 printf(
"root: %d\n", root_);
311 for (
SizeType i = 0; i < stateCount_ ; i++) {
312 State& s = GetState(i);
313 printf(
"[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (
char)s.codepoint);
321 State* s = states_.template Push<State>();
324 s->codepoint = codepoint;
325 s->rangeStart = kRegexInvalidRange;
326 return stateCount_++;
329 void PushOperand(Stack<Allocator>& operandStack,
unsigned codepoint) {
330 SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
331 *operandStack.template Push<Frag>() = Frag(s, s, s);
334 void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
335 if (*atomCountStack.template Top<unsigned>())
336 *operatorStack.template Push<Operator>() = kConcatenation;
337 (*atomCountStack.template Top<unsigned>())++;
342 while (GetState(l1).out != kRegexInvalidState)
343 l1 = GetState(l1).
out;
344 GetState(l1).
out = l2;
349 for (
SizeType next; l != kRegexInvalidState; l = next) {
350 next = GetState(l).
out;
355 bool Eval(Stack<Allocator>& operandStack, Operator op) {
360 Frag e2 = *operandStack.template Pop<Frag>(1);
361 Frag e1 = *operandStack.template Pop<Frag>(1);
362 Patch(e1.out, e2.start);
363 *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
368 if (operandStack.GetSize() >=
sizeof(Frag) * 2) {
369 Frag e2 = *operandStack.template Pop<Frag>(1);
370 Frag e1 = *operandStack.template Pop<Frag>(1);
371 SizeType s = NewState(e1.start, e2.start, 0);
372 *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
378 if (operandStack.GetSize() >=
sizeof(Frag)) {
379 Frag e = *operandStack.template Pop<Frag>(1);
380 SizeType s = NewState(kRegexInvalidState, e.start, 0);
381 *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
387 if (operandStack.GetSize() >=
sizeof(Frag)) {
388 Frag e = *operandStack.template Pop<Frag>(1);
389 SizeType s = NewState(kRegexInvalidState, e.start, 0);
391 *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
397 if (operandStack.GetSize() >=
sizeof(Frag)) {
398 Frag e = *operandStack.template Pop<Frag>(1);
399 SizeType s = NewState(kRegexInvalidState, e.start, 0);
401 *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
412 bool EvalQuantifier(Stack<Allocator>& operandStack,
unsigned n,
unsigned m) {
419 else if (m == kInfinityQuantifier)
420 Eval(operandStack, kZeroOrMore);
422 Eval(operandStack, kZeroOrOne);
423 for (
unsigned i = 0; i < m - 1; i++)
424 CloneTopOperand(operandStack);
425 for (
unsigned i = 0; i < m - 1; i++)
426 Eval(operandStack, kConcatenation);
431 for (
unsigned i = 0; i < n - 1; i++)
432 CloneTopOperand(operandStack);
434 if (m == kInfinityQuantifier)
435 Eval(operandStack, kOneOrMore);
437 CloneTopOperand(operandStack);
438 Eval(operandStack, kZeroOrOne);
439 for (
unsigned i = n; i < m - 1; i++)
440 CloneTopOperand(operandStack);
441 for (
unsigned i = n; i < m; i++)
442 Eval(operandStack, kConcatenation);
445 for (
unsigned i = 0; i < n - 1; i++)
446 Eval(operandStack, kConcatenation);
453 void CloneTopOperand(Stack<Allocator>& operandStack) {
454 const Frag src = *operandStack.template Top<Frag>();
455 SizeType count = stateCount_ - src.minIndex;
456 State* s = states_.template Push<State>(count);
457 memcpy(s, &GetState(src.minIndex), count *
sizeof(State));
458 for (
SizeType j = 0; j < count; j++) {
459 if (s[j].out != kRegexInvalidState)
461 if (s[j].out1 != kRegexInvalidState)
464 *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
465 stateCount_ += count;
468 template <
typename InputStream>
469 bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds,
unsigned* u) {
471 if (ds.Peek() <
'0' || ds.Peek() >
'9')
473 while (ds.Peek() >=
'0' && ds.Peek() <=
'9') {
474 if (r >= 429496729 && ds.Peek() >
'5')
476 r = r * 10 + (ds.Take() -
'0');
482 template <
typename InputStream>
483 bool ParseRange(DecodedStream<InputStream, Encoding>& ds,
SizeType* range) {
487 SizeType start = kRegexInvalidRange;
488 SizeType current = kRegexInvalidRange;
490 while ((codepoint = ds.Take()) != 0) {
493 if (codepoint ==
'^') {
501 if (start == kRegexInvalidRange)
506 GetRange(current).next = r;
509 GetRange(start).start |= kRangeNegationFlag;
514 if (ds.Peek() ==
'b') {
518 else if (!CharacterEscape(ds, &codepoint))
521 RAPIDJSON_DELIBERATE_FALLTHROUGH;
526 if (codepoint ==
'-') {
531 RAPIDJSON_DELIBERATE_FALLTHROUGH;
536 if (current != kRegexInvalidRange)
537 GetRange(current).next = r;
538 if (start == kRegexInvalidRange)
547 GetRange(current).end = codepoint;
555 SizeType NewRange(
unsigned codepoint) {
556 Range* r = ranges_.template Push<Range>();
557 r->start = r->end = codepoint;
558 r->next = kRegexInvalidRange;
559 return rangeCount_++;
562 template <
typename InputStream>
563 bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds,
unsigned* escapedCodepoint) {
565 switch (codepoint = ds.Take()) {
580 *escapedCodepoint = codepoint;
return true;
581 case 'f': *escapedCodepoint = 0x000C;
return true;
582 case 'n': *escapedCodepoint = 0x000A;
return true;
583 case 'r': *escapedCodepoint = 0x000D;
return true;
584 case 't': *escapedCodepoint = 0x0009;
return true;
585 case 'v': *escapedCodepoint = 0x000B;
return true;
593 Stack<Allocator> states_;
594 Stack<Allocator> ranges_;
599 static const unsigned kInfinityQuantifier = ~0u;
609 typedef typename RegexType::EncodingType Encoding;
610 typedef typename Encoding::Ch Ch;
613 regex_(regex), allocator_(allocator), ownAllocator_(0),
614 state0_(allocator, 0), state1_(allocator, 0), stateSet_()
619 stateSet_ =
static_cast<unsigned*
>(allocator_->Malloc(GetStateSetSize()));
620 state0_.template Reserve<SizeType>(regex_.stateCount_);
621 state1_.template Reserve<SizeType>(regex_.stateCount_);
625 Allocator::Free(stateSet_);
629 template <
typename InputStream>
630 bool Match(InputStream& is) {
631 return SearchWithAnchoring(is,
true,
true);
634 bool Match(
const Ch* s) {
639 template <
typename InputStream>
640 bool Search(InputStream& is) {
641 return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);
644 bool Search(
const Ch* s) {
650 typedef typename RegexType::State State;
651 typedef typename RegexType::Range Range;
653 template <
typename InputStream>
654 bool SearchWithAnchoring(InputStream& is,
bool anchorBegin,
bool anchorEnd) {
659 const size_t stateSetSize = GetStateSetSize();
660 std::memset(stateSet_, 0, stateSetSize);
662 bool matched = AddState(*current, regex_.root_);
664 while (!current->Empty() && (codepoint = ds.Take()) != 0) {
665 std::memset(stateSet_, 0, stateSetSize);
668 for (
const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
669 const State& sr = regex_.GetState(*s);
670 if (sr.codepoint == codepoint ||
671 sr.codepoint == RegexType::kAnyCharacterClass ||
672 (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
674 matched = AddState(*next, sr.out) || matched;
675 if (!anchorEnd && matched)
679 AddState(*next, regex_.root_);
681 internal::Swap(current, next);
687 size_t GetStateSetSize()
const {
688 return (regex_.stateCount_ + 31) / 32 * 4;
695 const State& s = regex_.GetState(index);
696 if (s.out1 != kRegexInvalidState) {
697 bool matched = AddState(l, s.out);
698 return AddState(l, s.out1) || matched;
700 else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {
701 stateSet_[index >> 5] |= (1u << (index & 31));
702 *l.template PushUnsafe<SizeType>() = index;
704 return s.out == kRegexInvalidState;
707 bool MatchRange(
SizeType rangeIndex,
unsigned codepoint)
const {
708 bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;
709 while (rangeIndex != kRegexInvalidRange) {
710 const Range& r = regex_.GetRange(rangeIndex);
711 if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)
718 const RegexType& regex_;