Compare commits

..

223 Commits

Author SHA1 Message Date
Jesse Beder 326899815f Added overloads for parsing stl maps and vectors 2010-03-15 04:25:17 +00:00
Jesse Beder 083a97b171 Set alias nodes to return the tag of their anchor 2010-03-15 04:10:36 +00:00
Jesse Beder 2226987442 Disabled those warnings in the release version of the .svn too. 2010-03-03 05:33:07 +00:00
Jesse Beder bca7737463 Updated to remove most of the warnings in Visual Studio. (There's still the one about all control paths returning a value left.) Fixed one warning (when an istream converts to void * to then convert to bool), and disabled three. 2010-03-03 05:30:06 +00:00
Jesse Beder 6f40b09525 Added newline to install and license files 2009-12-21 20:35:27 +00:00
Jesse Beder 3a755de572 Added missing include 2009-12-02 05:59:18 +00:00
Jesse Beder 9718e58120 Added test for duplicate key 2009-12-02 01:29:16 +00:00
Jesse Beder 8723b8f358 Fixed leak when adding duplicate keys (and actually changed the behavior - now we take the first instance, not the last) 2009-12-02 01:01:45 +00:00
Jesse Beder 03df73a7b0 Refactored emitter operator << overloads to not template them, so it's easier to overload for pointer types 2009-11-17 20:21:22 +00:00
Jesse Beder 3307f0941c Refactored the traits a bit, and added displaying the key to string and numeric key not found errors 2009-11-12 17:00:12 +00:00
Jesse Beder 54b68230ae Small bug from switching static initialized regexes to lazy ones 2009-11-12 05:45:47 +00:00
Jesse Beder 32491166ac Replaced conversion macros with SFINAE 2009-11-10 21:23:52 +00:00
Jesse Beder 6f94f954bb Overloaded more integral types for emitting 2009-11-06 03:24:12 +00:00
Jesse Beder 90fd24d149 Fixed the return value of the integral conversion functions, and also unset the dec flag so it reads other bases (just a temporary fix, since we're officially supposed to read binary too) 2009-11-06 03:13:54 +00:00
Jesse Beder 9a21a3ec8d Switched the Exp:: regexes to functions that lazily evaluate their regexes 2009-11-04 22:56:59 +00:00
Jesse Beder 3779e4255d Fixed silly bug in node cloning 2009-10-30 20:29:14 +00:00
Jesse Beder ec62dc547e Added some block scalar tests (with errors) 2009-10-30 18:16:26 +00:00
Jesse Beder a9b9e1ccec Updated the Visual Studio solution for the new files/renaming. 2009-10-30 04:52:13 +00:00
Jesse Beder e04be7890a Fixed bug with block maps with null value (the next key was being read as the value) 2009-10-30 01:06:19 +00:00
Jesse Beder ecb30132e9 Fixed the whitespace tracking when we escape a newline in a double-quoted string 2009-10-29 22:55:50 +00:00
Jesse Beder 52be1ccfb9 Fixed mistake in test 2009-10-29 22:39:53 +00:00
Jesse Beder 3405a6fe01 Refactored the compact map notation, which made it easy to implement explicit keys for compact maps 2009-10-29 22:09:50 +00:00
Jesse Beder d372729b92 Added case for parsing a compact key: value pair in a flow sequence with a null key 2009-10-29 22:01:01 +00:00
Jesse Beder fadc2ad39f Implemented adjacent key:value pairs when the key is JSON-like 2009-10-29 21:05:48 +00:00
Jesse Beder a5607f82a3 Added test 2009-10-29 20:45:20 +00:00
Jesse Beder f4c683ac22 Added flow collection tests 2009-10-29 20:35:07 +00:00
Jesse Beder 8c9c9d90da Added ability to read compact maps in a flow sequence 2009-10-29 19:41:46 +00:00
Jesse Beder a372bfdc60 Merged r295:305 from the tags branch to the trunk 2009-10-29 15:48:06 +00:00
Jesse Beder fe57829aca Removed crt stuff (we can do memory leak checking in Linux easier) 2009-10-27 14:55:01 +00:00
Jesse Beder b5c53d9e3a Removed unused test yaml file 2009-10-27 14:48:01 +00:00
Jesse Beder f2a2d25ec0 Now actually removed yaml-reader 2009-10-27 14:47:08 +00:00
Jesse Beder a706ffaf62 Reverted yaml-reader name change 2009-10-27 14:45:14 +00:00
Jesse Beder 8f48e693fe Renamed yaml-reader test (try 2) 2009-10-27 14:39:48 +00:00
Jesse Beder a0bf12e7a1 Renamed yaml-reader test 2009-10-27 14:38:53 +00:00
Jesse Beder 2314c04d5d Tagged version 0.2.4 2009-10-25 20:27:31 +00:00
Jesse Beder 22410f46f5 Updated the CMake globbing so it only compiles sources starting with a lowercase letter (apparently Mac OS auto-generates files looking like ._whatever and it was trying to compile those too) 2009-10-25 18:01:48 +00:00
Jesse Beder 9559a661aa Tagged version 0.2.3 2009-10-22 21:55:44 +00:00
Jesse Beder beb524489c Small refactoring 2009-10-22 21:51:32 +00:00
Jesse Beder 4ffb93c12b Switch to flow map when emitting an empty block map 2009-10-22 14:21:12 +00:00
Jesse Beder ae06a40fe6 Switch to flow sequence when emitting an empty sequence 2009-10-22 14:17:12 +00:00
Jesse Beder 315b00065b Fixed bug in plain scalar folding 2009-10-20 14:47:16 +00:00
Jesse Beder 6f02f7556e Added a bunch of tests, simplified the testing code 2009-10-20 14:43:24 +00:00
Jesse Beder fa0af88dfe Merged r270:HEAD of the emitting-unicode branch 2009-10-19 23:31:11 +00:00
Jesse Beder bce845bb1f Fixed little bug in parser commit 2009-10-19 22:42:30 +00:00
Jesse Beder ed570b9f7c Added default constructor to Parser, and cleaned it up a bit 2009-10-19 22:40:46 +00:00
Jesse Beder 59b0e986bf Update CMakeLists.txt to append, not overwrite CMAKE_CXX_FLAGS 2009-10-19 22:32:26 +00:00
Jesse Beder cffb98d15b Patched for optional building of tests and tools 2009-10-12 05:21:00 +00:00
Jesse Beder 3e1ba0f3b4 Refactored the UTF-8 emitting 2009-10-08 21:05:56 +00:00
Jesse Beder d0b5bf4b7b Fixed the emitter unicode output 2009-10-07 06:46:05 +00:00
Jesse Beder 7db39e66b8 Updated signature of Parser::GetNextDocument (issue 45) 2009-09-29 18:25:11 +00:00
Jesse Beder 94eb7f1dbd Modified old gcc version patch so it still uses the new Node::Read in Visual Studio. Also broke up the \uNNNN characters in the spec tests into \xNN-type strings. 2009-09-16 05:31:28 +00:00
Jesse Beder 5733b77b84 Patched for gcc version <= 3.3 (just fall back to original version of Node::Read) 2009-09-16 04:01:40 +00:00
Jesse Beder 98bebfb628 Tagged version 0.2.2 2009-09-09 01:37:23 +00:00
Jesse Beder 7c4cc9bf5f Cleaned up the read template overloads (per litb's update); it seems the old version didn't compile in VS2008. Also updated the VS project files. 2009-09-08 20:57:18 +00:00
Jesse Beder fa885d1813 More tests, found bug in implicit keys in flow sequence 2009-09-08 05:35:39 +00:00
Jesse Beder da4614eb8b Fixed flow folding, and made the separation slightly cleaner (but the whole scanscalar thing could use a major refactoring) 2009-09-08 05:24:06 +00:00
Jesse Beder 4dcd222d1f Tests through 6.29, skipping directives and tags 2009-09-08 04:16:45 +00:00
Jesse Beder 7bdd31b34b (Actually) fixed the folding newline bug, but it's a bit messy, and we don't accurately make the distinction between block folding and flow folding 2009-09-07 23:29:04 +00:00
Jesse Beder a4b8521efe Fixed newlines in folded scalars bug 2009-09-07 22:48:32 +00:00
Jesse Beder 7037562998 Simplified testing output 2009-09-07 22:17:02 +00:00
Jesse Beder f3ff6ffc55 Fixed bugs with tab as non-content whitespace 2009-09-07 17:12:45 +00:00
Jesse Beder e3ff87ecde Fixed bugs in escape characters (both parsing and emitting) 2009-09-07 16:31:23 +00:00
Jesse Beder 45ac700fff Fixed error in test 2009-09-07 06:56:05 +00:00
Jesse Beder 2aab5acab4 Fixed last newline of folded scalar bug 2009-09-07 06:54:38 +00:00
Jesse Beder e9d760eea9 Fixed bug in trailing newlines of plain scalars 2009-09-07 06:42:03 +00:00
Jesse Beder d485d0a834 Added spec tests (minus tags, directives, and BOM) up through example 5.12 - this exposed an error in line folding 2009-09-07 06:35:37 +00:00
Jesse Beder 973ac4b3bd Added spec tests through example 2.13 2009-09-06 22:17:53 +00:00
Jesse Beder e91a152e06 Tagged release 0.2.1 for patch with complex keys 2009-09-06 22:02:59 +00:00
Jesse Beder 5217149ed4 Fixed bug with complex keys (and simplified the parsing for flow maps) 2009-09-06 21:52:56 +00:00
Jesse Beder e7ac6b3bf1 Refactored the operator >> and Node::Read default functions, as well as the conversion functions, to more easily read new types as keys (this uncovered an error, in example 2.11 of the spec) 2009-09-06 20:52:45 +00:00
Jesse Beder 9a1f4f9a0d Added spec tests through 2.10 2009-09-06 17:02:24 +00:00
Jesse Beder 07443495c8 Added templated casting to nodes, as well as operator == and != (for quick checks, especially to help in testing). Implemented size() on a map node to return the number of key/value pairs (as in std::map) 2009-09-06 15:54:11 +00:00
Jesse Beder 729fb4d30b Updated the CMake file for 0.2.0 release, and added install.txt 2009-09-05 23:05:39 +00:00
Jesse Beder 91163d2296 Allowed solo entries in a flow map to be read as keys with null value 2009-09-05 22:42:01 +00:00
Jesse Beder 75477ade65 Finished refactoring of simple keys so that they can refer to multiple tokens at a single level 2009-09-05 03:49:38 +00:00
Jesse Beder 0e1638d7b5 Refactored simple keys so that validating doesn't require popping indents, and so popping indents (and adding the end map) is independent of when we validate the simple key 2009-09-05 02:51:09 +00:00
Jesse Beder 19673ff01a Moved token enums into Token scope 2009-09-05 02:28:11 +00:00
Jesse Beder 1db573dd30 Started implementing spec tests 2009-09-03 14:27:03 +00:00
Jesse Beder 873ad336f8 Fixed bug with omitted keys/values in a flow map 2009-09-02 21:39:57 +00:00
Jesse Beder 0d41a7de7c Added more explicit doc indicator tests 2009-08-26 16:23:58 +00:00
Jesse Beder 1b240d3576 Fixed bug with explicit doc start introduced in last commit 2009-08-26 16:15:27 +00:00
Jesse Beder 4b6a0b382c Added CMake option to build for the iphone 2009-08-24 23:43:53 +00:00
Jesse Beder b789a1c5f9 Removed the implicit sequence code (since it's not used any more) 2009-08-24 22:58:47 +00:00
Jesse Beder a1460169e6 Fixed bug in anchors with no content. This involved refactoring the 'implicit sequence' concept (where a map and a sequence start on the same indent, but we read the sequence as more indented since the '-' is visually an indent). 2009-08-24 22:56:54 +00:00
Jesse Beder abe0af76c5 Added Node::Clone function 2009-08-24 20:10:42 +00:00
Jesse Beder 8e636436f8 Cleaned up 2009-08-24 18:23:20 +00:00
Jesse Beder 8c33523b15 Removed the std::wstring conversion 2009-08-22 00:25:37 +00:00
Jesse Beder 81c2e6b6ca Converted indexing to std::size_t, and fixed the Node templated overloads to properly index any index type (determining what is an index type is a bit of a hack - it should be is_convertible<T, std::size_t> (I think), but I just explicitly wrote down a list) 2009-08-19 20:58:07 +00:00
Jesse Beder ba11f5ae15 Added 'yaml-cpp: ' to the exception messages 2009-08-19 05:09:12 +00:00
Jesse Beder d92ca21bcc Added templated Read() function that creates the output variable itself (so you don't need to have a temp variable) 2009-08-19 03:37:19 +00:00
Jesse Beder 487f381ae9 Fixed out-of-bounds memory access 2009-07-31 18:26:42 +00:00
Jesse Beder d506dae914 Added IsNull function 2009-07-31 05:07:21 +00:00
Jesse Beder 7a89920441 Fixed null key/value bug, added tests 2009-07-30 06:49:09 +00:00
Jesse Beder 382f1ba3c7 Fixed empty scalar in sequence bug 2009-07-30 05:54:40 +00:00
Jesse Beder ae41e58ca3 Added support for emitting and represeting null 2009-07-30 04:42:27 +00:00
Jesse Beder 72919adf55 Added header file inclusion guards 2009-07-29 22:27:20 +00:00
Jesse Beder 1507fcd36d Forgot to add mark.h 2009-07-27 04:14:19 +00:00
Jesse Beder b1ce042535 Collected pos, line, and column into a Mark struct 2009-07-27 02:56:18 +00:00
Jesse Beder 9b78bd459b Fixed hex output in emitter (should be always two hex chars) 2009-07-26 07:57:22 +00:00
Jesse Beder c225a55344 Fixed bug in emitting null nodes 2009-07-26 07:42:50 +00:00
Jesse Beder 555fb5c3a0 Fixed the Exception::what() function 2009-07-26 01:37:21 +00:00
Jesse Beder 2160bb2bcc Fixed bug with simple keys that are quoted scalars 2009-07-25 18:58:41 +00:00
Jesse Beder 946d3260d7 Fixed yaml-cpp.pc file (with prefix) 2009-07-25 18:03:58 +00:00
Jesse Beder 2f3821ca98 Fixed location of yaml-cpp.pc file 2009-07-24 06:18:46 +00:00
Jesse Beder 980c4cb0ce Updated visual studio project, and fixed a VS warning 2009-07-20 20:18:59 +00:00
Jesse Beder 670a3e952a Patched to read into std::wstring 2009-07-15 20:47:51 +00:00
Jesse Beder 5b7f931cd7 Cosmetic change to .pc.cmake file 2009-07-15 20:38:25 +00:00
Jesse Beder ff6e6bdfd5 Added support for pkgconfig 2009-07-15 20:37:11 +00:00
Jesse Beder a84c1af98a Added FindValue to more easily read optional keys in a map 2009-07-12 02:59:23 +00:00
Jesse Beder 3e0179fd6e Added emitting for a YAML::Node (instead of the ad-hoc std::ostream overload) so it'll actually emit valid YAML always 2009-07-10 23:39:14 +00:00
Jesse Beder 6c8600ab52 Added check for extra compiler flags if using gcc 2009-07-10 17:26:39 +00:00
Jesse Beder 174f2c1fe7 Set up the parse utility program to read from standard input if no file is specified 2009-07-10 04:25:11 +00:00
Jesse Beder 11f98f1cc6 (Finally) overrode Exception::what()\n 2009-07-10 04:17:30 +00:00
Jesse Beder 464bb70114 Applied patch to build and version a shared library 2009-07-10 03:52:05 +00:00
Jesse Beder 781fb4d093 Fixed warnings to compile on gcc with -Wall -pedantic -Wextra 2009-07-10 03:30:04 +00:00
Jesse Beder b113c37819 Clarified some copy/assignment issues with the stream/streamcharsource. 2009-07-10 03:20:16 +00:00
Jesse Beder 6f44e89b7f Updated the visual studio project with some of the utf changes 2009-07-10 03:15:08 +00:00
Jesse Beder b929eb94a0 Merged utf branch changes r178:187 into the trunk 2009-07-10 03:10:03 +00:00
Jesse Beder a7b8879494 Fixed bug that didn't allow multiple docs in a stream (using only "---") 2009-06-25 03:05:09 +00:00
Jesse Beder 81f5348ea9 Patched CMake file to allow flexibility in build (in particular to allow shared lib build) 2009-06-12 04:28:36 +00:00
Jesse Beder 620c58abec Updated the nested RegEx classes so they don't need to also take an std::string 2009-06-01 03:42:16 +00:00
Jesse Beder d2e037396e Updated yaml-reader CMake file 2009-05-31 06:39:08 +00:00
Jesse Beder 1cde7fbfc0 Switched from loading test files to testing specific parsing constructs. The tests don't fully cover the span (eventually I'll add more, maybe), but there's a bunch there.
More to the point, the yaml-reader program doesn't do any file IO, so it doesn't require a specific working directory.
2009-05-31 06:36:01 +00:00
Jesse Beder 9585797b41 Patch - added testing 2009-05-30 02:41:27 +00:00
Jesse Beder 441a230509 Set eol-style to native on all of the new files 2009-05-30 02:29:47 +00:00
Jesse Beder e06104d77c Patched - removed unnecessary CMake statements 2009-05-29 22:58:14 +00:00
Jesse Beder 67f49d96d9 Patched - install target 2009-05-29 22:55:59 +00:00
Jesse Beder 820f45b10b Patch to simplify CMakeLists.txt files 2009-05-29 22:48:25 +00:00
Jesse Beder 9a1a3974c6 Patch for gcc -Wall (order of initialization) 2009-05-29 22:36:52 +00:00
Jesse Beder e76521c0e9 Changed the way we read different types of scalars.
It's better organized now, I think - nodes only offer a single main way of getting the fundamental scalar (as a string), and now we can specialize a single template to read specific types.
2009-05-23 23:51:01 +00:00
Jesse Beder b952bc594f Updated Visual Studio project for the emitter. 2009-05-23 22:58:05 +00:00
Jesse Beder 24b0663828 Changed output library directory to /lib (in the source directory) - this makes more sense 2009-05-23 17:11:19 +00:00
Jesse Beder 5139ebf7ba Added emitter headers to yaml.h 2009-05-22 22:23:57 +00:00
Jesse Beder b51a32ae14 Replaced direct emitter writing with an accessor to a C-string 2009-05-22 22:21:01 +00:00
Jesse Beder 69ef85526a Restructured CMake file to include headers, and to be better organized 2009-05-22 22:11:21 +00:00
Jesse Beder de1c6171ee Removed excessive stderr logging 2009-05-22 21:56:45 +00:00
Jesse Beder 9245f9253a Merged emitter branch into trunk, changes r105:r151 2009-05-22 21:52:31 +00:00
Jesse Beder b3a5a519f2 Merged aliases branch into trunk, changes r100:150 2009-05-22 21:48:05 +00:00
Jesse Beder 9d0e0c6a48 Fixed several bugs from the new file i/o setup.
In particular:
1. Windows CR/LF weren't read properly (issue #11)
2. Scanning wasn't reading EOF properly
3. Documents may be empty (this was old, I think)
Also fixed some VS2008 warnings on /W4.
2009-02-07 07:57:13 +00:00
Jesse Beder f9c0725684 Switched to reading the entire file into a buffer at the start.\nThis speeds it up a TON (like 100x). 2009-02-01 20:48:43 +00:00
Jesse Beder a6d5902ebf Included <cstdio> for gcc-4.4 (issue 9) 2009-01-27 21:08:40 +00:00
Jesse Beder 2768927782 Included <cstring> for strcmp 2009-01-27 20:16:30 +00:00
Jesse Beder 5c54431b3b Applied patch for gcc -Wall 2009-01-15 17:12:13 +00:00
Jesse Beder 7214ffc107 Re-added the throw() specification to ~Exception(), and also to ~TypedKeyNotFound(); I suppose this'll fix the gcc compiler error. 2009-01-01 23:59:37 +00:00
Jesse Beder d98f9d8713 Removed throw() specifier in Exception (I don't remember putting it in). This may solve a gcc error (I haven't tested it yet) or it may break it further. 2009-01-01 20:14:32 +00:00
Jesse Beder 27bd791ea0 Added a templated derived exception to KeyNotFound so that you can figure out *which* key wasn't found. 2009-01-01 02:40:18 +00:00
Jesse Beder 5a2a317d62 Fixed tag output bug 2008-11-20 04:12:31 +00:00
Jesse Beder f8d81fff8c Replaced a pointer-centered try/catch block with std::auto_ptr 2008-11-20 03:41:40 +00:00
Jesse Beder 043bbddcf0 Added line/column data for nodes so they can give better invalid scalar exceptions. 2008-11-18 04:20:07 +00:00
Jesse Beder 9969ff512e Added line/column data for nodes so they can give better invalid scalar exceptions. 2008-11-18 04:19:50 +00:00
Jesse Beder 14cdec770c Added more natural ways to parse boolean values (based on the YAML spec).
(Thanks to Vadim Zeitlin)
2008-09-25 00:15:40 +00:00
Jesse Beder 6e4317e37c Added Read() functions for Node that return true/false, so we can easily check if a read is successful without throwing.
But we still have operator >> that throws on failure.
2008-09-24 23:29:00 +00:00
Jesse Beder 907be0660c Fixed infinite loop bug having to do with simple keys when we hit an unexpected EOF. 2008-09-24 22:45:04 +00:00
Jesse Beder 3ed09b89f8 Fixed a problem where you lose the exception type on rethrow. 2008-09-23 21:13:23 +00:00
Jesse Beder 1406b84016 Made Node non-copyable. 2008-09-19 02:44:49 +00:00
Jesse Beder c175be7d4c 2008-09-11 03:49:52 +00:00
Jesse Beder 9d403d08f0 2008-09-11 03:48:04 +00:00
Jesse Beder 45322566c7 Set the eol style to native for all files. 2008-09-03 22:20:39 +00:00
Jesse Beder a45f083e00 Fixed some gcc warnings. 2008-09-03 22:19:27 +00:00
Jesse Beder 5c0db0d21b Unified line endings. 2008-09-03 22:17:17 +00:00
Jesse Beder 80db86e771 Added the license.txt file describing the MIT license. 2008-09-03 04:37:06 +00:00
Jesse Beder b16f958660 Fixed struct vs. class disparity. 2008-08-07 03:37:16 +00:00
Jesse Beder ec2ecad197 Added CMake scripts for other platforms\nFixed some bugs that gcc complained about\nFixed CR/LF vs LF bug 2008-08-07 03:30:56 +00:00
Jesse Beder 813817f1ab 2008-07-31 19:41:11 +00:00
Jesse Beder d45bb667b6 Small changes in the iterator code.
Changed the public interface of Scanner to resemble an STL container.
2008-07-23 04:38:18 +00:00
Jesse Beder cc87c83b01 Switched the Iterator implementation to a dedicated helper class (to hide the specific implementation, since it's pretty messy and may change). 2008-07-21 02:54:39 +00:00
Jesse Beder 09d7ab365f Replaced the queue of Token pointers with values.
We were getting memory leaks (as told by the CRT detectors, which I also added), and there's really no reason (as long as we're careful) to use pointers there.
2008-07-20 05:02:01 +00:00
Jesse Beder 2eab1e025e Moved the testing source to the yaml-reader folder. 2008-07-14 05:18:25 +00:00
Jesse Beder 2e2c489e29 Set the yaml-reader project to link to the yamlcpp library. 2008-07-14 05:08:46 +00:00
Jesse Beder f3a2c8497a Added a static library project 'yamlcpp' to the solution. 2008-07-14 05:03:38 +00:00
Jesse Beder 771cc6fa25 Renamed the solution yamlcpp. 2008-07-14 04:51:47 +00:00
Jesse Beder ef630abeee 2008-07-14 04:37:58 +00:00
Jesse Beder cadc04ce47 Moved all code to src/ and include/ directories. 2008-07-14 04:33:30 +00:00
Jesse Beder 4cfa233888 Switched from moving the cursor forward (in Regex) to ignoring (this handles newlines properly).
Updated some of the character-in-scalar rules.
2008-07-10 00:23:25 +00:00
Jesse Beder 03e6b5b991 Centralized the error messages to one location. 2008-07-08 20:31:48 +00:00
Jesse Beder c0c55fe50b Removed the (unused) 'required' flag from simple keys (the parser should take care of this, not the scanner). 2008-07-08 18:34:26 +00:00
Jesse Beder a8a0fb41cb Added some exceptions for directives. 2008-07-08 06:06:24 +00:00
Jesse Beder 6c2946bf58 Combined the myriad ScannerExceptions and ParserExceptions to a single ParserException class that has a message and a line/column position in the file where the error occurred. 2008-07-08 05:48:38 +00:00
Jesse Beder 115cf601e9 Added a (recursive) ordering, so we have a canonical output that we can compare. 2008-07-06 00:06:36 +00:00
Jesse Beder 2a0ddc8cb2 Wrote some tests, but they don't work because it doesn't output maps in a canonical form. 2008-07-05 19:00:58 +00:00
Jesse Beder dacc631968 Rewrote the output so that it emits correct YAML.
Fixed a bug in the last newline of a block folded scalar.
2008-07-05 05:28:23 +00:00
Jesse Beder d98007b0be 2008-07-04 22:57:52 +00:00
Jesse Beder ed488e5197 Removed the document class (since it's really just a root node, and that's it). 2008-07-04 22:56:43 +00:00
Jesse Beder 2be40919de Specialized the overloaded [] operator for int/unsigned, and added a size() function, so that you can iterate through a sequence node like a vector. 2008-07-02 21:41:54 +00:00
Jesse Beder 2ccbfeff47 Added some parser exceptions. 2008-07-02 05:00:32 +00:00
Jesse Beder 901d16a96f Overloaded the iterator's -> operator. 2008-07-02 01:32:19 +00:00
Jesse Beder d56b54b34f Added an iterator class that can iterate through both sequence and map nodes. 2008-07-02 01:22:39 +00:00
Jesse Beder f7358701f2 Fixed opening newline bug for block scalars. 2008-07-01 06:34:55 +00:00
Jesse Beder 4c5a488f68 Tags, anchors, and aliases are all parsed now. 2008-07-01 06:28:10 +00:00
Jesse Beder 8180a85a3b Added parsing of anchors, aliases, and tags (still no semantics yet).
Fixed a silly bug in the simple key pushing (queues are FIFO!).
2008-07-01 01:17:10 +00:00
Jesse Beder 121c2e577f Finished parsing of basic data types (scalar, sequence, map). 2008-06-30 23:57:58 +00:00
Jesse Beder c1966ba3fc Renamed the stream member functions get() and eat(). 2008-06-30 22:34:10 +00:00
Jesse Beder 852e5b63e5 Instead of deriving different tokens from a base Token class, we now use an enumerated TOKEN_TYPE to distinguish types. This is so we don't have to cast all the time when parsing the resulting token stream.
Also, removed start/end stream tokens.
2008-06-30 21:47:21 +00:00
Jesse Beder b6a0ef207b Started the parser. 2008-06-30 06:51:22 +00:00
Jesse Beder ed6c294749 Added a peek token command (for the parser to use). 2008-06-30 06:21:12 +00:00
Jesse Beder 07d4cac48f Added directives and tags. 2008-06-30 04:22:41 +00:00
Jesse Beder 2b8628922f Moved the three scalar token scanning functions back to scantoken.cpp, so scanscalar.cpp now only has the main scalar scanning function.
Renamed ScanScalarInfo to ScanScalarParams.
2008-06-30 01:38:32 +00:00
Jesse Beder 0683cbf859 Mostly finished refactoring the scalar scanning. 2008-06-30 01:31:23 +00:00
Jesse Beder 5f8252ee6f Moved scalar scanning-related parameters to a struct.
Renamed the valid/possible tokens to a single variable status with enums valid, invalid, and unverified.
2008-06-29 17:39:33 +00:00
Jesse Beder ff99f85a6d Moved the input stream, together with line/column info, into its own class, which allowed some other stuff just to pass the stream, and not have to be a member of Scanner. 2008-06-29 06:32:13 +00:00
Jesse Beder 0d5a97bffe Refactored common scalar scanning code (from plain, quoted, and block) to one function. 2008-06-29 05:45:41 +00:00
Jesse Beder 6c193d6fbd Moved the scalar-related functions to their own file. 2008-06-29 03:11:25 +00:00
Jesse Beder d076252dff 2008-06-29 00:33:34 +00:00
Jesse Beder 2e27c5d9c3 Small refactoring. 2008-06-28 22:05:51 +00:00
Jesse Beder 72b443375c 2008-06-28 20:09:49 +00:00
Jesse Beder 43ea59a4ed Added folded and literal scalars. 2008-06-28 20:08:21 +00:00
Jesse Beder 01ef70a6f9 Fixed complex keys. 2008-06-28 17:32:10 +00:00
Jesse Beder c63ebbd878 Moved the simple key validation to before each token scan (plus at newlines of scalars). 2008-06-28 16:46:37 +00:00
Jesse Beder 11706abbb7 Added simple keys.
There's a bug (and question): should we test simple keys' validity BEFORE stuff or AFTER stuff?
2008-06-28 06:36:59 +00:00
Jesse Beder 49a75b2d78 Added quoted scalars (with escaping).
Refactored some common whitespace-parsing code in scanning both scalars.
Implemented the flow collection tokens.
2008-06-27 23:11:46 +00:00
Jesse Beder a224c7818b Small plain scalar scanning fixes. 2008-06-27 20:54:43 +00:00
Jesse Beder 8fca02fb2a Split off the specific regular expressions, and the specialized token-scanning functions, into their own files. 2008-06-27 19:13:03 +00:00
Jesse Beder de29068110 Added stream input to the regular expressions, greatly simplifying the usage (in particular, we no longer have to specify the number of characters to be checked). 2008-06-27 19:07:30 +00:00
Jesse Beder 4e435b1321 Wrote a simplified regular expression parser to make life easier (it only does single matches; i.e., no one-or-more matches, etc.).
Fixed some of the whitespace/line break matching.
2008-06-27 08:20:41 +00:00
Jesse Beder 873dbc2421 The plain scalar scanner is almost done (and it scans a simple list correctly).
Also messed around with multiple character peeking on the input, and got something working.
2008-06-27 00:18:52 +00:00
Jesse Beder 31f7db5a0d More simple scalar scanning. 2008-06-26 22:00:39 +00:00
Jesse Beder a3961d047f Continued working on scanner.
We're now using exceptions for errors, and scanning/pushing tokens is exception-safe (using a set of "limbo tokens").
2008-06-26 19:30:11 +00:00
Jesse Beder 8ae7b48188 Started the scanner. 2008-06-26 09:05:28 +00:00
Jesse Beder bcbca461de Beginning of first attempt to parse.
Will be completely wiped, I think, in favor of a Scanner (to tokens), then Parser mechanism.
2008-06-26 06:49:50 +00:00
Jesse Beder 4ed7f62431 Preliminary setup - basic data structures are there. 2008-06-25 23:00:18 +00:00
Jesse Beder e22eea26b1 2008-06-25 22:46:18 +00:00
Jesse Beder 110a7f06a8 2008-06-25 22:45:08 +00:00
Jesse Beder bb55b0ba91 2008-06-25 22:44:44 +00:00
50 changed files with 637 additions and 1795 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ endif(MSVC)
set(YAML_CPP_VERSION_MAJOR "0")
set(YAML_CPP_VERSION_MINOR "2")
set(YAML_CPP_VERSION_PATCH "5")
set(YAML_CPP_VERSION_PATCH "4")
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
enable_testing()
-38
View File
@@ -1,38 +0,0 @@
#pragma once
#ifndef ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "anchor.h"
#include <map>
namespace YAML
{
class Node;
class AliasManager
{
public:
AliasManager();
void RegisterReference(const Node& node);
const Node *LookupReference(const Node& node) const;
anchor_t LookupAnchor(const Node& node) const;
private:
const Node *_LookupReference(const Node& oldIdentity) const;
anchor_t _CreateNewAnchor();
private:
typedef std::map<const Node*, const Node*> NodeByNode;
NodeByNode m_newIdentityByOldIdentity;
typedef std::map<const Node*, anchor_t> AnchorByIdentity;
AnchorByIdentity m_anchorByIdentity;
anchor_t m_curAnchor;
};
}
#endif // ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <cstddef>
namespace YAML
{
typedef std::size_t anchor_t;
const anchor_t NullAnchor = 0;
}
#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-40
View File
@@ -1,40 +0,0 @@
#pragma once
#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <vector>
#include "anchor.h"
namespace YAML
{
/// AnchorDict
/// . An object that stores and retrieves values correlating to anchor_t
/// values.
/// . Efficient implementation that can make assumptions about how anchor_t
/// values are assigned by the Parser class.
template <class T>
class AnchorDict
{
public:
void Register(anchor_t anchor, T value)
{
if (anchor > m_data.size())
{
m_data.resize(anchor);
}
m_data[anchor - 1] = value;
}
T Get(anchor_t anchor) const
{
return m_data[anchor - 1];
}
private:
std::vector<T> m_data;
};
}
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-43
View File
@@ -1,43 +0,0 @@
#pragma once
#ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "eventhandler.h"
#include <stack>
namespace YAML
{
class Emitter;
class EmitFromEvents: public EventHandler
{
public:
EmitFromEvents(Emitter& emitter);
virtual void OnDocumentStart(const Mark& mark);
virtual void OnDocumentEnd();
virtual void OnNull(const std::string& tag, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnSequenceEnd();
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnMapEnd();
private:
void BeginNode();
void EmitProps(const std::string& tag, anchor_t anchor);
private:
Emitter& m_emitter;
struct State { enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue }; };
std::stack<State::value> m_stateStack;
};
}
#endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-2
View File
@@ -77,8 +77,6 @@ namespace YAML
void EmitEndMap();
void EmitKey();
void EmitValue();
void EmitKindTag();
void EmitTag(bool verbatim, const _Tag& tag);
private:
ostream m_stream;
+4 -15
View File
@@ -11,7 +11,6 @@ namespace YAML
enum EMITTER_MANIP {
// general manipulators
Auto,
TagByKind,
// output character set
EmitNonAscii,
@@ -83,24 +82,14 @@ namespace YAML
}
struct _Tag {
explicit _Tag(const std::string& content_)
: content(content_), verbatim(true)
{
}
_Tag(const std::string& content_): content(content_), verbatim(true) {}
std::string content;
bool verbatim;
};
typedef _Tag VerbatimTag;
struct LocalTag : public _Tag
{
explicit LocalTag(const std::string& content_)
: _Tag(content_)
{
verbatim = false;
}
};
inline _Tag VerbatimTag(const std::string& content) {
return _Tag(content);
}
struct _Comment {
_Comment(const std::string& content_): content(content_) {}
-34
View File
@@ -1,34 +0,0 @@
#pragma once
#ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "anchor.h"
#include <string>
namespace YAML
{
struct Mark;
class EventHandler
{
public:
virtual ~EventHandler() {}
virtual void OnDocumentStart(const Mark& mark) = 0;
virtual void OnDocumentEnd() = 0;
virtual void OnNull(const std::string& tag, anchor_t anchor) = 0;
virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0;
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) = 0;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0;
virtual void OnSequenceEnd() = 0;
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0;
virtual void OnMapEnd() = 0;
};
}
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-117
View File
@@ -1,117 +0,0 @@
#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
namespace YAML
{
struct Mark;
// GraphBuilderInterface
// . Abstraction of node creation
// . pParentNode is always NULL or the return value of one of the NewXXX()
// functions.
class GraphBuilderInterface
{
public:
// Create and return a new node with a null value.
virtual void *NewNull(const std::string& tag, void *pParentNode) = 0;
// Create and return a new node with the given tag and value.
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) = 0;
// Create and return a new sequence node
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) = 0;
// Add pNode to pSequence. pNode was created with one of the NewXxx()
// functions and pSequence with NewSequence().
virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
// Note that no moew entries will be added to pSequence
virtual void SequenceComplete(void *pSequence) {(void)pSequence;}
// Create and return a new map node
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) = 0;
// Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode
// were created with one of the NewXxx() methods and pMap with NewMap().
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
// Note that no more assignments will be made in pMap
virtual void MapComplete(void *pMap) {(void)pMap;}
// Return the node that should be used in place of an alias referencing
// pNode (pNode by default)
virtual void *AnchorReference(const Mark& mark, void *pNode) {(void)mark; return pNode;}
};
// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines
// Node, Sequence, and Map types. Sequence and Map must derive from Node
// (unless Node is defined as void). Impl must also implement function with
// all of the same names as the virtual functions in GraphBuilderInterface
// -- including the ones with default implementations -- but with the
// prototypes changed to accept an explicit Node*, Sequence*, or Map* where
// appropriate.
template <class Impl>
class GraphBuilder : public GraphBuilderInterface
{
public:
typedef typename Impl::Node Node;
typedef typename Impl::Sequence Sequence;
typedef typename Impl::Map Map;
GraphBuilder(Impl& impl) : m_impl(impl)
{
Map* pMap = NULL;
Sequence* pSeq = NULL;
Node* pNode = NULL;
// Type consistency checks
pNode = pMap;
pNode = pSeq;
}
GraphBuilderInterface& AsBuilderInterface() {return *this;}
virtual void *NewNull(const std::string& tag, void* pParentNode) {
return CheckType<Node>(m_impl.NewNull(tag, AsNode(pParentNode)));
}
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) {
return CheckType<Node>(m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
}
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) {
return CheckType<Sequence>(m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
}
virtual void AppendToSequence(void *pSequence, void *pNode) {
m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
}
virtual void SequenceComplete(void *pSequence) {
m_impl.SequenceComplete(AsSequence(pSequence));
}
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) {
return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
}
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
}
virtual void MapComplete(void *pMap) {
m_impl.MapComplete(AsMap(pMap));
}
virtual void *AnchorReference(const Mark& mark, void *pNode) {
return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
}
private:
Impl& m_impl;
// Static check for pointer to T
template <class T, class U>
static T* CheckType(U* p) {return p;}
static Node *AsNode(void *pNode) {return static_cast<Node*>(pNode);}
static Sequence *AsSequence(void *pSeq) {return static_cast<Sequence*>(pSeq);}
static Map *AsMap(void *pMap) {return static_cast<Map*>(pMap);}
};
}
#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+12 -14
View File
@@ -17,12 +17,10 @@
namespace YAML
{
class AliasManager;
class Content;
class Scanner;
class Emitter;
class EventHandler;
struct NodeProperties;
struct ParserState;
enum CONTENT_TYPE { CT_NONE, CT_SCALAR, CT_SEQUENCE, CT_MAP };
@@ -34,16 +32,7 @@ namespace YAML
void Clear();
std::auto_ptr<Node> Clone() const;
void EmitEvents(EventHandler& eventHandler) const;
void EmitEvents(AliasManager& am, EventHandler& eventHandler) const;
void Init(CONTENT_TYPE type, const Mark& mark, const std::string& tag);
void InitNull(const std::string& tag);
void InitAlias(const Mark& mark, const Node& identity);
void SetData(const std::string& data);
void Append(std::auto_ptr<Node> pNode);
void Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
void Parse(Scanner *pScanner, ParserState& state);
CONTENT_TYPE GetType() const;
@@ -108,10 +97,19 @@ namespace YAML
template <typename T>
const Node *FindValueForKey(const T& key) const;
// helper for cloning
Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent);
// helpers for parsing
void ParseHeader(Scanner *pScanner, ParserState& state);
void ParseTag(Scanner *pScanner, ParserState& state);
void ParseAnchor(Scanner *pScanner, ParserState& state);
void ParseAlias(Scanner *pScanner, ParserState& state);
private:
Mark m_mark;
std::string m_tag;
std::string m_anchor, m_tag;
Content *m_pContent;
bool m_alias;
const Node *m_pIdentity;
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#ifndef NODEPROPERTIES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEPROPERTIES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
namespace YAML
{
struct NodeProperties {
std::string tag;
std::string anchor;
};
}
#endif // NODEPROPERTIES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+8 -21
View File
@@ -4,20 +4,19 @@
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "graphbuilder.h"
#include "node.h"
#include "noncopyable.h"
#include <ios>
#include <string>
#include <vector>
#include <map>
#include <memory>
namespace YAML
{
struct Directives;
struct Mark;
struct Token;
class EventHandler;
class GraphBuilderInterface;
class Node;
class Scanner;
struct ParserState;
struct Token;
class Parser: private noncopyable
{
@@ -29,18 +28,6 @@ namespace YAML
operator bool() const;
void Load(std::istream& in);
bool HandleNextDocument(EventHandler& eventHandler);
void *BuildNextDocumentGraph(GraphBuilderInterface& graphBuilder);
template <class Builder>
typename Builder::Node *BuildNextDocumentGraph(Builder& graphBuilder)
{
GraphBuilder<Builder> wrapper(graphBuilder); // Must be lvalue to make C++ happy
return static_cast<typename Builder::Node *>(
BuildNextDocumentGraph(wrapper.AsBuilderInterface())
);
}
bool GetNextDocument(Node& document);
void PrintTokens(std::ostream& out);
@@ -49,10 +36,10 @@ namespace YAML
void HandleDirective(const Token& token);
void HandleYamlDirective(const Token& token);
void HandleTagDirective(const Token& token);
private:
std::auto_ptr<Scanner> m_pScanner;
std::auto_ptr<Directives> m_pDirectives;
std::auto_ptr<ParserState> m_pState;
};
}
+16 -6
View File
@@ -2,10 +2,25 @@
namespace YAML
{
AliasContent::AliasContent(Content* pNodeContent): m_pRef(pNodeContent)
AliasContent::AliasContent(Content* pNodeContent)
: m_pRef(pNodeContent)
{
}
Content *AliasContent::Clone() const
{
return 0; // TODO: how to clone an alias?
}
void AliasContent::Parse(Scanner * /*pScanner*/, ParserState& /*state*/)
{
}
void AliasContent::Write(Emitter&) const
{
// no content (just an alias)
}
bool AliasContent::GetBegin(std::vector <Node *>::const_iterator& i) const
{
return m_pRef->GetBegin(i);
@@ -56,11 +71,6 @@ namespace YAML
return m_pRef->GetScalar(scalar);
}
void AliasContent::EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
{
m_pRef->EmitEvents(am, eventHandler, mark, tag, anchor);
}
int AliasContent::Compare(Content *pContent)
{
return m_pRef->Compare(pContent);
+5 -1
View File
@@ -12,6 +12,11 @@ namespace YAML
{
public:
AliasContent(Content *pNodeContent);
virtual Content *Clone() const;
virtual void Parse(Scanner* pScanner, ParserState& state);
virtual void Write(Emitter&) const;
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const;
@@ -24,7 +29,6 @@ namespace YAML
virtual bool IsSequence() const;
virtual bool GetScalar(std::string& s) const;
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
virtual int Compare(Content *);
virtual int Compare(Scalar *);
-45
View File
@@ -1,45 +0,0 @@
#include "aliasmanager.h"
#include "node.h"
#include <cassert>
#include <sstream>
namespace YAML
{
AliasManager::AliasManager(): m_curAnchor(0)
{
}
void AliasManager::RegisterReference(const Node& node)
{
const Node *pIdentity = node.Identity();
m_newIdentityByOldIdentity.insert(std::make_pair(pIdentity, &node));
m_anchorByIdentity.insert(std::make_pair(&node, _CreateNewAnchor()));
}
const Node *AliasManager::LookupReference(const Node& node) const
{
const Node *pIdentity = node.Identity();
return _LookupReference(*pIdentity);
}
anchor_t AliasManager::LookupAnchor(const Node& node) const
{
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(&node);
if(it == m_anchorByIdentity.end())
assert(false); // TODO: throw
return it->second;
}
const Node *AliasManager::_LookupReference(const Node& oldIdentity) const
{
NodeByNode::const_iterator it = m_newIdentityByOldIdentity.find(&oldIdentity);
if(it == m_newIdentityByOldIdentity.end())
return 0;
return it->second;
}
anchor_t AliasManager::_CreateNewAnchor()
{
return ++m_curAnchor;
}
}
-33
View File
@@ -1,33 +0,0 @@
#pragma once
#ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <stack>
#include <cassert>
namespace YAML
{
struct CollectionType {
enum value { None, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap };
};
class CollectionStack
{
public:
CollectionType::value GetCurCollectionType() const {
if(collectionStack.empty())
return CollectionType::None;
return collectionStack.top();
}
void PushCollectionType(CollectionType::value type) { collectionStack.push(type); }
void PopCollectionType(CollectionType::value type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
private:
std::stack<CollectionType::value> collectionStack;
};
}
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-21
View File
@@ -1,21 +0,0 @@
#include "content.h"
#include "node.h"
#include <cassert>
namespace YAML
{
void Content::SetData(const std::string&)
{
assert(false); // TODO: throw
}
void Content::Append(std::auto_ptr<Node>)
{
assert(false); // TODO: throw
}
void Content::Insert(std::auto_ptr<Node>, std::auto_ptr<Node>)
{
assert(false); // TODO: throw
}
}
+12 -15
View File
@@ -4,30 +4,32 @@
#define CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "anchor.h"
#include <vector>
#include <map>
#include "parserstate.h"
#include "exceptions.h"
#include "ltnode.h"
#include <map>
#include <memory>
#include <vector>
namespace YAML
{
struct Mark;
struct NodeProperties;
class AliasManager;
class EventHandler;
class Map;
class Scanner;
class Parser;
class Node;
class Scalar;
class Scanner;
class Sequence;
class Map;
class Emitter;
class Content
{
public:
Content() {}
virtual ~Content() {}
virtual Content *Clone() const = 0;
virtual void Parse(Scanner *pScanner, ParserState& state) = 0;
virtual void Write(Emitter& out) const = 0;
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
@@ -38,11 +40,6 @@ namespace YAML
virtual bool IsScalar() const { return false; }
virtual bool IsMap() const { return false; }
virtual bool IsSequence() const { return false; }
virtual void SetData(const std::string& data);
virtual void Append(std::auto_ptr<Node> pNode);
virtual void Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const = 0;
// extraction
virtual bool GetScalar(std::string&) const { return false; }
-27
View File
@@ -1,27 +0,0 @@
#pragma once
#ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
#include <map>
namespace YAML
{
struct Version {
bool isDefault;
int major, minor;
};
struct Directives {
Directives();
const std::string TranslateTagHandle(const std::string& handle) const;
Version version;
std::map<std::string, std::string> tags;
};
}
#endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-106
View File
@@ -1,106 +0,0 @@
#include "emitfromevents.h"
#include "emitter.h"
#include "null.h"
#include <cassert>
#include <sstream>
namespace {
std::string ToString(YAML::anchor_t anchor) {
std::stringstream stream;
stream << anchor;
return stream.str();
}
}
namespace YAML
{
EmitFromEvents::EmitFromEvents(Emitter& emitter): m_emitter(emitter)
{
}
void EmitFromEvents::OnDocumentStart(const Mark&)
{
}
void EmitFromEvents::OnDocumentEnd()
{
}
void EmitFromEvents::OnNull(const std::string& tag, anchor_t anchor)
{
BeginNode();
EmitProps(tag, anchor);
if(tag.empty())
m_emitter << Null;
}
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor)
{
BeginNode();
m_emitter << Alias(ToString(anchor));
}
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << value;
}
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << BeginSeq;
m_stateStack.push(State::WaitingForSequenceEntry);
}
void EmitFromEvents::OnSequenceEnd()
{
m_emitter << EndSeq;
assert(m_stateStack.top() == State::WaitingForSequenceEntry);
m_stateStack.pop();
}
void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag, anchor_t anchor)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << BeginMap;
m_stateStack.push(State::WaitingForKey);
}
void EmitFromEvents::OnMapEnd()
{
m_emitter << EndMap;
assert(m_stateStack.top() == State::WaitingForKey);
m_stateStack.pop();
}
void EmitFromEvents::BeginNode()
{
if(m_stateStack.empty())
return;
switch(m_stateStack.top()) {
case State::WaitingForKey:
m_emitter << Key;
m_stateStack.top() = State::WaitingForValue;
break;
case State::WaitingForValue:
m_emitter << Value;
m_stateStack.top() = State::WaitingForKey;
break;
default:
break;
}
}
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor)
{
if(!tag.empty())
m_emitter << VerbatimTag(tag);
if(anchor)
m_emitter << Anchor(ToString(anchor));
}
}
+3 -17
View File
@@ -120,9 +120,6 @@ namespace YAML
case Value:
EmitValue();
break;
case TagByKind:
EmitKindTag();
break;
default:
m_pState->SetLocalValue(value);
break;
@@ -654,26 +651,15 @@ namespace YAML
if(!good())
return *this;
EmitTag(tag.verbatim, tag);
return *this;
}
void Emitter::EmitTag(bool verbatim, const _Tag& tag)
{
PreAtomicWrite();
EmitSeparationIfNecessary();
if(!Utils::WriteTag(m_stream, tag.content, verbatim)) {
if(!Utils::WriteTag(m_stream, tag.content)) {
m_pState->SetError(ErrorMsg::INVALID_TAG);
return;
return *this;
}
m_pState->RequireSeparation();
// Note: no PostAtomicWrite() because we need another value for this node
}
void Emitter::EmitKindTag()
{
_Tag tag("");
EmitTag(false, tag);
return *this;
}
Emitter& Emitter::Write(const _Comment& comment)
+4 -6
View File
@@ -294,13 +294,12 @@ namespace YAML
return WriteAliasName(out, str);
}
bool WriteTag(ostream& out, const std::string& str, bool verbatim)
bool WriteTag(ostream& out, const std::string& str)
{
out << (verbatim ? "!<" : "!");
out << "!<";
StringCharSource buffer(str.c_str(), str.size());
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
while(buffer) {
int n = reValid.Match(buffer);
int n = Exp::URI().Match(buffer);
if(n <= 0)
return false;
@@ -309,8 +308,7 @@ namespace YAML
++buffer;
}
}
if (verbatim)
out << ">";
out << ">";
return true;
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ namespace YAML
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent);
bool WriteAlias(ostream& out, const std::string& str);
bool WriteAnchor(ostream& out, const std::string& str);
bool WriteTag(ostream& out, const std::string& str, bool verbatim);
bool WriteTag(ostream& out, const std::string& str);
}
}
-96
View File
@@ -1,96 +0,0 @@
#include "graphbuilderadapter.h"
namespace YAML
{
int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
void GraphBuilderAdapter::OnNull(const std::string& tag, anchor_t anchor)
{
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewNull(tag, pParent);
RegisterAnchor(anchor, pNode);
DispositionNode(pNode);
}
void GraphBuilderAdapter::OnAlias(const Mark& mark, anchor_t anchor)
{
void *pReffedNode = m_anchors.Get(anchor);
DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
}
void GraphBuilderAdapter::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
{
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
RegisterAnchor(anchor, pNode);
DispositionNode(pNode);
}
void GraphBuilderAdapter::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode));
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnSequenceEnd()
{
void *pSequence = m_containers.top().pContainer;
m_containers.pop();
DispositionNode(pSequence);
}
void GraphBuilderAdapter::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
m_pKeyNode = NULL;
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnMapEnd()
{
void *pMap = m_containers.top().pContainer;
m_pKeyNode = m_containers.top().pPrevKeyNode;
m_containers.pop();
DispositionNode(pMap);
}
void *GraphBuilderAdapter::GetCurrentParent() const
{
if (m_containers.empty()) {
return NULL;
}
return m_containers.top().pContainer;
}
void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode)
{
if (anchor) {
m_anchors.Register(anchor, pNode);
}
}
void GraphBuilderAdapter::DispositionNode(void *pNode)
{
if (m_containers.empty()) {
m_pRootNode = pNode;
return;
}
void *pContainer = m_containers.top().pContainer;
if (m_containers.top().isMap()) {
if (m_pKeyNode) {
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
m_pKeyNode = NULL;
} else {
m_pKeyNode = pNode;
}
} else {
m_builder.AppendToSequence(pContainer, pNode);
}
}
}
-68
View File
@@ -1,68 +0,0 @@
#ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <map>
#include <stack>
#include "anchordict.h"
#include "eventhandler.h"
#include "graphbuilder.h"
namespace YAML
{
class GraphBuilderAdapter : public EventHandler
{
public:
GraphBuilderAdapter(GraphBuilderInterface& builder)
: m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL)
{
}
virtual void OnDocumentStart(const Mark& mark) {(void)mark;}
virtual void OnDocumentEnd() {}
virtual void OnNull(const std::string& tag, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnSequenceEnd();
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnMapEnd();
void *RootNode() const {return m_pRootNode;}
private:
struct ContainerFrame
{
ContainerFrame(void *pSequence)
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker)
{}
ContainerFrame(void *pMap, void* pPrevKeyNode)
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode)
{}
void *pContainer;
void *pPrevKeyNode;
bool isMap() const {return pPrevKeyNode != &sequenceMarker;}
private:
static int sequenceMarker;
};
typedef std::stack<ContainerFrame> ContainerStack;
typedef AnchorDict<void*> AnchorMap;
GraphBuilderInterface& m_builder;
ContainerStack m_containers;
AnchorMap m_anchors;
void *m_pRootNode;
void *m_pKeyNode;
void *GetCurrentParent() const;
void RegisterAnchor(anchor_t anchor, void *pNode);
void DispositionNode(void *pNode);
};
}
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+156 -9
View File
@@ -1,13 +1,24 @@
#include "map.h"
#include "node.h"
#include "eventhandler.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "emitter.h"
namespace YAML
{
Map::Map()
{
}
Map::Map(const node_map& data)
{
for(node_map::const_iterator it=data.begin();it!=data.end();++it) {
std::auto_ptr<Node> pKey = it->first->Clone();
std::auto_ptr<Node> pValue = it->second->Clone();
AddEntry(pKey, pValue);
}
}
Map::~Map()
{
@@ -23,6 +34,11 @@ namespace YAML
m_data.clear();
}
Content *Map::Clone() const
{
return new Map(m_data);
}
bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
{
it = m_data.begin();
@@ -40,7 +56,140 @@ namespace YAML
return m_data.size();
}
void Map::Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
void Map::Parse(Scanner *pScanner, ParserState& state)
{
Clear();
// split based on start token
switch(pScanner->peek().type) {
case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
case Token::KEY: ParseCompact(pScanner, state); break;
case Token::VALUE: ParseCompactWithNoKey(pScanner, state); break;
default: break;
}
}
void Map::ParseBlock(Scanner *pScanner, ParserState& state)
{
// eat start token
pScanner->pop();
state.PushCollectionType(ParserState::BLOCK_MAP);
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
Token token = pScanner->peek();
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
if(token.type == Token::BLOCK_MAP_END) {
pScanner->pop();
break;
}
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
// grab key (if non-null)
if(token.type == Token::KEY) {
pScanner->pop();
pKey->Parse(pScanner, state);
}
// now grab value (optional)
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
pScanner->pop();
pValue->Parse(pScanner, state);
}
AddEntry(pKey, pValue);
}
state.PopCollectionType(ParserState::BLOCK_MAP);
}
void Map::ParseFlow(Scanner *pScanner, ParserState& state)
{
// eat start token
pScanner->pop();
state.PushCollectionType(ParserState::FLOW_MAP);
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
Token& token = pScanner->peek();
// first check for end
if(token.type == Token::FLOW_MAP_END) {
pScanner->pop();
break;
}
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
// grab key (if non-null)
if(token.type == Token::KEY) {
pScanner->pop();
pKey->Parse(pScanner, state);
}
// now grab value (optional)
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
pScanner->pop();
pValue->Parse(pScanner, state);
}
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
Token& nextToken = pScanner->peek();
if(nextToken.type == Token::FLOW_ENTRY)
pScanner->pop();
else if(nextToken.type != Token::FLOW_MAP_END)
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
AddEntry(pKey, pValue);
}
state.PopCollectionType(ParserState::FLOW_MAP);
}
// ParseCompact
// . Single "key: value" pair in a flow sequence
void Map::ParseCompact(Scanner *pScanner, ParserState& state)
{
state.PushCollectionType(ParserState::COMPACT_MAP);
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
// grab key
pScanner->pop();
pKey->Parse(pScanner, state);
// now grab value (optional)
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
pScanner->pop();
pValue->Parse(pScanner, state);
}
AddEntry(pKey, pValue);
state.PopCollectionType(ParserState::COMPACT_MAP);
}
// ParseCompactWithNoKey
// . Single ": value" pair in a flow sequence
void Map::ParseCompactWithNoKey(Scanner *pScanner, ParserState& state)
{
state.PushCollectionType(ParserState::COMPACT_MAP);
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
// grab value
pScanner->pop();
pValue->Parse(pScanner, state);
AddEntry(pKey, pValue);
state.PopCollectionType(ParserState::COMPACT_MAP);
}
void Map::AddEntry(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
{
node_map::const_iterator it = m_data.find(pKey.get());
if(it != m_data.end())
@@ -49,14 +198,12 @@ namespace YAML
m_data[pKey.release()] = pValue.release();
}
void Map::EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
void Map::Write(Emitter& out) const
{
eventHandler.OnMapStart(mark, tag, anchor);
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
it->first->EmitEvents(am, eventHandler);
it->second->EmitEvents(am, eventHandler);
}
eventHandler.OnMapEnd();
out << BeginMap;
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it)
out << Key << *it->first << Value << *it->second;
out << EndMap;
}
int Map::Compare(Content *pContent)
+12 -3
View File
@@ -19,16 +19,17 @@ namespace YAML
public:
Map();
Map(const node_map& data);
virtual ~Map();
void Clear();
virtual Content *Clone() const;
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
virtual std::size_t GetSize() const;
virtual void Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
virtual void Parse(Scanner *pScanner, ParserState& state);
virtual void Write(Emitter& out) const;
virtual bool IsMap() const { return true; }
@@ -38,6 +39,14 @@ namespace YAML
virtual int Compare(Sequence *) { return 1; }
virtual int Compare(Map *pMap);
private:
void ParseBlock(Scanner *pScanner, ParserState& state);
void ParseFlow(Scanner *pScanner, ParserState& state);
void ParseCompact(Scanner *pScanner, ParserState& state);
void ParseCompactWithNoKey(Scanner *pScanner, ParserState& state);
void AddEntry(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
private:
node_map m_data;
};
+141 -94
View File
@@ -1,21 +1,15 @@
#include "node.h"
#include "aliascontent.h"
#include "aliasmanager.h"
#include "content.h"
#include "emitfromevents.h"
#include "emitter.h"
#include "eventhandler.h"
#include "graphbuilderadapter.h"
#include "iterpriv.h"
#include "map.h"
#include "nodebuilder.h"
#include "nodeproperties.h"
#include "scalar.h"
#include "scanner.h"
#include "sequence.h"
#include "tag.h"
#include "token.h"
#include <cassert>
#include "scanner.h"
#include "content.h"
#include "parser.h"
#include "scalar.h"
#include "sequence.h"
#include "map.h"
#include "aliascontent.h"
#include "iterpriv.h"
#include "emitter.h"
#include "tag.h"
#include <stdexcept>
namespace YAML
@@ -26,10 +20,17 @@ namespace YAML
return *pNode1 < *pNode2;
}
Node::Node(): m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
Node::Node(): m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(true)
{
}
Node::Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent)
: m_mark(mark), m_anchor(anchor), m_tag(tag), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
{
if(pContent)
m_pContent = pContent->Clone();
}
Node::~Node()
{
Clear();
@@ -41,107 +42,138 @@ namespace YAML
m_pContent = 0;
m_alias = false;
m_referenced = false;
m_anchor.clear();
m_tag.clear();
}
std::auto_ptr<Node> Node::Clone() const
{
std::auto_ptr<Node> pNode(new Node);
NodeBuilder nodeBuilder(*pNode);
GraphBuilder<NodeBuilder> graphBuilder(nodeBuilder);
GraphBuilderAdapter eventHandler(graphBuilder);
EmitEvents(eventHandler);
return pNode;
}
void Node::EmitEvents(EventHandler& eventHandler) const
{
eventHandler.OnDocumentStart(m_mark);
AliasManager am;
EmitEvents(am, eventHandler);
eventHandler.OnDocumentEnd();
}
void Node::EmitEvents(AliasManager& am, EventHandler& eventHandler) const
{
anchor_t anchor = NullAnchor;
if(m_referenced || m_alias) {
if(const Node *pOther = am.LookupReference(*this)) {
eventHandler.OnAlias(m_mark, am.LookupAnchor(*pOther));
return;
}
am.RegisterReference(*this);
anchor = am.LookupAnchor(*this);
}
if(m_alias)
throw std::runtime_error("yaml-cpp: Can't clone alias"); // TODO: what to do about aliases?
if(m_pContent)
m_pContent->EmitEvents(am, eventHandler, m_mark, GetTag(), anchor);
else
eventHandler.OnNull(GetTag(), anchor);
return std::auto_ptr<Node> (new Node(m_mark, m_anchor, m_tag, m_pContent));
}
void Node::Init(CONTENT_TYPE type, const Mark& mark, const std::string& tag)
void Node::Parse(Scanner *pScanner, ParserState& state)
{
Clear();
m_mark = mark;
m_tag = tag;
m_alias = false;
m_pIdentity = this;
m_referenced = false;
switch(type) {
case CT_SCALAR:
// an empty node *is* a possibility
if(pScanner->empty())
return;
// save location
m_mark = pScanner->peek().mark;
// special case: a value node by itself must be a map, with no header
if(pScanner->peek().type == Token::VALUE) {
m_pContent = new Map;
m_pContent->Parse(pScanner, state);
return;
}
ParseHeader(pScanner, state);
// is this an alias? if so, its contents are an alias to
// a previously defined anchor
if(m_alias) {
// the scanner throws an exception if it doesn't know this anchor name
const Node *pReferencedNode = pScanner->Retrieve(m_anchor);
m_pIdentity = pReferencedNode;
// mark the referenced node for the sake of the client code
pReferencedNode->m_referenced = true;
// use of an Alias object keeps the referenced content from
// being deleted twice
Content *pAliasedContent = pReferencedNode->m_pContent;
if(pAliasedContent)
m_pContent = new AliasContent(pAliasedContent);
return;
}
// now split based on what kind of node we should be
switch(pScanner->peek().type) {
case Token::SCALAR:
m_pContent = new Scalar;
break;
case CT_SEQUENCE:
case Token::FLOW_SEQ_START:
case Token::BLOCK_SEQ_START:
m_pContent = new Sequence;
break;
case CT_MAP:
case Token::FLOW_MAP_START:
case Token::BLOCK_MAP_START:
m_pContent = new Map;
break;
default:
m_pContent = 0;
case Token::KEY:
// compact maps can only go in a flow sequence
if(state.GetCurCollectionType() == ParserState::FLOW_SEQ)
m_pContent = new Map;
break;
default:
break;
}
// Have to save anchor before parsing to allow for aliases as
// contained node (recursive structure)
if(!m_anchor.empty())
pScanner->Save(m_anchor, this);
if(m_pContent)
m_pContent->Parse(pScanner, state);
}
// ParseHeader
// . Grabs any tag, alias, or anchor tokens and deals with them.
void Node::ParseHeader(Scanner *pScanner, ParserState& state)
{
while(1) {
if(pScanner->empty())
return;
switch(pScanner->peek().type) {
case Token::TAG: ParseTag(pScanner, state); break;
case Token::ANCHOR: ParseAnchor(pScanner, state); break;
case Token::ALIAS: ParseAlias(pScanner, state); break;
default: return;
}
}
}
void Node::InitNull(const std::string& tag)
void Node::ParseTag(Scanner *pScanner, ParserState& state)
{
Clear();
m_tag = tag;
m_alias = false;
m_pIdentity = this;
m_referenced = false;
}
Token& token = pScanner->peek();
if(m_tag != "")
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
void Node::InitAlias(const Mark& mark, const Node& identity)
{
Clear();
m_mark = mark;
m_alias = true;
m_pIdentity = &identity;
if(identity.m_pContent)
m_pContent = new AliasContent(identity.m_pContent);
identity.m_referenced = true;
}
void Node::SetData(const std::string& data)
{
assert(m_pContent); // TODO: throw
m_pContent->SetData(data);
}
void Node::Append(std::auto_ptr<Node> pNode)
{
assert(m_pContent); // TODO: throw
m_pContent->Append(pNode);
Tag tag(token);
m_tag = tag.Translate(state);
pScanner->pop();
}
void Node::Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
void Node::ParseAnchor(Scanner *pScanner, ParserState& /*state*/)
{
assert(m_pContent); // TODO: throw
m_pContent->Insert(pKey, pValue);
Token& token = pScanner->peek();
if(m_anchor != "")
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
m_anchor = token.value;
m_alias = false;
pScanner->pop();
}
void Node::ParseAlias(Scanner *pScanner, ParserState& /*state*/)
{
Token& token = pScanner->peek();
if(m_anchor != "")
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ALIASES);
if(m_tag != "")
throw ParserException(token.mark, ErrorMsg::ALIAS_CONTENT);
m_anchor = token.value;
m_alias = true;
pScanner->pop();
}
CONTENT_TYPE Node::GetType() const
@@ -229,8 +261,23 @@ namespace YAML
Emitter& operator << (Emitter& out, const Node& node)
{
EmitFromEvents emitFromEvents(out);
node.EmitEvents(emitFromEvents);
// write anchor/alias
if(node.m_anchor != "") {
if(node.m_alias)
out << Alias(node.m_anchor);
else
out << Anchor(node.m_anchor);
}
if(node.m_tag != "")
out << VerbatimTag(node.m_tag);
// write content
if(node.m_pContent)
node.m_pContent->Write(out);
else if(!node.m_alias)
out << Null;
return out;
}
-90
View File
@@ -1,90 +0,0 @@
#include "nodebuilder.h"
#include "mark.h"
#include "node.h"
#include "nodeproperties.h"
#include <cassert>
namespace YAML
{
NodeBuilder::NodeBuilder(Node& root): m_root(root), m_initializedRoot(false)
{
m_root.Clear();
}
NodeBuilder::NodeBuilder(const NodeBuilder& o): m_root(o.m_root), m_initializedRoot(o.m_initializedRoot)
{
}
NodeBuilder::~NodeBuilder()
{
}
Node *NodeBuilder::NewNull(const std::string& tag, Node *pParent)
{
(void)pParent;
Node *pNode = NewNode();
pNode->InitNull(tag);
return pNode;
}
Node *NodeBuilder::AnchorReference(const Mark& mark, Node *pNode)
{
Node *pAlias = NewNode();
pAlias->InitAlias(mark, *pNode);
return pAlias;
}
Node *NodeBuilder::NewScalar(const Mark& mark, const std::string& tag, Node *pParent, const std::string& value)
{
(void)pParent;
Node *pNode = NewNode();
pNode->Init(CT_SCALAR, mark, tag);
pNode->SetData(value);
return pNode;
}
NodeBuilder::Sequence *NodeBuilder::NewSequence(const Mark& mark, const std::string& tag, Node *pParent)
{
(void)pParent;
Node *pNode = NewNode();
pNode->Init(CT_SEQUENCE, mark, tag);
return pNode;
}
void NodeBuilder::AppendToSequence(Sequence *pSequence, Node *pNode)
{
std::auto_ptr<Node> apNode(m_unlinked.pop(pNode));
assert(apNode.get());
pSequence->Append(apNode);
}
NodeBuilder::Map *NodeBuilder::NewMap(const Mark& mark, const std::string& tag, Node* pParent)
{
(void)pParent;
Node *pNode = NewNode();
pNode->Init(CT_MAP, mark, tag);
return pNode;
}
void NodeBuilder::AssignInMap(Map *pMap, Node *pKeyNode, Node *pValueNode)
{
std::auto_ptr<Node> apKeyNode(m_unlinked.pop(pKeyNode));
std::auto_ptr<Node> apValueNode(m_unlinked.pop(pValueNode));
assert(apKeyNode.get() && apValueNode.get());
pMap->Insert(apKeyNode, apValueNode);
}
Node* NodeBuilder::NewNode()
{
if(!m_initializedRoot) {
m_initializedRoot = true;
return &m_root;
}
std::auto_ptr<Node> pNode(new Node);
Node* pResult = pNode.get();
// Save the pointer in a collection that will free it on exception
m_unlinked.push(pNode);
return pResult;
}
}
-53
View File
@@ -1,53 +0,0 @@
#pragma once
#ifndef NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <map>
#include <memory>
#include <stack>
#include <string>
#include "ptr_stack.h"
namespace YAML
{
class Node;
class Mark;
class NodeBuilder
{
public:
typedef YAML::Node Node;
typedef YAML::Node Map;
typedef YAML::Node Sequence;
explicit NodeBuilder(Node& root);
NodeBuilder(const NodeBuilder& o);
virtual ~NodeBuilder();
Node *NewNull(const std::string& tag, Node *pParent);
Node *AnchorReference(const Mark& mark, Node *pNode);
Node *NewScalar(const Mark& mark, const std::string& tag, Node *pParent, const std::string& value);
Sequence *NewSequence(const Mark& mark, const std::string& tag, Node *pParent);
void AppendToSequence(Sequence *pSequence, Node *pNode);
void SequenceComplete(Sequence *pSequence) {(void)pSequence;}
Map *NewMap(const Mark& mark, const std::string& tag, Node *pParent);
void AssignInMap(Map *pMap, Node *pKeyNode, Node *pValueNode);
void MapComplete(Map *pMap) {(void)pMap;}
private:
Node* NewNode();
private:
Node& m_root;
bool m_initializedRoot;
ptr_stack<Node> m_unlinked;
};
}
#endif // NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+39 -50
View File
@@ -1,14 +1,8 @@
#include "parser.h"
#include "directives.h"
#include "eventhandler.h"
#include "exceptions.h"
#include "graphbuilderadapter.h"
#include "node.h"
#include "nodebuilder.h"
#include "scanner.h"
#include "singledocparser.h"
#include "tag.h"
#include "token.h"
#include "exceptions.h"
#include "parserstate.h"
#include <sstream>
#include <cstdio>
@@ -35,38 +29,7 @@ namespace YAML
void Parser::Load(std::istream& in)
{
m_pScanner.reset(new Scanner(in));
m_pDirectives.reset(new Directives);
}
// HandleNextDocument
// . Handles the next document
// . Throws a ParserException on error.
// . Returns false if there are no more documents
bool Parser::HandleNextDocument(EventHandler& eventHandler)
{
if(!m_pScanner.get())
return false;
ParseDirectives();
if(m_pScanner->empty())
return false;
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
sdp.HandleDocument(eventHandler);
return true;
}
// BuildNextDocumentGraph
// . Builds a graph of the next document
// . Returns NULL if there are no more documents
void *Parser::BuildNextDocumentGraph(GraphBuilderInterface& graphBuilder)
{
GraphBuilderAdapter eventHandler(graphBuilder);
if (HandleNextDocument(eventHandler)) {
return eventHandler.RootNode();
} else {
return NULL;
}
m_pState.reset(new ParserState);
}
// GetNextDocument
@@ -74,8 +37,34 @@ namespace YAML
// . Throws a ParserException on error.
bool Parser::GetNextDocument(Node& document)
{
NodeBuilder builder(document);
return BuildNextDocumentGraph(builder);
if(!m_pScanner.get())
return false;
// clear node
document.Clear();
// first read directives
ParseDirectives();
// we better have some tokens in the queue
if(m_pScanner->empty())
return false;
// first eat doc start (optional)
if(m_pScanner->peek().type == Token::DOC_START)
m_pScanner->pop();
// now parse our root node
document.Parse(m_pScanner.get(), *m_pState);
// and finally eat any doc ends we see
while(!m_pScanner->empty() && m_pScanner->peek().type == Token::DOC_END)
m_pScanner->pop();
// clear anchors from the scanner, which are no longer relevant
m_pScanner->ClearAnchors();
return true;
}
// ParseDirectives
@@ -95,7 +84,7 @@ namespace YAML
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if(!readDirective)
m_pDirectives.reset(new Directives);
m_pState.reset(new ParserState);
readDirective = true;
HandleDirective(token);
@@ -118,20 +107,20 @@ namespace YAML
if(token.params.size() != 1)
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
if(!m_pDirectives->version.isDefault)
if(!m_pState->version.isDefault)
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
std::stringstream str(token.params[0]);
str >> m_pDirectives->version.major;
str >> m_pState->version.major;
str.get();
str >> m_pDirectives->version.minor;
str >> m_pState->version.minor;
if(!str || str.peek() != EOF)
throw ParserException(token.mark, ErrorMsg::YAML_VERSION + token.params[0]);
if(m_pDirectives->version.major > 1)
if(m_pState->version.major > 1)
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
m_pDirectives->version.isDefault = false;
m_pState->version.isDefault = false;
// TODO: warning on major == 1, minor > 2?
}
@@ -144,10 +133,10 @@ namespace YAML
const std::string& handle = token.params[0];
const std::string& prefix = token.params[1];
if(m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
if(m_pState->tags.find(handle) != m_pState->tags.end())
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
m_pDirectives->tags[handle] = prefix;
m_pState->tags[handle] = prefix;
}
void Parser::PrintTokens(std::ostream& out)
+5 -5
View File
@@ -1,16 +1,16 @@
#include "directives.h"
#include "parserstate.h"
namespace YAML
{
Directives::Directives()
ParserState::ParserState()
{
// version
version.isDefault = true;
version.major = 1;
version.minor = 2;
}
const std::string Directives::TranslateTagHandle(const std::string& handle) const
const std::string ParserState::TranslateTagHandle(const std::string& handle) const
{
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
if(it == tags.end()) {
@@ -18,7 +18,7 @@ namespace YAML
return "tag:yaml.org,2002:";
return handle;
}
return it->second;
}
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#ifndef PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
#include <map>
#include <stack>
#include <cassert>
namespace YAML
{
struct Version {
bool isDefault;
int major, minor;
};
struct ParserState
{
enum COLLECTION_TYPE { NONE, BLOCK_MAP, BLOCK_SEQ, FLOW_MAP, FLOW_SEQ, COMPACT_MAP };
ParserState();
const std::string TranslateTagHandle(const std::string& handle) const;
COLLECTION_TYPE GetCurCollectionType() const { if(collectionStack.empty()) return NONE; return collectionStack.top(); }
void PushCollectionType(COLLECTION_TYPE type) { collectionStack.push(type); }
void PopCollectionType(COLLECTION_TYPE type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
Version version;
std::map <std::string, std::string> tags;
std::stack <COLLECTION_TYPE> collectionStack;
};
}
#endif // PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-55
View File
@@ -1,55 +0,0 @@
#pragma once
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <algorithm>
#include <memory>
#include <vector>
#include "noncopyable.h"
template <typename T>
class ptr_stack : private YAML::noncopyable
{
public:
ptr_stack() {}
~ptr_stack() { clear(); }
void clear() {
for(unsigned i=0;i<m_data.size();i++)
delete m_data[i];
m_data.clear();
}
std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); }
void push(std::auto_ptr<T> t) {
// Make sure that the space is available before releasing the
// auto_ptr to it. NULL can be deleted safely.
m_data.push_back(NULL);
m_data.back() = t.release();
}
std::auto_ptr<T> pop() {
std::auto_ptr<T> t(m_data.back());
m_data.pop_back();
return t;
}
std::auto_ptr<T> pop(T* val) {
typename std::vector<T*>::reverse_iterator itVal =
std::find(m_data.rbegin(), m_data.rend(), val);
std::auto_ptr<T> t;
if (itVal != m_data.rend()) {
t.reset(*itVal);
m_data.erase((itVal + 1).base());
}
return t;
}
T& top() const { return *m_data.back(); }
private:
std::vector<T*> m_data;
};
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+23 -3
View File
@@ -1,5 +1,9 @@
#include "scalar.h"
#include "eventhandler.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "node.h"
#include "emitter.h"
namespace YAML
{
@@ -7,13 +11,29 @@ namespace YAML
{
}
Scalar::Scalar(const std::string& data): m_data(data)
{
}
Scalar::~Scalar()
{
}
void Scalar::EmitEvents(AliasManager&, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
Content *Scalar::Clone() const
{
eventHandler.OnScalar(mark, tag, anchor, m_data);
return new Scalar(m_data);
}
void Scalar::Parse(Scanner *pScanner, ParserState& /*state*/)
{
Token& token = pScanner->peek();
m_data = token.value;
pScanner->pop();
}
void Scalar::Write(Emitter& out) const
{
out << m_data;
}
int Scalar::Compare(Content *pContent)
+5 -2
View File
@@ -13,12 +13,15 @@ namespace YAML
{
public:
Scalar();
Scalar(const std::string& data);
virtual ~Scalar();
virtual void SetData(const std::string& data) { m_data = data; }
virtual Content *Clone() const;
virtual void Parse(Scanner *pScanner, ParserState& state);
virtual void Write(Emitter& out) const;
virtual bool IsScalar() const { return true; }
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
// extraction
virtual bool GetScalar(std::string& scalar) const {
+35 -1
View File
@@ -32,8 +32,13 @@ namespace YAML
void Scanner::pop()
{
EnsureTokensInQueue();
if(!m_tokens.empty())
if(!m_tokens.empty()) {
// Saved anchors shouldn't survive popping the document end marker
if (m_tokens.front().type == Token::DOC_END) {
ClearAnchors();
}
m_tokens.pop();
}
}
// peek
@@ -240,6 +245,7 @@ namespace YAML
IndentMarker *pIndent = new IndentMarker(-1, IndentMarker::NONE);
m_indentRefs.push_back(pIndent);
m_indents.push(pIndent);
m_anchors.clear();
}
// EndStream
@@ -372,6 +378,29 @@ namespace YAML
return m_indents.top()->column;
}
// Save
// . Saves a pointer to the Node object referenced by a particular anchor
// name.
void Scanner::Save(const std::string& anchor, Node* value)
{
m_anchors[anchor] = value;
}
// Retrieve
// . Retrieves a pointer previously saved for an anchor name.
// . Throws an exception if the anchor has not been defined.
const Node *Scanner::Retrieve(const std::string& anchor) const
{
typedef std::map<std::string, const Node *> map;
map::const_iterator itNode = m_anchors.find(anchor);
if(m_anchors.end() == itNode)
ThrowParserException(ErrorMsg::UNKNOWN_ANCHOR);
return itNode->second;
}
// ThrowParserException
// . Throws a ParserException with the current token location
// (if available).
@@ -385,5 +414,10 @@ namespace YAML
}
throw ParserException(mark, msg);
}
void Scanner::ClearAnchors()
{
m_anchors.clear();
}
}
+6
View File
@@ -29,6 +29,11 @@ namespace YAML
void pop();
Token& peek();
// anchor management
void Save(const std::string& anchor, Node* value);
const Node *Retrieve(const std::string& anchor) const;
void ClearAnchors();
private:
struct IndentMarker {
enum INDENT_TYPE { MAP, SEQ, NONE };
@@ -122,6 +127,7 @@ namespace YAML
std::stack <IndentMarker *> m_indents;
std::vector <IndentMarker *> m_indentRefs; // for "garbage collection"
std::stack <FLOW_MARKER> m_flows;
std::map <std::string, const Node *> m_anchors;
};
}
+1 -7
View File
@@ -276,12 +276,7 @@ namespace YAML
} else {
bool canBeHandle;
token.value = ScanTagHandle(INPUT, canBeHandle);
if(!canBeHandle && token.value.empty())
token.data = Tag::NON_SPECIFIC;
else if(token.value.empty())
token.data = Tag::SECONDARY_HANDLE;
else
token.data = Tag::PRIMARY_HANDLE;
token.data = (token.value.empty() ? Tag::SECONDARY_HANDLE : Tag::PRIMARY_HANDLE);
// is there a suffix?
if(canBeHandle && INPUT.peek() == Keys::Tag) {
@@ -328,7 +323,6 @@ namespace YAML
Token token(Token::SCALAR, mark);
token.value = scalar;
token.params.push_back(Token::PLAIN_SCALAR);
m_tokens.push(token);
}
+94 -8
View File
@@ -1,6 +1,8 @@
#include "sequence.h"
#include "eventhandler.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
#include "emitter.h"
#include <stdexcept>
namespace YAML
@@ -10,6 +12,12 @@ namespace YAML
}
Sequence::Sequence(const std::vector<Node *>& data)
{
for(std::size_t i=0;i<data.size();i++)
m_data.push_back(data[i]->Clone().release());
}
Sequence::~Sequence()
{
Clear();
@@ -22,6 +30,11 @@ namespace YAML
m_data.clear();
}
Content *Sequence::Clone() const
{
return new Sequence(m_data);
}
bool Sequence::GetBegin(std::vector <Node *>::const_iterator& it) const
{
it = m_data.begin();
@@ -46,17 +59,90 @@ namespace YAML
return m_data.size();
}
void Sequence::Append(std::auto_ptr<Node> pNode)
void Sequence::Parse(Scanner *pScanner, ParserState& state)
{
m_data.push_back(pNode.release());
Clear();
// split based on start token
switch(pScanner->peek().type) {
case Token::BLOCK_SEQ_START: ParseBlock(pScanner, state); break;
case Token::FLOW_SEQ_START: ParseFlow(pScanner, state); break;
default: break;
}
}
void Sequence::EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
void Sequence::ParseBlock(Scanner *pScanner, ParserState& state)
{
eventHandler.OnSequenceStart(mark, tag, anchor);
// eat start token
pScanner->pop();
state.PushCollectionType(ParserState::BLOCK_SEQ);
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
Token token = pScanner->peek();
if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
pScanner->pop();
if(token.type == Token::BLOCK_SEQ_END)
break;
Node *pNode = new Node;
m_data.push_back(pNode);
// check for null
if(!pScanner->empty()) {
const Token& token = pScanner->peek();
if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END)
continue;
}
pNode->Parse(pScanner, state);
}
state.PopCollectionType(ParserState::BLOCK_SEQ);
}
void Sequence::ParseFlow(Scanner *pScanner, ParserState& state)
{
// eat start token
pScanner->pop();
state.PushCollectionType(ParserState::FLOW_SEQ);
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
// first check for end
if(pScanner->peek().type == Token::FLOW_SEQ_END) {
pScanner->pop();
break;
}
// then read the node
Node *pNode = new Node;
m_data.push_back(pNode);
pNode->Parse(pScanner, state);
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
Token& token = pScanner->peek();
if(token.type == Token::FLOW_ENTRY)
pScanner->pop();
else if(token.type != Token::FLOW_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
}
state.PopCollectionType(ParserState::FLOW_SEQ);
}
void Sequence::Write(Emitter& out) const
{
out << BeginSeq;
for(std::size_t i=0;i<m_data.size();i++)
m_data[i]->EmitEvents(am, eventHandler);
eventHandler.OnSequenceEnd();
out << *m_data[i];
out << EndSeq;
}
int Sequence::Compare(Content *pContent)
+8 -2
View File
@@ -15,17 +15,19 @@ namespace YAML
{
public:
Sequence();
Sequence(const std::vector<Node *>& data);
virtual ~Sequence();
void Clear();
virtual Content *Clone() const;
virtual bool GetBegin(std::vector <Node *>::const_iterator& it) const;
virtual bool GetEnd(std::vector <Node *>::const_iterator& it) const;
virtual Node *GetNode(std::size_t i) const;
virtual std::size_t GetSize() const;
virtual void Append(std::auto_ptr<Node> pNode);
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
virtual void Parse(Scanner *pScanner, ParserState& state);
virtual void Write(Emitter& out) const;
virtual bool IsSequence() const { return true; }
@@ -35,6 +37,10 @@ namespace YAML
virtual int Compare(Sequence *pSeq);
virtual int Compare(Map *) { return -1; }
private:
void ParseBlock(Scanner *pScanner, ParserState& state);
void ParseFlow(Scanner *pScanner, ParserState& state);
protected:
std::vector <Node *> m_data;
};
-381
View File
@@ -1,381 +0,0 @@
#include "singledocparser.h"
#include "collectionstack.h"
#include "directives.h"
#include "eventhandler.h"
#include "exceptions.h"
#include "scanner.h"
#include "tag.h"
#include "token.h"
#include <sstream>
#include <cstdio>
#include <algorithm>
namespace YAML
{
SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives): m_scanner(scanner), m_directives(directives), m_pCollectionStack(new CollectionStack), m_curAnchor(0)
{
}
SingleDocParser::~SingleDocParser()
{
}
// HandleDocument
// . Handles the next document
// . Throws a ParserException on error.
void SingleDocParser::HandleDocument(EventHandler& eventHandler)
{
assert(!m_scanner.empty()); // guaranteed that there are tokens
assert(!m_curAnchor);
eventHandler.OnDocumentStart(m_scanner.peek().mark);
// eat doc start
if(m_scanner.peek().type == Token::DOC_START)
m_scanner.pop();
// recurse!
HandleNode(eventHandler);
eventHandler.OnDocumentEnd();
// and finally eat any doc ends we see
while(!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
m_scanner.pop();
}
void SingleDocParser::HandleNode(EventHandler& eventHandler)
{
// an empty node *is* a possibility
if(m_scanner.empty()) {
eventHandler.OnNull("", NullAnchor);
return;
}
// save location
Mark mark = m_scanner.peek().mark;
// special case: a value node by itself must be a map, with no header
if(m_scanner.peek().type == Token::VALUE) {
eventHandler.OnMapStart(mark, "", NullAnchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
}
// special case: an alias node
if(m_scanner.peek().type == Token::ALIAS) {
eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
m_scanner.pop();
return;
}
std::string tag;
anchor_t anchor;
ParseProperties(tag, anchor);
if (tag.empty()) {
const Token& token = m_scanner.peek();
const std::vector<std::string>& tparams = token.params;
if (token.type != Token::SCALAR ||
std::find(tparams.begin(), tparams.end(), Token::PLAIN_SCALAR) != tparams.end()) {
tag = "?";
} else {
tag = "!";
}
}
// now split based on what kind of node we should be
switch(m_scanner.peek().type) {
case Token::SCALAR:
eventHandler.OnScalar(mark, tag, anchor, m_scanner.peek().value);
m_scanner.pop();
return;
case Token::FLOW_SEQ_START:
case Token::BLOCK_SEQ_START:
eventHandler.OnSequenceStart(mark, tag, anchor);
HandleSequence(eventHandler);
eventHandler.OnSequenceEnd();
return;
case Token::FLOW_MAP_START:
case Token::BLOCK_MAP_START:
eventHandler.OnMapStart(mark, tag, anchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
case Token::KEY:
// compact maps can only go in a flow sequence
if(m_pCollectionStack->GetCurCollectionType() == CollectionType::FlowSeq) {
eventHandler.OnMapStart(mark, tag, anchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
}
break;
default:
break;
}
eventHandler.OnNull(tag, anchor);
}
void SingleDocParser::HandleSequence(EventHandler& eventHandler)
{
// split based on start token
switch(m_scanner.peek().type) {
case Token::BLOCK_SEQ_START: HandleBlockSequence(eventHandler); break;
case Token::FLOW_SEQ_START: HandleFlowSequence(eventHandler); break;
default: break;
}
}
void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
Token token = m_scanner.peek();
if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
m_scanner.pop();
if(token.type == Token::BLOCK_SEQ_END)
break;
// check for null
if(!m_scanner.empty()) {
const Token& token = m_scanner.peek();
if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END) {
eventHandler.OnNull("", NullAnchor);
continue;
}
}
HandleNode(eventHandler);
}
m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
}
void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
// first check for end
if(m_scanner.peek().type == Token::FLOW_SEQ_END) {
m_scanner.pop();
break;
}
// then read the node
HandleNode(eventHandler);
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
Token& token = m_scanner.peek();
if(token.type == Token::FLOW_ENTRY)
m_scanner.pop();
else if(token.type != Token::FLOW_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
}
m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
}
void SingleDocParser::HandleMap(EventHandler& eventHandler)
{
// split based on start token
switch(m_scanner.peek().type) {
case Token::BLOCK_MAP_START: HandleBlockMap(eventHandler); break;
case Token::FLOW_MAP_START: HandleFlowMap(eventHandler); break;
case Token::KEY: HandleCompactMap(eventHandler); break;
case Token::VALUE: HandleCompactMapWithNoKey(eventHandler); break;
default: break;
}
}
void SingleDocParser::HandleBlockMap(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
Token token = m_scanner.peek();
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
if(token.type == Token::BLOCK_MAP_END) {
m_scanner.pop();
break;
}
// grab key (if non-null)
if(token.type == Token::KEY) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
// now grab value (optional)
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
}
m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
}
void SingleDocParser::HandleFlowMap(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
Token& token = m_scanner.peek();
// first check for end
if(token.type == Token::FLOW_MAP_END) {
m_scanner.pop();
break;
}
// grab key (if non-null)
if(token.type == Token::KEY) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
// now grab value (optional)
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
Token& nextToken = m_scanner.peek();
if(nextToken.type == Token::FLOW_ENTRY)
m_scanner.pop();
else if(nextToken.type != Token::FLOW_MAP_END)
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
}
m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
}
// . Single "key: value" pair in a flow sequence
void SingleDocParser::HandleCompactMap(EventHandler& eventHandler)
{
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
// grab key
m_scanner.pop();
HandleNode(eventHandler);
// now grab value (optional)
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
}
// . Single ": value" pair in a flow sequence
void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler)
{
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
// null key
eventHandler.OnNull("", NullAnchor);
// grab value
m_scanner.pop();
HandleNode(eventHandler);
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
}
// ParseProperties
// . Grabs any tag or anchor tokens and deals with them.
void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor)
{
tag.clear();
anchor = NullAnchor;
while(1) {
if(m_scanner.empty())
return;
switch(m_scanner.peek().type) {
case Token::TAG: ParseTag(tag); break;
case Token::ANCHOR: ParseAnchor(anchor); break;
default: return;
}
}
}
void SingleDocParser::ParseTag(std::string& tag)
{
Token& token = m_scanner.peek();
if(!tag.empty())
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
Tag tagInfo(token);
tag = tagInfo.Translate(m_directives);
m_scanner.pop();
}
void SingleDocParser::ParseAnchor(anchor_t& anchor)
{
Token& token = m_scanner.peek();
if(anchor)
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
anchor = RegisterAnchor(token.value);
m_scanner.pop();
}
anchor_t SingleDocParser::RegisterAnchor(const std::string& name)
{
if(name.empty())
return NullAnchor;
return m_anchors[name] = ++m_curAnchor;
}
anchor_t SingleDocParser::LookupAnchor(const Mark& mark, const std::string& name) const
{
Anchors::const_iterator it = m_anchors.find(name);
if(it == m_anchors.end())
throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
return it->second;
}
}
-63
View File
@@ -1,63 +0,0 @@
#pragma once
#ifndef SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "anchor.h"
#include "noncopyable.h"
#include <string>
#include <map>
#include <memory>
namespace YAML
{
struct Directives;
struct Mark;
struct Token;
class CollectionStack;
class EventHandler;
class Node;
class Scanner;
class SingleDocParser: private noncopyable
{
public:
SingleDocParser(Scanner& scanner, const Directives& directives);
~SingleDocParser();
void HandleDocument(EventHandler& eventHandler);
private:
void HandleNode(EventHandler& eventHandler);
void HandleSequence(EventHandler& eventHandler);
void HandleBlockSequence(EventHandler& eventHandler);
void HandleFlowSequence(EventHandler& eventHandler);
void HandleMap(EventHandler& eventHandler);
void HandleBlockMap(EventHandler& eventHandler);
void HandleFlowMap(EventHandler& eventHandler);
void HandleCompactMap(EventHandler& eventHandler);
void HandleCompactMapWithNoKey(EventHandler& eventHandler);
void ParseProperties(std::string& tag, anchor_t& anchor);
void ParseTag(std::string& tag);
void ParseAnchor(anchor_t& anchor);
anchor_t RegisterAnchor(const std::string& name);
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
private:
Scanner& m_scanner;
const Directives& m_directives;
std::auto_ptr<CollectionStack> m_pCollectionStack;
typedef std::map<std::string, anchor_t> Anchors;
Anchors m_anchors;
anchor_t m_curAnchor;
};
}
#endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+5 -5
View File
@@ -1,6 +1,6 @@
#include "tag.h"
#include "directives.h"
#include "token.h"
#include "parserstate.h"
#include <cassert>
namespace YAML
@@ -28,17 +28,17 @@ namespace YAML
}
}
const std::string Tag::Translate(const Directives& directives)
const std::string Tag::Translate(const ParserState& state)
{
switch(type) {
case VERBATIM:
return value;
case PRIMARY_HANDLE:
return directives.TranslateTagHandle("!") + value;
return state.TranslateTagHandle("!") + value;
case SECONDARY_HANDLE:
return directives.TranslateTagHandle("!!") + value;
return state.TranslateTagHandle("!!") + value;
case NAMED_HANDLE:
return directives.TranslateTagHandle("!" + handle + "!") + value;
return state.TranslateTagHandle("!" + handle + "!") + value;
case NON_SPECIFIC:
// TODO:
return "!";
+2 -2
View File
@@ -8,7 +8,7 @@
namespace YAML
{
struct Token;
struct Directives;
struct ParserState;
struct Tag {
enum TYPE {
@@ -16,7 +16,7 @@ namespace YAML
};
Tag(const Token& token);
const std::string Translate(const Directives& directives);
const std::string Translate(const ParserState& state);
TYPE type;
std::string handle, value;
-6
View File
@@ -1,6 +0,0 @@
#include "token.h"
namespace YAML
{
const std::string Token::PLAIN_SCALAR("pln");
}
+1 -3
View File
@@ -5,7 +5,7 @@
#include "mark.h"
#include <iostream>
#include <ios>
#include <string>
#include <vector>
@@ -59,8 +59,6 @@ namespace YAML
TAG,
SCALAR
};
static const std::string PLAIN_SCALAR;
// data
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_), data(0) {}
-28
View File
@@ -373,31 +373,6 @@ namespace Test
desiredOutput = "---\n- !<!foo>\n []\n- !<!bar>\n {}";
}
void ByKindTagWithScalar(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginSeq;
out << YAML::DoubleQuoted << "12";
out << "12";
out << YAML::TagByKind << "12";
out << YAML::EndSeq;
desiredOutput = "---\n- \"12\"\n- 12\n- ! 12";
}
void LocalTagWithScalar(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::LocalTag("foo") << "bar";
desiredOutput = "--- !foo bar";
}
void BadLocalTag(YAML::Emitter& out, std::string& desiredError)
{
out << YAML::LocalTag("e!far") << "bar";
desiredError = "invalid tag";
}
void ComplexDoc(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginMap;
@@ -814,8 +789,6 @@ namespace Test
RunEmitterTest(&Emitter::VerbatimTagWithEmptySeq, "verbatim tag with empty seq", passed, total);
RunEmitterTest(&Emitter::VerbatimTagWithEmptyMap, "verbatim tag with empty map", passed, total);
RunEmitterTest(&Emitter::VerbatimTagWithEmptySeqAndMap, "verbatim tag with empty seq and map", passed, total);
RunEmitterTest(&Emitter::ByKindTagWithScalar, "by-kind tag with scalar", passed, total);
RunEmitterTest(&Emitter::LocalTagWithScalar, "local tag with scalar", passed, total);
RunEmitterTest(&Emitter::ComplexDoc, "complex doc", passed, total);
RunEmitterTest(&Emitter::STLContainers, "STL containers", passed, total);
RunEmitterTest(&Emitter::SimpleComment, "simple comment", passed, total);
@@ -842,7 +815,6 @@ namespace Test
RunEmitterErrorTest(&Emitter::MissingValue, "missing value", passed, total);
RunEmitterErrorTest(&Emitter::UnexpectedKey, "unexpected key", passed, total);
RunEmitterErrorTest(&Emitter::UnexpectedValue, "unexpected value", passed, total);
RunEmitterErrorTest(&Emitter::BadLocalTag, "bad local tag", passed, total);
std::cout << "Emitter tests: " << passed << "/" << total << " passed\n";
return passed == total;
+1 -114
View File
@@ -706,106 +706,6 @@ namespace Test
return false;
return true;
}
void PrepareNodeForTagExam(YAML::Node& doc, const std::string& input)
{
std::stringstream stream(input);
YAML::Parser parser(stream);
parser.GetNextDocument(doc);
}
struct TagMismatch: public std::exception {
TagMismatch(const std::string& actualTag, const std::string& expectedTag) {
std::stringstream output;
output << "Tag has value \"" << actualTag << "\" but \"" << expectedTag << "\" was expected";
what_ = output.str();
}
virtual ~TagMismatch() throw() {}
virtual const char *what() const throw() { return what_.c_str(); }
private:
std::string what_;
};
bool ExpectedTagValue(YAML::Node& node, const char* tag)
{
if(node.GetTag() == tag)
return true;
throw TagMismatch(node.GetTag(), tag);
}
bool DefaultPlainScalarTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- 12");
return ExpectedTagValue(node, "?");
}
bool DefaultSingleQuotedScalarTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- '12'");
return ExpectedTagValue(node, "!");
}
bool ExplicitNonSpecificPlainScalarTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- ! 12");
return ExpectedTagValue(node, "!");
}
bool BasicLocalTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- !foo 12");
return ExpectedTagValue(node, "!foo");
}
bool VerbatimLocalTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- !<!foo> 12");
return ExpectedTagValue(node, "!foo");
}
bool StandardShortcutTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- !!int 12");
return ExpectedTagValue(node, "tag:yaml.org,2002:int");
}
bool VerbatimURITag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- !<tag:yaml.org,2002:int> 12");
return ExpectedTagValue(node, "tag:yaml.org,2002:int");
}
bool DefaultSequenceTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- [12]");
return ExpectedTagValue(node, "?");
}
bool ExplicitNonSpecificSequenceTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- ! [12]");
return ExpectedTagValue(node, "!");
}
}
namespace {
@@ -846,10 +746,7 @@ namespace Test
ok = test();
} catch(const YAML::Exception& e) {
ok = false;
error = e.what();
} catch(const Parser::TagMismatch& e) {
ok = false;
error = e.what();
error = e.msg;
}
if(ok) {
passed++;
@@ -1072,16 +969,6 @@ namespace Test
RunParserTest(&Parser::Bases, "bases", passed, total);
RunParserTest(&Parser::KeyNotFound, "key not found", passed, total);
RunParserTest(&Parser::DuplicateKey, "duplicate key", passed, total);
RunParserTest(&Parser::DefaultPlainScalarTag, "default plain scalar tag", passed, total);
RunParserTest(&Parser::DefaultSingleQuotedScalarTag, "default single-quoted scalar tag", passed, total);
RunParserTest(&Parser::ExplicitNonSpecificPlainScalarTag, "explicit, non-specific plain scalar tag", passed, total);
RunParserTest(&Parser::BasicLocalTag, "basic local tag", passed, total);
RunParserTest(&Parser::VerbatimLocalTag, "verbatim local tag", passed, total);
RunParserTest(&Parser::StandardShortcutTag, "standard shortcut tag", passed, total);
RunParserTest(&Parser::VerbatimURITag, "verbatim URI tag", passed, total);
RunParserTest(&Parser::DefaultPlainScalarTag, "default plain scalar tag", passed, total);
RunParserTest(&Parser::DefaultSequenceTag, "default sequence tag", passed, total);
RunParserTest(&Parser::ExplicitNonSpecificSequenceTag, "explicit, non-specific sequence tag", passed, total);
RunEncodingTest(&EncodeToUtf8, false, "UTF-8, no BOM", passed, total);
RunEncodingTest(&EncodeToUtf8, true, "UTF-8 with BOM", passed, total);
-16
View File
@@ -1,25 +1,9 @@
#include "yaml.h"
#include <fstream>
#include <iostream>
#include <vector>
struct Params {
bool hasFile;
std::string fileName;
};
Params ParseArgs(int argc, char **argv) {
Params p;
std::vector<char*> args(argv + 1, argv + argc);
return p;
}
int main(int argc, char **argv)
{
Params p = ParseArgs(argc, argv);
std::ifstream fin;
if(argc > 1)
fin.open(argv[1]);