1 // 2 // Copyright (C) 2016 Google, Inc. 3 // 4 // All rights reserved. 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions 8 // are met: 9 // 10 // Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // 13 // Redistributions in binary form must reproduce the above 14 // copyright notice, this list of conditions and the following 15 // disclaimer in the documentation and/or other materials provided 16 // with the distribution. 17 // 18 // Neither the name of Google, Inc., nor the names of its 19 // contributors may be used to endorse or promote products derived 20 // from this software without specific prior written permission. 21 // 22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 // POSSIBILITY OF SUCH DAMAGE. 34 // 35 36 #include "hlslTokenStream.h" 37 38 namespace glslang { 39 40 void HlslTokenStream::pushPreToken(const HlslToken& tok) 41 { 42 assert(preTokenStackSize < tokenBufferSize); 43 preTokenStack[preTokenStackSize++] = tok; 44 } 45 46 HlslToken HlslTokenStream::popPreToken() 47 { 48 assert(preTokenStackSize > 0); 49 50 return preTokenStack[--preTokenStackSize]; 51 } 52 53 void HlslTokenStream::pushTokenBuffer(const HlslToken& tok) 54 { 55 tokenBuffer[tokenBufferPos] = tok; 56 tokenBufferPos = (tokenBufferPos+1) % tokenBufferSize; 57 } 58 59 HlslToken HlslTokenStream::popTokenBuffer() 60 { 61 // Back up 62 tokenBufferPos = (tokenBufferPos+tokenBufferSize-1) % tokenBufferSize; 63 64 return tokenBuffer[tokenBufferPos]; 65 } 66 67 // 68 // Make a new source of tokens, not from the source, but from an 69 // already pre-processed token stream. 70 // 71 // This interrupts current token processing which must be restored 72 // later. Some simplifying assumptions are made (and asserted). 73 // 74 void HlslTokenStream::pushTokenStream(const TVector<HlslToken>* tokens) 75 { 76 // not yet setup to interrupt a stream that has been receded 77 // and not yet reconsumed 78 assert(preTokenStackSize == 0); 79 80 // save current state 81 currentTokenStack.push_back(token); 82 83 // set up new token stream 84 tokenStreamStack.push_back(tokens); 85 86 // start position at first token: 87 token = (*tokens)[0]; 88 tokenPosition.push_back(0); 89 } 90 91 // Undo pushTokenStream(), see above 92 void HlslTokenStream::popTokenStream() 93 { 94 tokenStreamStack.pop_back(); 95 tokenPosition.pop_back(); 96 token = currentTokenStack.back(); 97 currentTokenStack.pop_back(); 98 } 99 100 // Load 'token' with the next token in the stream of tokens. 101 void HlslTokenStream::advanceToken() 102 { 103 pushTokenBuffer(token); 104 if (preTokenStackSize > 0) 105 token = popPreToken(); 106 else { 107 if (tokenStreamStack.size() == 0) 108 scanner.tokenize(token); 109 else { 110 ++tokenPosition.back(); 111 if (tokenPosition.back() >= (int)tokenStreamStack.back()->size()) 112 token.tokenClass = EHTokNone; 113 else 114 token = (*tokenStreamStack.back())[tokenPosition.back()]; 115 } 116 } 117 } 118 119 void HlslTokenStream::recedeToken() 120 { 121 pushPreToken(token); 122 token = popTokenBuffer(); 123 } 124 125 // Return the current token class. 126 EHlslTokenClass HlslTokenStream::peek() const 127 { 128 return token.tokenClass; 129 } 130 131 // Return true, without advancing to the next token, if the current token is 132 // the expected (passed in) token class. 133 bool HlslTokenStream::peekTokenClass(EHlslTokenClass tokenClass) const 134 { 135 return peek() == tokenClass; 136 } 137 138 // Return true and advance to the next token if the current token is the 139 // expected (passed in) token class. 140 bool HlslTokenStream::acceptTokenClass(EHlslTokenClass tokenClass) 141 { 142 if (peekTokenClass(tokenClass)) { 143 advanceToken(); 144 return true; 145 } 146 147 return false; 148 } 149 150 } // end namespace glslang 151