| /* |
| * Copyright 2017 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "RegexNode.h" |
| |
| #include "NFA.h" |
| |
| std::vector<int> RegexNode::createStates(NFA* nfa, const std::vector<int>& accept) const { |
| std::vector<int> result; |
| switch (fKind) { |
| case kChar_Kind: |
| result.push_back(nfa->addState(NFAState(fPayload.fChar, accept))); |
| break; |
| case kCharset_Kind: { |
| std::vector<bool> chars; |
| for (const RegexNode& child : fChildren) { |
| if (child.fKind == kChar_Kind) { |
| while (chars.size() <= (size_t) child.fPayload.fChar) { |
| chars.push_back(false); |
| } |
| chars[child.fPayload.fChar] = true; |
| } else { |
| SkASSERT(child.fKind == kRange_Kind); |
| while (chars.size() <= (size_t) child.fChildren[1].fPayload.fChar) { |
| chars.push_back(false); |
| } |
| for (char c = child.fChildren[0].fPayload.fChar; |
| c <= child.fChildren[1].fPayload.fChar; |
| ++c) { |
| chars[c] = true; |
| } |
| } |
| } |
| result.push_back(nfa->addState(NFAState(fPayload.fBool, chars, accept))); |
| break; |
| } |
| case kConcat_Kind: { |
| std::vector<int> right = fChildren[1].createStates(nfa, accept); |
| result = fChildren[0].createStates(nfa, right); |
| break; |
| } |
| case kDot_Kind: |
| result.push_back(nfa->addState(NFAState(NFAState::kDot_Kind, accept))); |
| break; |
| case kOr_Kind: { |
| std::vector<int> states = fChildren[0].createStates(nfa, accept); |
| result.insert(result.end(), states.begin(), states.end()); |
| states = fChildren[1].createStates(nfa, accept); |
| result.insert(result.end(), states.begin(), states.end()); |
| break; |
| } |
| case kPlus_Kind: { |
| std::vector<int> next = accept; |
| std::vector<int> placeholder; |
| int id = nfa->addState(NFAState(placeholder)); |
| next.push_back(id); |
| result = fChildren[0].createStates(nfa, next); |
| nfa->fStates[id] = NFAState(result); |
| break; |
| } |
| case kQuestion_Kind: |
| result = fChildren[0].createStates(nfa, accept); |
| result.insert(result.end(), accept.begin(), accept.end()); |
| break; |
| case kRange_Kind: |
| ABORT("unreachable"); |
| case kStar_Kind: { |
| std::vector<int> next = accept; |
| std::vector<int> placeholder; |
| int id = nfa->addState(NFAState(placeholder)); |
| next.push_back(id); |
| result = fChildren[0].createStates(nfa, next); |
| result.insert(result.end(), accept.begin(), accept.end()); |
| nfa->fStates[id] = NFAState(result); |
| break; |
| } |
| } |
| return result; |
| } |
| |
| std::string RegexNode::description() const { |
| switch (fKind) { |
| case kChar_Kind: |
| return std::string(1, fPayload.fChar); |
| case kCharset_Kind: { |
| std::string result("["); |
| if (fPayload.fBool) { |
| result += "^"; |
| } |
| for (const RegexNode& c : fChildren) { |
| result += c.description(); |
| } |
| result += "]"; |
| return result; |
| } |
| case kConcat_Kind: |
| return fChildren[0].description() + fChildren[1].description(); |
| case kDot_Kind: |
| return "."; |
| case kOr_Kind: |
| return "(" + fChildren[0].description() + "|" + fChildren[1].description() + ")"; |
| case kPlus_Kind: |
| return fChildren[0].description() + "+"; |
| case kQuestion_Kind: |
| return fChildren[0].description() + "?"; |
| case kRange_Kind: |
| return fChildren[0].description() + "-" + fChildren[1].description(); |
| case kStar_Kind: |
| return fChildren[0].description() + "*"; |
| default: |
| return "<" + std::to_string(fKind) + ">"; |
| } |
| } |