yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1// slang-json-parser.cpp 2#include "slang-json-parser.h" 3 4#include "../core/slang-string-escape-util.h" 5#include "slang-json-diagnostics.h" 6 7/* 8https://www.json.org/json-en.html 9*/ 10 11namespace Slang 12{ 13 14SlangResult JSONParser ::_parseObject () 15{ 16 { 17const SourceLoc loc = m_lexer -> peekLoc (); 18SLANG_RETURN_ON_FAIL (m_lexer -> expect (JSONTokenType ::LBrace )); 19m_listener -> startObject (loc ); 20 } 21 22 { 23const SourceLoc loc = m_lexer -> peekLoc (); 24if (m_lexer -> advanceIf (JSONTokenType ::RBrace )) 25 { 26m_listener -> endObject (loc ); 27return SLANG_OK ; 28 } 29 } 30 31while (true) 32 { 33JSONToken keyToken ; 34SLANG_RETURN_ON_FAIL (m_lexer -> expect (JSONTokenType ::StringLiteral ,keyToken )); 35m_listener -> addQuotedKey (m_lexer -> getLexeme (keyToken ),keyToken .loc ); 36 37SLANG_RETURN_ON_FAIL (m_lexer -> expect (JSONTokenType ::Colon )); 38 39SLANG_RETURN_ON_FAIL (_parseValue ()); 40if (m_lexer -> advanceIf (JSONTokenType ::Comma )) 41 { 42continue ; 43 } 44 45break ; 46 } 47 48 { 49const SourceLoc loc = m_lexer -> peekLoc (); 50SLANG_RETURN_ON_FAIL (m_lexer -> expect (JSONTokenType ::RBrace )); 51m_listener -> endObject (loc ); 52 } 53return SLANG_OK ; 54} 55 56SlangResult JSONParser ::_parseArray () 57{ 58 { 59const SourceLoc loc = m_lexer -> peekLoc (); 60SLANG_RETURN_ON_FAIL (m_lexer -> expect (JSONTokenType ::LBracket )); 61m_listener -> startArray (loc ); 62 } 63 64 { 65const SourceLoc loc = m_lexer -> peekLoc (); 66if (m_lexer -> advanceIf (JSONTokenType ::RBracket )) 67 { 68m_listener -> endArray (loc ); 69return SLANG_OK ; 70 } 71 } 72 73while (true) 74 { 75SLANG_RETURN_ON_FAIL (_parseValue ()); 76if (m_lexer -> advanceIf (JSONTokenType ::Comma )) 77 { 78continue ; 79 } 80break ; 81 } 82 83 { 84const SourceLoc loc = m_lexer -> peekLoc (); 85SLANG_RETURN_ON_FAIL (m_lexer -> expect (JSONTokenType ::RBracket )); 86m_listener -> endArray (loc ); 87 } 88return SLANG_OK ; 89} 90 91SlangResult JSONParser ::_parseValue () 92{ 93switch (m_lexer -> peekType ()) 94 { 95case JSONTokenType ::True : 96case JSONTokenType ::False : 97case JSONTokenType ::Null : 98case JSONTokenType ::IntegerLiteral : 99case JSONTokenType ::FloatLiteral : 100case JSONTokenType ::StringLiteral : 101 { 102const JSONToken & tok = m_lexer -> peekToken (); 103m_listener -> addLexemeValue (tok .type ,m_lexer -> peekLexeme (),tok .loc ); 104m_lexer -> advance (); 105return SLANG_OK ; 106 } 107case JSONTokenType ::LBracket : 108 { 109return _parseArray (); 110 } 111case JSONTokenType ::LBrace : 112 { 113return _parseObject (); 114 } 115default : 116 { 117m_sink -> diagnose ( 118m_lexer -> peekLoc (), 119JSONDiagnostics ::unexpectedToken , 120getJSONTokenAsText (m_lexer -> peekType ())); 121return SLANG_FAIL ; 122 } 123case JSONTokenType ::Invalid : 124 { 125// It's a lex error, so just fail 126return SLANG_FAIL ; 127 } 128 } 129} 130 131SlangResult JSONParser ::parse ( 132JSONLexer * lexer , 133SourceView * sourceView , 134JSONListener * listener , 135DiagnosticSink * sink ) 136{ 137m_sourceView = sourceView ; 138m_lexer = lexer ; 139m_listener = listener ; 140m_sink = sink ; 141 142SLANG_RETURN_ON_FAIL (_parseValue ()); 143 144return m_lexer -> expect (JSONTokenType ::EndOfFile ); 145} 146 147/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 148 149JSONWriter 150 151!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 152 153Index JSONWriter ::_getLineLengthAfterIndent () 154{ 155if (m_emittedIndent < 0 ) 156 { 157return 0 ; 158 } 159 160Index lineLength = m_builder .getLength ()- m_lineStart ; 161return lineLength - m_emittedIndent * m_indentCharCount ; 162} 163 164 165void JSONWriter ::_emitIndent () 166{ 167m_builder .appendRepeatedChar (m_indentChar ,m_currentIndent * m_indentCharCount ); 168m_emittedIndent = m_currentIndent ; 169SLANG_ASSERT (m_emittedIndent >=0 ); 170} 171 172void JSONWriter ::_maybeEmitIndent () 173{ 174if (m_emittedIndent < 0 ) 175 { 176_emitIndent (); 177 } 178} 179 180void JSONWriter ::_nextLine () 181{ 182m_builder <<"\n" ; 183m_lineStart = m_builder .getLength (); 184m_lineIndex ++ ; 185m_emittedIndent = -1 ; 186} 187 188void JSONWriter ::_maybeNextLine () 189{ 190// Nothing has been emitted, because nothing has been indented, and we must indent before an 191// emit 192if (m_emittedIndent < 0 ) 193 { 194 } 195else 196 { 197_nextLine (); 198 } 199} 200 201void JSONWriter ::_handleFormat (Location loc ) 202{ 203switch (m_format ) 204 { 205case IndentationStyle ::Allman : 206 { 207if (isComma (loc )) 208 { 209_maybeNextLine (); 210 } 211else 212 { 213if (isBefore (loc )) 214 { 215_maybeNextLine (); 216if (isClose (loc )) 217 { 218_dedent (); 219 } 220 } 221else 222 { 223_maybeNextLine (); 224if (isOpen (loc )) 225 { 226_indent (); 227 } 228 } 229 } 230break ; 231 } 232case IndentationStyle ::KNR : 233 { 234if (isComma (loc )) 235 { 236if (loc == Location ::FieldComma || 237 (m_lineLengthLimit > 0 && _getLineLengthAfterIndent ()> m_lineLengthLimit )) 238 { 239_maybeNextLine (); 240 } 241 } 242else 243 { 244if (isBefore (loc )) 245 { 246if (isClose (loc )) 247 { 248_maybeNextLine (); 249_dedent (); 250 } 251 } 252else 253 { 254_maybeNextLine (); 255if (isOpen (loc )) 256 { 257_indent (); 258 } 259 } 260 } 261break ; 262 } 263 } 264} 265 266void JSONWriter ::_maybeEmitComma () 267{ 268if (m_state .m_flags & State ::Flag ::HasPrevious ) 269 { 270_maybeEmitIndent (); 271m_builder <<", " ; 272_handleFormat (Location ::Comma ); 273 } 274} 275 276void JSONWriter ::_maybeEmitFieldComma () 277{ 278if (m_state .m_flags & State ::Flag ::HasPrevious ) 279 { 280_maybeEmitIndent (); 281m_builder <<", " ; 282_handleFormat (Location ::FieldComma ); 283 } 284} 285 286void JSONWriter ::startObject (SourceLoc loc ) 287{ 288SLANG_UNUSED (loc ); 289SLANG_ASSERT (m_state .canEmitValue ()); 290 291_maybeEmitComma (); 292 293_handleFormat (Location ::BeforeOpenObject ); 294_maybeEmitIndent (); 295m_builder <<"{" ; 296_handleFormat (Location ::AfterOpenObject ); 297 298m_state .m_flags |=State ::Flag ::HasPrevious ; 299m_state .m_flags &=State ::Flag ::HasKey ; 300 301m_stack .add (m_state ); 302 303m_state .m_kind = State ::Kind ::Object ; 304m_state .m_flags = 0 ; 305} 306 307void JSONWriter ::endObject (SourceLoc loc ) 308{ 309SLANG_UNUSED (loc ); 310SLANG_ASSERT (m_state .m_kind == State ::Kind ::Object ); 311 312_handleFormat (Location ::BeforeCloseObject ); 313_maybeEmitIndent (); 314m_builder <<"}" ; 315_handleFormat (Location ::AfterCloseObject ); 316 317m_state = m_stack .getLast (); 318m_stack .removeLast (); 319 320_postValue (); 321} 322 323void JSONWriter ::startArray (SourceLoc loc ) 324{ 325SLANG_UNUSED (loc ); 326SLANG_ASSERT (m_state .canEmitValue ()); 327 328_maybeEmitComma (); 329 330_handleFormat (Location ::BeforeOpenArray ); 331_maybeEmitIndent (); 332m_builder <<"[" ; 333_handleFormat (Location ::AfterOpenArray ); 334 335m_state .m_flags |=State ::Flag ::HasPrevious ; 336m_state .m_flags &=State ::Flag ::HasKey ; 337 338m_stack .add (m_state ); 339 340m_state .m_kind = State ::Kind ::Array ; 341m_state .m_flags = 0 ; 342} 343 344void JSONWriter ::endArray (SourceLoc loc ) 345{ 346SLANG_UNUSED (loc ); 347SLANG_ASSERT (m_state .m_kind == State ::Kind ::Array ); 348 349_handleFormat (Location ::BeforeCloseArray ); 350_maybeEmitIndent (); 351m_builder <<"]" ; 352_handleFormat (Location ::AfterCloseArray ); 353 354m_state = m_stack .getLast (); 355m_stack .removeLast (); 356 357_postValue (); 358} 359 360void JSONWriter ::addUnquotedKey (const UnownedStringSlice & key ,SourceLoc loc ) 361{ 362SLANG_UNUSED (loc ); 363SLANG_ASSERT ( 364m_state .m_kind == State ::Kind ::Object && (m_state .m_flags & State ::Flag ::HasKey )== 0 ); 365 366_maybeEmitFieldComma (); 367_maybeEmitIndent (); 368 369// Output the key quoted 370StringEscapeHandler * handler = StringEscapeUtil ::getHandler (StringEscapeUtil ::Style ::JSON ); 371StringEscapeUtil ::appendQuoted (handler ,key ,m_builder ); 372 373m_builder <<" : " ; 374 375m_state .m_flags |=State ::Flag ::HasKey ; 376// We don't want it to emit a , after the : 377m_state .m_flags &= ~State ::Flag ::HasPrevious ; 378} 379 380void JSONWriter ::addQuotedKey (const UnownedStringSlice & key ,SourceLoc loc ) 381{ 382SLANG_UNUSED (loc ); 383SLANG_ASSERT ( 384m_state .m_kind == State ::Kind ::Object && (m_state .m_flags & State ::Flag ::HasKey )== 0 ); 385 386// It should be quoted 387SLANG_ASSERT (key .getLength () >=2 && key [0 ]== '"' && key [key .getLength ()- 1 ]== '"' ); 388 389_maybeEmitFieldComma (); 390_maybeEmitIndent (); 391 392m_builder <<key ; 393 394m_builder <<" : " ; 395 396m_state .m_flags |=State ::Flag ::HasKey ; 397// We don't want it to emit a , after the : 398m_state .m_flags &= ~State ::Flag ::HasPrevious ; 399} 400 401void JSONWriter ::_preValue (SourceLoc loc ) 402{ 403SLANG_UNUSED (loc ); 404SLANG_ASSERT (m_state .canEmitValue ()); 405 406_maybeEmitComma (); 407_maybeEmitIndent (); 408} 409 410void JSONWriter ::_postValue () 411{ 412// We have a previous 413m_state .m_flags |=State ::Flag ::HasPrevious ; 414// We don't have a key 415m_state .m_flags &= ~State ::Flag ::HasKey ; 416} 417 418 419void JSONWriter ::addLexemeValue (JSONTokenType type ,const UnownedStringSlice & value ,SourceLoc loc ) 420{ 421_preValue (loc ); 422 423switch (type ) 424 { 425case JSONTokenType ::IntegerLiteral : 426case JSONTokenType ::FloatLiteral : 427case JSONTokenType ::StringLiteral : 428 { 429m_builder <<value ; 430break ; 431 } 432case JSONTokenType ::True : 433 { 434m_builder <<UnownedStringSlice ::fromLiteral ("true" ); 435break ; 436 } 437case JSONTokenType ::False : 438 { 439m_builder <<UnownedStringSlice ::fromLiteral ("false" ); 440break ; 441 } 442case JSONTokenType ::Null : 443 { 444m_builder <<UnownedStringSlice ::fromLiteral ("null" ); 445break ; 446 } 447default : 448 { 449SLANG_ASSERT (!"Can only emit values" ); 450 } 451 } 452 453_postValue (); 454} 455 456void JSONWriter ::addIntegerValue (int64_t value ,SourceLoc loc ) 457{ 458_preValue (loc ); 459m_builder <<value ; 460_postValue (); 461} 462 463void JSONWriter ::addFloatValue (double value ,SourceLoc loc ) 464{ 465_preValue (loc ); 466m_builder <<value ; 467_postValue (); 468} 469 470void JSONWriter ::addBoolValue (bool inValue ,SourceLoc loc ) 471{ 472_preValue (loc ); 473const UnownedStringSlice slice = inValue ?UnownedStringSlice ::fromLiteral ("true" ) 474 :UnownedStringSlice ::fromLiteral ("false" ); 475m_builder <<slice ; 476_postValue (); 477} 478 479void JSONWriter ::addNullValue (SourceLoc loc ) 480{ 481_preValue (loc ); 482m_builder <<UnownedStringSlice ::fromLiteral ("null" ); 483_postValue (); 484} 485 486void JSONWriter ::addStringValue (const UnownedStringSlice & slice ,SourceLoc loc ) 487{ 488_preValue (loc ); 489StringEscapeHandler * handler = StringEscapeUtil ::getHandler (StringEscapeUtil ::Style ::JSON ); 490StringEscapeUtil ::appendQuoted (handler ,slice ,m_builder ); 491_postValue (); 492} 493 494}// namespace Slang