singledocparser.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <sstream>
  4. #include "collectionstack.h" // IWYU pragma: keep
  5. #include "scanner.h"
  6. #include "singledocparser.h"
  7. #include "tag.h"
  8. #include "token.h"
  9. #include "yaml-cpp/emitterstyle.h"
  10. #include "yaml-cpp/eventhandler.h"
  11. #include "yaml-cpp/exceptions.h" // IWYU pragma: keep
  12. #include "yaml-cpp/mark.h"
  13. #include "yaml-cpp/null.h"
  14. namespace YAML {
  15. SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
  16. : m_scanner(scanner),
  17. m_directives(directives),
  18. m_pCollectionStack(new CollectionStack),
  19. m_curAnchor(0) {}
  20. SingleDocParser::~SingleDocParser() {}
  21. // HandleDocument
  22. // . Handles the next document
  23. // . Throws a ParserException on error.
  24. void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
  25. assert(!m_scanner.empty()); // guaranteed that there are tokens
  26. assert(!m_curAnchor);
  27. eventHandler.OnDocumentStart(m_scanner.peek().mark);
  28. // eat doc start
  29. if (m_scanner.peek().type == Token::DOC_START)
  30. m_scanner.pop();
  31. // recurse!
  32. HandleNode(eventHandler);
  33. eventHandler.OnDocumentEnd();
  34. // and finally eat any doc ends we see
  35. while (!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
  36. m_scanner.pop();
  37. }
  38. void SingleDocParser::HandleNode(EventHandler& eventHandler) {
  39. // an empty node *is* a possibility
  40. if (m_scanner.empty()) {
  41. eventHandler.OnNull(m_scanner.mark(), NullAnchor);
  42. return;
  43. }
  44. // save location
  45. Mark mark = m_scanner.peek().mark;
  46. // special case: a value node by itself must be a map, with no header
  47. if (m_scanner.peek().type == Token::VALUE) {
  48. eventHandler.OnMapStart(mark, "?", NullAnchor, EmitterStyle::Default);
  49. HandleMap(eventHandler);
  50. eventHandler.OnMapEnd();
  51. return;
  52. }
  53. // special case: an alias node
  54. if (m_scanner.peek().type == Token::ALIAS) {
  55. eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
  56. m_scanner.pop();
  57. return;
  58. }
  59. std::string tag;
  60. anchor_t anchor;
  61. ParseProperties(tag, anchor);
  62. const Token& token = m_scanner.peek();
  63. if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
  64. eventHandler.OnNull(mark, anchor);
  65. m_scanner.pop();
  66. return;
  67. }
  68. // add non-specific tags
  69. if (tag.empty())
  70. tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
  71. // now split based on what kind of node we should be
  72. switch (token.type) {
  73. case Token::PLAIN_SCALAR:
  74. case Token::NON_PLAIN_SCALAR:
  75. eventHandler.OnScalar(mark, tag, anchor, token.value);
  76. m_scanner.pop();
  77. return;
  78. case Token::FLOW_SEQ_START:
  79. eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Flow);
  80. HandleSequence(eventHandler);
  81. eventHandler.OnSequenceEnd();
  82. return;
  83. case Token::BLOCK_SEQ_START:
  84. eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Block);
  85. HandleSequence(eventHandler);
  86. eventHandler.OnSequenceEnd();
  87. return;
  88. case Token::FLOW_MAP_START:
  89. eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
  90. HandleMap(eventHandler);
  91. eventHandler.OnMapEnd();
  92. return;
  93. case Token::BLOCK_MAP_START:
  94. eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Block);
  95. HandleMap(eventHandler);
  96. eventHandler.OnMapEnd();
  97. return;
  98. case Token::KEY:
  99. // compact maps can only go in a flow sequence
  100. if (m_pCollectionStack->GetCurCollectionType() ==
  101. CollectionType::FlowSeq) {
  102. eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
  103. HandleMap(eventHandler);
  104. eventHandler.OnMapEnd();
  105. return;
  106. }
  107. break;
  108. default:
  109. break;
  110. }
  111. if (tag == "?")
  112. eventHandler.OnNull(mark, anchor);
  113. else
  114. eventHandler.OnScalar(mark, tag, anchor, "");
  115. }
  116. void SingleDocParser::HandleSequence(EventHandler& eventHandler) {
  117. // split based on start token
  118. switch (m_scanner.peek().type) {
  119. case Token::BLOCK_SEQ_START:
  120. HandleBlockSequence(eventHandler);
  121. break;
  122. case Token::FLOW_SEQ_START:
  123. HandleFlowSequence(eventHandler);
  124. break;
  125. default:
  126. break;
  127. }
  128. }
  129. void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
  130. // eat start token
  131. m_scanner.pop();
  132. m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
  133. while (1) {
  134. if (m_scanner.empty())
  135. throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
  136. Token token = m_scanner.peek();
  137. if (token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
  138. throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
  139. m_scanner.pop();
  140. if (token.type == Token::BLOCK_SEQ_END)
  141. break;
  142. // check for null
  143. if (!m_scanner.empty()) {
  144. const Token& token_ = m_scanner.peek();
  145. if (token_.type == Token::BLOCK_ENTRY ||
  146. token_.type == Token::BLOCK_SEQ_END) {
  147. eventHandler.OnNull(token_.mark, NullAnchor);
  148. continue;
  149. }
  150. }
  151. HandleNode(eventHandler);
  152. }
  153. m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
  154. }
  155. void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
  156. // eat start token
  157. m_scanner.pop();
  158. m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
  159. while (1) {
  160. if (m_scanner.empty())
  161. throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
  162. // first check for end
  163. if (m_scanner.peek().type == Token::FLOW_SEQ_END) {
  164. m_scanner.pop();
  165. break;
  166. }
  167. // then read the node
  168. HandleNode(eventHandler);
  169. if (m_scanner.empty())
  170. throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
  171. // now eat the separator (or could be a sequence end, which we ignore - but
  172. // if it's neither, then it's a bad node)
  173. Token& token = m_scanner.peek();
  174. if (token.type == Token::FLOW_ENTRY)
  175. m_scanner.pop();
  176. else if (token.type != Token::FLOW_SEQ_END)
  177. throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
  178. }
  179. m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
  180. }
  181. void SingleDocParser::HandleMap(EventHandler& eventHandler) {
  182. // split based on start token
  183. switch (m_scanner.peek().type) {
  184. case Token::BLOCK_MAP_START:
  185. HandleBlockMap(eventHandler);
  186. break;
  187. case Token::FLOW_MAP_START:
  188. HandleFlowMap(eventHandler);
  189. break;
  190. case Token::KEY:
  191. HandleCompactMap(eventHandler);
  192. break;
  193. case Token::VALUE:
  194. HandleCompactMapWithNoKey(eventHandler);
  195. break;
  196. default:
  197. break;
  198. }
  199. }
  200. void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
  201. // eat start token
  202. m_scanner.pop();
  203. m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
  204. while (1) {
  205. if (m_scanner.empty())
  206. throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
  207. Token token = m_scanner.peek();
  208. if (token.type != Token::KEY && token.type != Token::VALUE &&
  209. token.type != Token::BLOCK_MAP_END)
  210. throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
  211. if (token.type == Token::BLOCK_MAP_END) {
  212. m_scanner.pop();
  213. break;
  214. }
  215. // grab key (if non-null)
  216. if (token.type == Token::KEY) {
  217. m_scanner.pop();
  218. HandleNode(eventHandler);
  219. } else {
  220. eventHandler.OnNull(token.mark, NullAnchor);
  221. }
  222. // now grab value (optional)
  223. if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
  224. m_scanner.pop();
  225. HandleNode(eventHandler);
  226. } else {
  227. eventHandler.OnNull(token.mark, NullAnchor);
  228. }
  229. }
  230. m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
  231. }
  232. void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
  233. // eat start token
  234. m_scanner.pop();
  235. m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
  236. while (1) {
  237. if (m_scanner.empty())
  238. throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
  239. Token& token = m_scanner.peek();
  240. const Mark mark = token.mark;
  241. // first check for end
  242. if (token.type == Token::FLOW_MAP_END) {
  243. m_scanner.pop();
  244. break;
  245. }
  246. // grab key (if non-null)
  247. if (token.type == Token::KEY) {
  248. m_scanner.pop();
  249. HandleNode(eventHandler);
  250. } else {
  251. eventHandler.OnNull(mark, NullAnchor);
  252. }
  253. // now grab value (optional)
  254. if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
  255. m_scanner.pop();
  256. HandleNode(eventHandler);
  257. } else {
  258. eventHandler.OnNull(mark, NullAnchor);
  259. }
  260. if (m_scanner.empty())
  261. throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
  262. // now eat the separator (or could be a map end, which we ignore - but if
  263. // it's neither, then it's a bad node)
  264. Token& nextToken = m_scanner.peek();
  265. if (nextToken.type == Token::FLOW_ENTRY)
  266. m_scanner.pop();
  267. else if (nextToken.type != Token::FLOW_MAP_END)
  268. throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
  269. }
  270. m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
  271. }
  272. // . Single "key: value" pair in a flow sequence
  273. void SingleDocParser::HandleCompactMap(EventHandler& eventHandler) {
  274. m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
  275. // grab key
  276. Mark mark = m_scanner.peek().mark;
  277. m_scanner.pop();
  278. HandleNode(eventHandler);
  279. // now grab value (optional)
  280. if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
  281. m_scanner.pop();
  282. HandleNode(eventHandler);
  283. } else {
  284. eventHandler.OnNull(mark, NullAnchor);
  285. }
  286. m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
  287. }
  288. // . Single ": value" pair in a flow sequence
  289. void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) {
  290. m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
  291. // null key
  292. eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);
  293. // grab value
  294. m_scanner.pop();
  295. HandleNode(eventHandler);
  296. m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
  297. }
  298. // ParseProperties
  299. // . Grabs any tag or anchor tokens and deals with them.
  300. void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) {
  301. tag.clear();
  302. anchor = NullAnchor;
  303. while (1) {
  304. if (m_scanner.empty())
  305. return;
  306. switch (m_scanner.peek().type) {
  307. case Token::TAG:
  308. ParseTag(tag);
  309. break;
  310. case Token::ANCHOR:
  311. ParseAnchor(anchor);
  312. break;
  313. default:
  314. return;
  315. }
  316. }
  317. }
  318. void SingleDocParser::ParseTag(std::string& tag) {
  319. Token& token = m_scanner.peek();
  320. if (!tag.empty())
  321. throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
  322. Tag tagInfo(token);
  323. tag = tagInfo.Translate(m_directives);
  324. m_scanner.pop();
  325. }
  326. void SingleDocParser::ParseAnchor(anchor_t& anchor) {
  327. Token& token = m_scanner.peek();
  328. if (anchor)
  329. throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
  330. anchor = RegisterAnchor(token.value);
  331. m_scanner.pop();
  332. }
  333. anchor_t SingleDocParser::RegisterAnchor(const std::string& name) {
  334. if (name.empty())
  335. return NullAnchor;
  336. return m_anchors[name] = ++m_curAnchor;
  337. }
  338. anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
  339. const std::string& name) const {
  340. Anchors::const_iterator it = m_anchors.find(name);
  341. if (it == m_anchors.end())
  342. throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
  343. return it->second;
  344. }
  345. }