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