1 // Copyright Contributors to the Open Shading Language project. 2 // SPDX-License-Identifier: BSD-3-Clause 3 // https://github.com/AcademySoftwareFoundation/OpenShadingLanguage 4 5 #pragma once 6 7 #include "automata.h" 8 9 OSL_NAMESPACE_ENTER 10 11 12 namespace lpexp { 13 14 // This is just a pair of states, see the use of the function genAuto in LPexp 15 // for a justification of this type that we use throughout all the regexp code 16 typedef std::pair<NdfAutomata::State *, NdfAutomata::State *> FirstLast; 17 18 /// LPexp atom type for the getType method 19 typedef enum { 20 CAT, 21 OR, 22 SYMBOL, 23 WILDCARD, 24 REPEAT, 25 NREPEAT 26 }Regtype; 27 28 29 30 /// Base class for a light path expression 31 // 32 /// Light path expressions are arranged as an abstract syntax tree. All the 33 /// nodes in that tree satisfy this interface that basically makes the automate 34 /// generation easy and clear. 35 /// 36 /// The node types for this tree are: 37 /// CAT: Concatenation of regexps like abcde or (abcde) 38 /// OR: Ored union of two or more expressions like a|b|c|d 39 /// SYMBOL Just a symbol like G or 'customlabel' 40 /// WILDCARD The wildcard regexp for . or [^GS] 41 /// REPEAT Generic unlimited repetition of the child expression (exp)* 42 /// NREPEAT Bounded repetition of the child expression like (exp){n,m} 43 /// 44 class LPexp { 45 public: ~LPexp()46 virtual ~LPexp() {}; 47 48 /// Generate automata states for this subtree 49 /// 50 /// This method recursively builds all the needed automata states of 51 /// the tree rooted by this node and returns the begin and end states 52 /// for it. That means that if it were the only thing in the automata, 53 /// making retvalue.first initial state and retvalue.second final state, 54 /// would be the right thing to do. 55 /// 56 virtual FirstLast genAuto(NdfAutomata &automata)const = 0; 57 /// Get the type for this node 58 virtual Regtype getType()const = 0; 59 /// For the parser's convenience. It is easy to implement things like a+ 60 /// as aa*. So the amount of regexp classes gets reduced. For doing that 61 /// it needs an abstract clone function 62 virtual LPexp * clone()const = 0; 63 }; 64 65 66 67 /// LPexp concatenation 68 class Cat final : public LPexp { 69 public: 70 virtual ~Cat(); 71 void append(LPexp *regexp); 72 virtual FirstLast genAuto(NdfAutomata &automata)const; getType()73 virtual Regtype getType()const { return CAT; }; 74 virtual LPexp * clone()const; 75 76 protected: 77 std::list<LPexp *> m_children; 78 }; 79 80 81 82 /// Basic symbol like G or 'customlabel' 83 class Symbol final : public LPexp { 84 public: Symbol(ustring sym)85 Symbol(ustring sym) { m_sym = sym; }; ~Symbol()86 virtual ~Symbol() {}; 87 88 virtual FirstLast genAuto(NdfAutomata &automata)const; getType()89 virtual Regtype getType()const { return SYMBOL; }; clone()90 virtual LPexp * clone()const { return new Symbol(*this); }; 91 92 protected: 93 // All symbols are unique ustrings 94 ustring m_sym; 95 }; 96 97 98 99 /// Wildcard regexp 100 /// 101 /// Named like this to avoid confusion with the automata Wildcard class 102 class Wildexp final : public LPexp { 103 public: Wildexp(SymbolSet & minus)104 Wildexp(SymbolSet &minus):m_wildcard(minus) {}; ~Wildexp()105 virtual ~Wildexp() {}; 106 107 virtual FirstLast genAuto(NdfAutomata &automata)const; getType()108 virtual Regtype getType()const { return WILDCARD; }; clone()109 virtual LPexp * clone()const { return new Wildexp(*this); }; 110 111 protected: 112 // And internally we use the automata's Wildcard type 113 Wildcard m_wildcard; 114 }; 115 116 117 118 /// Ored list of expressions 119 class Orlist final : public LPexp { 120 public: 121 virtual ~Orlist(); 122 void append(LPexp *regexp); 123 virtual FirstLast genAuto(NdfAutomata &automata)const; getType()124 virtual Regtype getType()const { return OR; }; 125 virtual LPexp * clone()const; 126 127 protected: 128 std::list<LPexp *> m_children; 129 }; 130 131 132 133 // Unlimited repeat: (exp)* 134 class Repeat final : public LPexp { 135 public: Repeat(LPexp * child)136 Repeat(LPexp *child):m_child(child) {}; ~Repeat()137 virtual ~Repeat() { delete m_child; }; 138 virtual FirstLast genAuto(NdfAutomata &automata)const; getType()139 virtual Regtype getType()const { return REPEAT; }; clone()140 virtual LPexp * clone()const { return new Repeat(m_child->clone()); }; 141 142 protected: 143 LPexp *m_child; 144 }; 145 146 147 148 // Bounded repeat: (exp){m,n} 149 class NRepeat final : public LPexp { 150 public: NRepeat(LPexp * child,int min,int max)151 NRepeat(LPexp *child, int min, int max):m_child(child),m_min(min),m_max(max) {}; ~NRepeat()152 virtual ~NRepeat() { delete m_child; }; 153 virtual FirstLast genAuto(NdfAutomata &automata)const; getType()154 virtual Regtype getType()const { return NREPEAT; }; clone()155 virtual LPexp * clone()const { return new NRepeat(m_child->clone(), m_min, m_max); }; 156 157 protected: 158 LPexp *m_child; 159 int m_min, m_max; 160 }; 161 162 163 164 /// Toplevel rule definition 165 /// 166 /// Note that although it has almost the same interface, this is not 167 /// a LPexp. It actually binds a light path expression to a certain rule. 168 /// Making the begin state initial and the end state final. It can't be 169 /// nested in other light path expressions, it is the root of the tree. 170 class Rule 171 { 172 public: Rule(LPexp * child,void * rule)173 Rule(LPexp *child, void *rule):m_child(child), m_rule(rule) {}; ~Rule()174 virtual ~Rule() { delete m_child; }; 175 void genAuto(NdfAutomata &automata)const; 176 177 protected: 178 LPexp *m_child; 179 // Anonymous pointer to the associated object for this rule 180 void *m_rule; 181 }; 182 183 } // namespace regexp 184 185 OSL_NAMESPACE_EXIT 186