1 #ifndef ANTLR3REWRITESTREAM_HPP 2 #define ANTLR3REWRITESTREAM_HPP 3 4 // [The "BSD licence"] 5 // Copyright (c) 2005-2009 Gokulakannan Somasundaram, ElectronDB 6 7 // 8 // All rights reserved. 9 // 10 // Redistribution and use in source and binary forms, with or without 11 // modification, are permitted provided that the following conditions 12 // are met: 13 // 1. Redistributions of source code must retain the above copyright 14 // notice, this list of conditions and the following disclaimer. 15 // 2. Redistributions in binary form must reproduce the above copyright 16 // notice, this list of conditions and the following disclaimer in the 17 // documentation and/or other materials provided with the distribution. 18 // 3. The name of the author may not be used to endorse or promote products 19 // derived from this software without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32 #include "antlr3defs.hpp" 33 34 /// A generic list of elements tracked in an alternative to be used in 35 /// a -> rewrite rule. 36 /// 37 /// In the C implementation, all tree oriented streams return a pointer to 38 /// the same type: pANTLR3_BASE_TREE. Anything that has subclassed from this 39 /// still passes this type, within which there is a super pointer, which points 40 /// to it's own data and methods. Hence we do not need to implement this as 41 /// the equivalent of an abstract class, but just fill in the appropriate interface 42 /// as usual with this model. 43 /// 44 /// Once you start next()ing, do not try to add more elements. It will 45 /// break the cursor tracking I believe. 46 /// 47 /// 48 /// \see #pANTLR3_REWRITE_RULE_NODE_STREAM 49 /// \see #pANTLR3_REWRITE_RULE_ELEMENT_STREAM 50 /// \see #pANTLR3_REWRITE_RULE_SUBTREE_STREAM 51 /// 52 /// TODO: add mechanism to detect/puke on modification after reading from stream 53 /// 54 ANTLR_BEGIN_NAMESPACE() 55 56 template<class ImplTraits, class SuperType> 57 class RewriteRuleElementStream : public ImplTraits::AllocPolicyType 58 { 59 public: 60 typedef typename ImplTraits::TreeType TreeType; 61 typedef typename ImplTraits::AllocPolicyType AllocPolicyType; 62 typedef typename ImplTraits::TreeAdaptorType TreeAdaptorType; 63 64 typedef typename ImplTraits::template RecognizerType< typename SuperType::StreamType > RecognizerType; 65 typedef typename ImplTraits::StringType StringType; 66 typedef typename SuperType::TokenType TokenType; 67 typedef typename AllocPolicyType::template VectorType< TokenType* > ElementsType; 68 69 protected: 70 /// Track single elements w/o creating a list. Upon 2nd add, alloc list 71 /// 72 TokenType* m_singleElement; 73 74 /// The list of tokens or subtrees we are tracking 75 /// 76 ElementsType m_elements; 77 78 /// The element or stream description; usually has name of the token or 79 /// rule reference that this list tracks. Can include rulename too, but 80 /// the exception would track that info. 81 /// 82 StringType m_elementDescription; 83 84 /// Pointer to the tree adaptor in use for this stream 85 /// 86 TreeAdaptorType* m_adaptor; 87 88 // Pointer to the recognizer shared state to which this stream belongs 89 // 90 RecognizerType* m_rec; 91 92 /// Cursor 0..n-1. If singleElement!=NULL, cursor is 0 until you next(), 93 /// which bumps it to 1 meaning no more elements. 94 /// 95 ANTLR_UINT32 m_cursor; 96 97 /// Once a node / subtree has been used in a stream, it must be dup'ed 98 /// from then on. Streams are reset after sub rules so that the streams 99 /// can be reused in future sub rules. So, reset must set a dirty bit. 100 /// If dirty, then next() always returns a dup. 101 /// 102 bool m_dirty; 103 104 public: 105 RewriteRuleElementStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description); 106 RewriteRuleElementStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description, TokenType* oneElement); 107 RewriteRuleElementStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description, const ElementsType& elements); 108 109 ~RewriteRuleElementStream(); 110 // Methods 111 112 /// Reset the condition of this stream so that it appears we have 113 /// not consumed any of its elements. Elements themselves are untouched. 114 /// 115 void reset(); 116 117 /// Add a new pANTLR3_BASE_TREE to this stream 118 /// 119 void add(TokenType* el); 120 121 /// Return the next element in the stream. If out of elements, throw 122 /// an exception unless size()==1. If size is 1, then return elements[0]. 123 /// 124 TokenType* next(); 125 TreeType* nextTree(); 126 TokenType* nextToken(); 127 TokenType* _next(); 128 129 /// When constructing trees, sometimes we need to dup a token or AST 130 /// subtree. Dup'ing a token means just creating another AST node 131 /// around it. For trees, you must call the adaptor.dupTree(). 132 /// 133 TokenType* dup( TokenType* el ); 134 135 /// Ensure stream emits trees; tokens must be converted to AST nodes. 136 /// AST nodes can be passed through unmolested. 137 /// 138 TreeType* toTree(TreeType* el); 139 140 /// Returns true if there is a next element available 141 /// 142 bool hasNext(); 143 144 /// Treat next element as a single node even if it's a subtree. 145 /// This is used instead of next() when the result has to be a 146 /// tree root node. Also prevents us from duplicating recently-added 147 /// children; e.g., ^(type ID)+ adds ID to type and then 2nd iteration 148 /// must dup the type node, but ID has been added. 149 /// 150 /// Referencing to a rule result twice is ok; dup entire tree as 151 /// we can't be adding trees; e.g., expr expr. 152 /// 153 TreeType* nextNode(); 154 155 /// Number of elements available in the stream 156 /// 157 ANTLR_UINT32 size(); 158 159 /// Returns the description string if there is one available (check for NULL). 160 /// 161 StringType getDescription(); 162 163 protected: 164 void init(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description); 165 }; 166 167 /// This is an implementation of a token stream, which is basically an element 168 /// stream that deals with tokens only. 169 /// 170 template<class ImplTraits> 171 class RewriteRuleTokenStream : public ImplTraits::template RewriteRuleElementStreamType< typename ImplTraits::ParserType> 172 { 173 public: 174 typedef typename ImplTraits::AllocPolicyType AllocPolicyType; 175 typedef typename ImplTraits::TreeAdaptorType TreeAdaptorType; 176 typedef typename ImplTraits::ParserType ComponentType; 177 typedef typename ComponentType::StreamType StreamType; 178 typedef typename ImplTraits::CommonTokenType TokenType; 179 typedef typename ImplTraits::TreeType TreeType; 180 typedef typename AllocPolicyType::template VectorType< TokenType* > ElementsType; 181 typedef typename ImplTraits::template RecognizerType< StreamType > RecognizerType; 182 typedef typename ImplTraits::template RewriteRuleElementStreamType< typename ImplTraits::ParserType> BaseType; 183 184 public: 185 RewriteRuleTokenStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description); 186 RewriteRuleTokenStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description, TokenType* oneElement); 187 RewriteRuleTokenStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description, const ElementsType& elements); 188 TreeType* nextNode(); 189 190 private: 191 TreeType* nextNodeToken(); 192 }; 193 194 /// This is an implementation of a subtree stream which is a set of trees 195 /// modelled as an element stream. 196 /// 197 template<class ImplTraits> 198 class RewriteRuleSubtreeStream : public ImplTraits::template RewriteRuleElementStreamType< typename ImplTraits::TreeParserType> 199 { 200 public: 201 typedef typename ImplTraits::AllocPolicyType AllocPolicyType; 202 typedef typename ImplTraits::TreeAdaptorType TreeAdaptorType; 203 typedef typename ImplTraits::TreeParserType ComponentType; 204 typedef typename ComponentType::StreamType StreamType; 205 typedef typename ImplTraits::TreeType TreeType; 206 typedef TreeType TokenType; 207 typedef typename ImplTraits::template RecognizerType< StreamType > RecognizerType; 208 typedef typename AllocPolicyType::template VectorType< TokenType* > ElementsType; 209 typedef typename ImplTraits::template RewriteRuleElementStreamType< typename ImplTraits::TreeParserType> BaseType; 210 211 public: 212 RewriteRuleSubtreeStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description); 213 RewriteRuleSubtreeStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description, TokenType* oneElement); 214 RewriteRuleSubtreeStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description, const ElementsType& elements); 215 216 TreeType* dup( TreeType* el ); 217 218 private: 219 TreeType* dupTree( TreeType* el ); 220 }; 221 222 /// This is an implementation of a node stream, which is basically an element 223 /// stream that deals with tree nodes only. 224 /// 225 template<class ImplTraits> 226 class RewriteRuleNodeStream : public ImplTraits::template RewriteRuleElementStreamType< typename ImplTraits::TreeParserType> 227 { 228 public: 229 typedef typename ImplTraits::AllocPolicyType AllocPolicyType; 230 typedef typename ImplTraits::TreeAdaptorType TreeAdaptorType; 231 typedef typename ImplTraits::TreeParserType ComponentType; 232 typedef typename ComponentType::StreamType StreamType; 233 typedef typename ImplTraits::TreeType TreeType; 234 typedef TreeType TokenType; 235 typedef typename ImplTraits::template RecognizerType< StreamType > RecognizerType; 236 typedef typename AllocPolicyType::template VectorType< TokenType* > ElementsType; 237 typedef typename ImplTraits::template RewriteRuleElementStreamType< typename ImplTraits::TreeParserType> BaseType; 238 239 public: 240 RewriteRuleNodeStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description); 241 RewriteRuleNodeStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description, TokenType* oneElement); 242 RewriteRuleNodeStream(TreeAdaptorType* adaptor, RecognizerType* rec, ANTLR_UINT8* description, const ElementsType& elements); 243 244 TreeType* toTree(TreeType* element); 245 246 private: 247 TreeType* toTreeNode(TreeType* element); 248 }; 249 250 ANTLR_END_NAMESPACE() 251 252 #include "antlr3rewritestreams.inl" 253 254 #endif 255