1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2017 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SKSL_NFASTATE 9*c8dee2aaSAndroid Build Coastguard Worker #define SKSL_NFASTATE 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include <string> 12*c8dee2aaSAndroid Build Coastguard Worker #include <vector> 13*c8dee2aaSAndroid Build Coastguard Worker 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/lex/LexUtil.h" 15*c8dee2aaSAndroid Build Coastguard Worker 16*c8dee2aaSAndroid Build Coastguard Worker struct NFAState { 17*c8dee2aaSAndroid Build Coastguard Worker enum Kind { 18*c8dee2aaSAndroid Build Coastguard Worker // represents an accept state - if the NFA ends up in this state, we have successfully 19*c8dee2aaSAndroid Build Coastguard Worker // matched the token indicated by fData[0] 20*c8dee2aaSAndroid Build Coastguard Worker kAccept_Kind, 21*c8dee2aaSAndroid Build Coastguard Worker // matches the single character fChar 22*c8dee2aaSAndroid Build Coastguard Worker kChar_Kind, 23*c8dee2aaSAndroid Build Coastguard Worker // the regex '.'; matches any char but '\n' 24*c8dee2aaSAndroid Build Coastguard Worker kDot_Kind, 25*c8dee2aaSAndroid Build Coastguard Worker // a state which serves as a placeholder for the states indicated in fData. When we 26*c8dee2aaSAndroid Build Coastguard Worker // transition to this state, we instead transition to all of the fData states. 27*c8dee2aaSAndroid Build Coastguard Worker kRemapped_Kind, 28*c8dee2aaSAndroid Build Coastguard Worker // contains a list of true/false values in fData. fData[c] tells us whether we accept the 29*c8dee2aaSAndroid Build Coastguard Worker // character c. 30*c8dee2aaSAndroid Build Coastguard Worker kTable_Kind 31*c8dee2aaSAndroid Build Coastguard Worker }; 32*c8dee2aaSAndroid Build Coastguard Worker NFAStateNFAState33*c8dee2aaSAndroid Build Coastguard Worker NFAState(Kind kind, std::vector<int> next) 34*c8dee2aaSAndroid Build Coastguard Worker : fKind(kind) 35*c8dee2aaSAndroid Build Coastguard Worker , fNext(std::move(next)) {} 36*c8dee2aaSAndroid Build Coastguard Worker NFAStateNFAState37*c8dee2aaSAndroid Build Coastguard Worker NFAState(char c, std::vector<int> next) 38*c8dee2aaSAndroid Build Coastguard Worker : fKind(kChar_Kind) 39*c8dee2aaSAndroid Build Coastguard Worker , fChar(c) 40*c8dee2aaSAndroid Build Coastguard Worker , fNext(std::move(next)) {} 41*c8dee2aaSAndroid Build Coastguard Worker NFAStateNFAState42*c8dee2aaSAndroid Build Coastguard Worker NFAState(std::vector<int> states) 43*c8dee2aaSAndroid Build Coastguard Worker : fKind(kRemapped_Kind) 44*c8dee2aaSAndroid Build Coastguard Worker , fData(std::move(states)) {} 45*c8dee2aaSAndroid Build Coastguard Worker NFAStateNFAState46*c8dee2aaSAndroid Build Coastguard Worker NFAState(bool inverse, std::vector<bool> accepts, std::vector<int> next) 47*c8dee2aaSAndroid Build Coastguard Worker : fKind(kTable_Kind) 48*c8dee2aaSAndroid Build Coastguard Worker , fInverse(inverse) 49*c8dee2aaSAndroid Build Coastguard Worker , fNext(std::move(next)) { 50*c8dee2aaSAndroid Build Coastguard Worker for (bool b : accepts) { 51*c8dee2aaSAndroid Build Coastguard Worker fData.push_back(b); 52*c8dee2aaSAndroid Build Coastguard Worker } 53*c8dee2aaSAndroid Build Coastguard Worker } 54*c8dee2aaSAndroid Build Coastguard Worker NFAStateNFAState55*c8dee2aaSAndroid Build Coastguard Worker NFAState(int token) 56*c8dee2aaSAndroid Build Coastguard Worker : fKind(kAccept_Kind) { 57*c8dee2aaSAndroid Build Coastguard Worker fData.push_back(token); 58*c8dee2aaSAndroid Build Coastguard Worker } 59*c8dee2aaSAndroid Build Coastguard Worker acceptNFAState60*c8dee2aaSAndroid Build Coastguard Worker bool accept(char c) const { 61*c8dee2aaSAndroid Build Coastguard Worker switch (fKind) { 62*c8dee2aaSAndroid Build Coastguard Worker case kAccept_Kind: 63*c8dee2aaSAndroid Build Coastguard Worker return false; 64*c8dee2aaSAndroid Build Coastguard Worker case kChar_Kind: 65*c8dee2aaSAndroid Build Coastguard Worker return c == fChar; 66*c8dee2aaSAndroid Build Coastguard Worker case kDot_Kind: 67*c8dee2aaSAndroid Build Coastguard Worker return c != '\n'; 68*c8dee2aaSAndroid Build Coastguard Worker case kTable_Kind: { 69*c8dee2aaSAndroid Build Coastguard Worker bool value; 70*c8dee2aaSAndroid Build Coastguard Worker if ((size_t) c < fData.size()) { 71*c8dee2aaSAndroid Build Coastguard Worker value = fData[c]; 72*c8dee2aaSAndroid Build Coastguard Worker } else { 73*c8dee2aaSAndroid Build Coastguard Worker value = false; 74*c8dee2aaSAndroid Build Coastguard Worker } 75*c8dee2aaSAndroid Build Coastguard Worker return value != fInverse; 76*c8dee2aaSAndroid Build Coastguard Worker } 77*c8dee2aaSAndroid Build Coastguard Worker default: 78*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE; 79*c8dee2aaSAndroid Build Coastguard Worker } 80*c8dee2aaSAndroid Build Coastguard Worker } 81*c8dee2aaSAndroid Build Coastguard Worker 82*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG descriptionNFAState83*c8dee2aaSAndroid Build Coastguard Worker std::string description() const { 84*c8dee2aaSAndroid Build Coastguard Worker switch (fKind) { 85*c8dee2aaSAndroid Build Coastguard Worker case kAccept_Kind: 86*c8dee2aaSAndroid Build Coastguard Worker return "Accept(" + std::to_string(fData[0]) + ")"; 87*c8dee2aaSAndroid Build Coastguard Worker case kChar_Kind: { 88*c8dee2aaSAndroid Build Coastguard Worker std::string result = "Char('" + std::string(1, fChar) + "'"; 89*c8dee2aaSAndroid Build Coastguard Worker for (int v : fNext) { 90*c8dee2aaSAndroid Build Coastguard Worker result += ", "; 91*c8dee2aaSAndroid Build Coastguard Worker result += std::to_string(v); 92*c8dee2aaSAndroid Build Coastguard Worker } 93*c8dee2aaSAndroid Build Coastguard Worker result += ")"; 94*c8dee2aaSAndroid Build Coastguard Worker return result; 95*c8dee2aaSAndroid Build Coastguard Worker } 96*c8dee2aaSAndroid Build Coastguard Worker case kDot_Kind: { 97*c8dee2aaSAndroid Build Coastguard Worker std::string result = "Dot("; 98*c8dee2aaSAndroid Build Coastguard Worker const char* separator = ""; 99*c8dee2aaSAndroid Build Coastguard Worker for (int v : fNext) { 100*c8dee2aaSAndroid Build Coastguard Worker result += separator; 101*c8dee2aaSAndroid Build Coastguard Worker result += std::to_string(v); 102*c8dee2aaSAndroid Build Coastguard Worker separator = ", "; 103*c8dee2aaSAndroid Build Coastguard Worker } 104*c8dee2aaSAndroid Build Coastguard Worker result += ")"; 105*c8dee2aaSAndroid Build Coastguard Worker return result; 106*c8dee2aaSAndroid Build Coastguard Worker } 107*c8dee2aaSAndroid Build Coastguard Worker case kRemapped_Kind: { 108*c8dee2aaSAndroid Build Coastguard Worker std::string result = "Remapped("; 109*c8dee2aaSAndroid Build Coastguard Worker const char* separator = ""; 110*c8dee2aaSAndroid Build Coastguard Worker for (int v : fData) { 111*c8dee2aaSAndroid Build Coastguard Worker result += separator; 112*c8dee2aaSAndroid Build Coastguard Worker result += std::to_string(v); 113*c8dee2aaSAndroid Build Coastguard Worker separator = ", "; 114*c8dee2aaSAndroid Build Coastguard Worker } 115*c8dee2aaSAndroid Build Coastguard Worker result += ")"; 116*c8dee2aaSAndroid Build Coastguard Worker return result; 117*c8dee2aaSAndroid Build Coastguard Worker } 118*c8dee2aaSAndroid Build Coastguard Worker case kTable_Kind: { 119*c8dee2aaSAndroid Build Coastguard Worker std::string result = std::string("Table(") + (fInverse ? "true" : "false") + ", ["; 120*c8dee2aaSAndroid Build Coastguard Worker const char* separator = ""; 121*c8dee2aaSAndroid Build Coastguard Worker for (int v : fData) { 122*c8dee2aaSAndroid Build Coastguard Worker result += separator; 123*c8dee2aaSAndroid Build Coastguard Worker result += v ? "true" : "false"; 124*c8dee2aaSAndroid Build Coastguard Worker separator = ", "; 125*c8dee2aaSAndroid Build Coastguard Worker } 126*c8dee2aaSAndroid Build Coastguard Worker result += "]"; 127*c8dee2aaSAndroid Build Coastguard Worker for (int n : fNext) { 128*c8dee2aaSAndroid Build Coastguard Worker result += ", "; 129*c8dee2aaSAndroid Build Coastguard Worker result += std::to_string(n); 130*c8dee2aaSAndroid Build Coastguard Worker } 131*c8dee2aaSAndroid Build Coastguard Worker result += ")"; 132*c8dee2aaSAndroid Build Coastguard Worker return result; 133*c8dee2aaSAndroid Build Coastguard Worker } 134*c8dee2aaSAndroid Build Coastguard Worker default: 135*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE; 136*c8dee2aaSAndroid Build Coastguard Worker } 137*c8dee2aaSAndroid Build Coastguard Worker } 138*c8dee2aaSAndroid Build Coastguard Worker #endif 139*c8dee2aaSAndroid Build Coastguard Worker 140*c8dee2aaSAndroid Build Coastguard Worker Kind fKind; 141*c8dee2aaSAndroid Build Coastguard Worker 142*c8dee2aaSAndroid Build Coastguard Worker char fChar = 0; 143*c8dee2aaSAndroid Build Coastguard Worker 144*c8dee2aaSAndroid Build Coastguard Worker bool fInverse = false; 145*c8dee2aaSAndroid Build Coastguard Worker 146*c8dee2aaSAndroid Build Coastguard Worker std::vector<int> fData; 147*c8dee2aaSAndroid Build Coastguard Worker 148*c8dee2aaSAndroid Build Coastguard Worker // states we transition to upon a succesful match from this state 149*c8dee2aaSAndroid Build Coastguard Worker std::vector<int> fNext; 150*c8dee2aaSAndroid Build Coastguard Worker }; 151*c8dee2aaSAndroid Build Coastguard Worker 152*c8dee2aaSAndroid Build Coastguard Worker #endif 153