You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
3.1 KiB

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