yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1#ifndef SLANG_CORE_TOKEN_READER_H 2#define SLANG_CORE_TOKEN_READER_H 3 4#include "slang-basic.h" 5 6namespace Slang 7{ 8namespace Misc 9{ 10 11/* NOTE! This TokenReader is NOT used by the main slang compiler !*/ 12 13enum class TokenType 14{ 15EndOfFile = -1 , 16// illegal 17Unknown , 18// identifier 19Identifier , 20// constant 21IntLiteral , 22DoubleLiteral , 23StringLiteral , 24CharLiteral , 25// operators 26Semicolon , 27Comma , 28Dot , 29LBrace , 30RBrace , 31LBracket , 32RBracket , 33LParent , 34RParent , 35OpAssign , 36OpAdd , 37OpSub , 38OpMul , 39OpDiv , 40OpMod , 41OpNot , 42OpBitNot , 43OpLsh , 44OpRsh , 45OpEql , 46OpNeq , 47OpGreater , 48OpLess , 49OpGeq , 50OpLeq , 51OpAnd , 52OpOr , 53OpBitXor , 54OpBitAnd , 55OpBitOr , 56OpInc , 57OpDec , 58OpAddAssign , 59OpSubAssign , 60OpMulAssign , 61OpDivAssign , 62OpModAssign , 63OpShlAssign , 64OpShrAssign , 65OpOrAssign , 66OpAndAssign , 67OpXorAssign , 68 69QuestionMark , 70Colon , 71RightArrow , 72At , 73Pound , 74PoundPound , 75Scope , 76}; 77 78class CodePosition 79{ 80public : 81int Line = -1 ,Col = -1 ,Pos = -1 ; 82String FileName ; 83String ToString () 84 { 85StringBuilder sb (100 ); 86sb <<FileName ; 87if (Line != -1 ) 88sb <<"(" <<Line <<")" ; 89return sb .produceString (); 90 } 91CodePosition ()= default ; 92CodePosition (int line ,int col ,int pos ,String fileName ) 93 { 94Line = line ; 95Col = col ; 96Pos = pos ; 97this -> FileName = fileName ; 98 } 99bool operator < (const CodePosition & pos )const 100 { 101return FileName < pos .FileName || (FileName == pos .FileName && Line < pos .Line )|| 102 (FileName == pos .FileName && Line == pos .Line && Col < pos .Col ); 103 } 104bool operator == (const CodePosition & pos )const 105 { 106return FileName == pos .FileName && Line == pos .Line && Col == pos .Col ; 107 } 108}; 109 110enum TokenFlag :unsigned int 111{ 112AtStartOfLine = 1 <<0 , 113AfterWhitespace = 1 <<1 , 114}; 115typedef unsigned int TokenFlags ; 116 117class Token 118{ 119public : 120TokenType Type = TokenType ::Unknown ; 121String Content ; 122CodePosition Position ; 123TokenFlags flags = 0 ; 124Token ()= default ; 125Token ( 126TokenType type , 127const String & content , 128int line , 129int col , 130int pos , 131String fileName , 132TokenFlags flags = 0 ) 133 :flags (flags ) 134 { 135Type = type ; 136Content = content ; 137Position = CodePosition (line ,col ,pos ,fileName ); 138 } 139}; 140 141class TextFormatException :public Exception 142{ 143public : 144TextFormatException (String message ) 145 :Exception (message ) 146 { 147 } 148}; 149 150class TokenReader 151{ 152private : 153bool legal ; 154List < Token > tokens ; 155int tokenPtr ; 156 157public : 158TokenReader (String text ); 159int ReadInt () 160{ 161auto token = ReadToken (); 162bool neg = false; 163if (token. Content . getUnownedSlice (). isChar ( '-' )) 164{ 165neg = true; 166token = ReadToken (); 167} 168if (token. Type == TokenType::IntLiteral) 169{ 170if (neg) 171return - stringToInt (token. Content ); 172else 173return stringToInt (token. Content ); 174} 175throw TextFormatException( "Text parsing error: int expected." ); 176} 177unsigned int ReadUInt () 178{ 179auto token = ReadToken (); 180if (token. Type == TokenType::IntLiteral) 181{ 182return stringToUInt (token. Content ); 183} 184throw TextFormatException( "Text parsing error: int expected." ); 185} 186double ReadDouble () 187{ 188auto token = ReadToken (); 189bool neg = false; 190if (token. Content . getUnownedSlice (). isChar ( '-' )) 191{ 192neg = true; 193token = ReadToken (); 194} 195if (token. Type == TokenType::DoubleLiteral || token. Type == TokenType::IntLiteral) 196{ 197if (neg) 198return - stringToDouble (token. Content ); 199else 200return stringToDouble (token. Content ); 201} 202throw TextFormatException( "Text parsing error: floating point value expected." ); 203} 204float ReadFloat () { return ( float ) ReadDouble (); } 205String ReadWord () 206{ 207auto token = ReadToken (); 208if (token. Type == TokenType::Identifier) 209{ 210return token. Content ; 211} 212throw TextFormatException( "Text parsing error: identifier expected." ); 213} 214String Read ( const char * expectedStr) 215{ 216auto token = ReadToken (); 217if (token. Content == expectedStr) 218{ 219return token. Content ; 220} 221throw TextFormatException( "Text parsing error: \'" + String (expectedStr) + "\' expected." ); 222} 223String Read ( String expectedStr) 224{ 225auto token = ReadToken (); 226if (token. Content == expectedStr) 227{ 228return token. Content ; 229} 230throw TextFormatException( "Text parsing error: \'" + expectedStr + "\' expected." ); 231} 232bool Read ( TokenType tokenType) 233{ 234if ( NextToken (). Type == tokenType) 235{ 236ReadToken (); 237return true; 238} 239throw TextFormatException( "Text parsing error: unexpected '" + NextToken (). Content + "'." ); 240} 241 242String ReadStringLiteral () 243{ 244auto token = ReadToken (); 245if (token. Type == TokenType::StringLiteral) 246{ 247return token. Content ; 248} 249throw TextFormatException( "Text parsing error: string literal expected." ); 250} 251void Back ( int count) { tokenPtr -= count; } 252Token ReadMatchingToken ( TokenType type) 253{ 254auto token = ReadToken (); 255if (token. Type != type) 256{ 257throw TextFormatException( "Text parsing error: unexpected token." ); 258} 259return token; 260} 261Token ReadToken () 262{ 263if (tokenPtr < ( int )tokens. getCount ()) 264{ 265auto & rs = tokens[tokenPtr]; 266tokenPtr ++ ; 267return rs; 268} 269throw TextFormatException( "Unexpected ending." ); 270} 271Token NextToken ( int offset = 0 ) 272{ 273if (tokenPtr + offset < ( int )tokens. getCount ()) 274return tokens[tokenPtr + offset]; 275else 276{ 277Token rs; 278rs. Type = TokenType::Unknown; 279return rs; 280} 281} 282bool LookAhead ( String token) 283{ 284if (tokenPtr < ( int )tokens. getCount ()) 285{ 286auto next = NextToken (); 287return next. Content == token; 288} 289else 290{ 291return false; 292} 293} 294bool LookAhead ( TokenType tokenType) 295{ 296if (tokenPtr < ( int )tokens. getCount ()) 297{ 298auto next = NextToken (); 299return next. Type == tokenType; 300} 301else 302{ 303return false; 304} 305} 306bool AdvanceIf ( String token) 307{ 308if ( LookAhead (token)) 309{ 310ReadToken (); 311return true; 312} 313return false; 314} 315bool AdvanceIf ( TokenType token) 316{ 317if ( LookAhead (token)) 318{ 319ReadToken (); 320return true; 321} 322return false; 323} 324bool IsEnd () { return tokenPtr == ( int )tokens. getCount (); } 325 326public : 327bool IsLegalText () { return legal; } 328}; 329 330inline List < String > Split ( String text, char c) 331{ 332List < String > result; 333StringBuilder sb; 334for ( Index i = 0 ; i < text. getLength (); i ++ ) 335{ 336if (text[i] == c) 337{ 338auto str = sb. toString (); 339if (str. getLength () != 0 ) 340result. add (str); 341sb. clear (); 342} 343else 344sb << text[i]; 345} 346auto lastStr = sb. toString (); 347if (lastStr. getLength ()) 348result. add (lastStr); 349return result; 350} 351 352} // namespace Misc 353} // namespace Slang 354 355 356#endif