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