simplekey.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "scanner.h"
  2. #include "token.h"
  3. namespace YAML {
  4. struct Mark;
  5. Scanner::SimpleKey::SimpleKey(const Mark& mark_, std::size_t flowLevel_)
  6. : mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0) {}
  7. void Scanner::SimpleKey::Validate() {
  8. // Note: pIndent will *not* be garbage here;
  9. // we "garbage collect" them so we can
  10. // always refer to them
  11. if (pIndent)
  12. pIndent->status = IndentMarker::VALID;
  13. if (pMapStart)
  14. pMapStart->status = Token::VALID;
  15. if (pKey)
  16. pKey->status = Token::VALID;
  17. }
  18. void Scanner::SimpleKey::Invalidate() {
  19. if (pIndent)
  20. pIndent->status = IndentMarker::INVALID;
  21. if (pMapStart)
  22. pMapStart->status = Token::INVALID;
  23. if (pKey)
  24. pKey->status = Token::INVALID;
  25. }
  26. // CanInsertPotentialSimpleKey
  27. bool Scanner::CanInsertPotentialSimpleKey() const {
  28. if (!m_simpleKeyAllowed)
  29. return false;
  30. return !ExistsActiveSimpleKey();
  31. }
  32. // ExistsActiveSimpleKey
  33. // . Returns true if there's a potential simple key at our flow level
  34. // (there's allowed at most one per flow level, i.e., at the start of the flow
  35. // start token)
  36. bool Scanner::ExistsActiveSimpleKey() const {
  37. if (m_simpleKeys.empty())
  38. return false;
  39. const SimpleKey& key = m_simpleKeys.top();
  40. return key.flowLevel == GetFlowLevel();
  41. }
  42. // InsertPotentialSimpleKey
  43. // . If we can, add a potential simple key to the queue,
  44. // and save it on a stack.
  45. void Scanner::InsertPotentialSimpleKey() {
  46. if (!CanInsertPotentialSimpleKey())
  47. return;
  48. SimpleKey key(INPUT.mark(), GetFlowLevel());
  49. // first add a map start, if necessary
  50. if (InBlockContext()) {
  51. key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
  52. if (key.pIndent) {
  53. key.pIndent->status = IndentMarker::UNKNOWN;
  54. key.pMapStart = key.pIndent->pStartToken;
  55. key.pMapStart->status = Token::UNVERIFIED;
  56. }
  57. }
  58. // then add the (now unverified) key
  59. m_tokens.push(Token(Token::KEY, INPUT.mark()));
  60. key.pKey = &m_tokens.back();
  61. key.pKey->status = Token::UNVERIFIED;
  62. m_simpleKeys.push(key);
  63. }
  64. // InvalidateSimpleKey
  65. // . Automatically invalidate the simple key in our flow level
  66. void Scanner::InvalidateSimpleKey() {
  67. if (m_simpleKeys.empty())
  68. return;
  69. // grab top key
  70. SimpleKey& key = m_simpleKeys.top();
  71. if (key.flowLevel != GetFlowLevel())
  72. return;
  73. key.Invalidate();
  74. m_simpleKeys.pop();
  75. }
  76. // VerifySimpleKey
  77. // . Determines whether the latest simple key to be added is valid,
  78. // and if so, makes it valid.
  79. bool Scanner::VerifySimpleKey() {
  80. if (m_simpleKeys.empty())
  81. return false;
  82. // grab top key
  83. SimpleKey key = m_simpleKeys.top();
  84. // only validate if we're in the correct flow level
  85. if (key.flowLevel != GetFlowLevel())
  86. return false;
  87. m_simpleKeys.pop();
  88. bool isValid = true;
  89. // needs to be less than 1024 characters and inline
  90. if (INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024)
  91. isValid = false;
  92. // invalidate key
  93. if (isValid)
  94. key.Validate();
  95. else
  96. key.Invalidate();
  97. return isValid;
  98. }
  99. void Scanner::PopAllSimpleKeys() {
  100. while (!m_simpleKeys.empty())
  101. m_simpleKeys.pop();
  102. }
  103. }