1 /**********************************************
2 
3 License: BSD
4 Project Webpage: http://cajun-jsonapi.sourceforge.net/
5 Author: Terry Caton
6 
7 ***********************************************/
8 
9 #pragma once
10 
11 #include "elements.h"
12 
13 #include <vector>
14 
15 namespace json
16 {
17 
18 class Reader {
19 public:
20 	// this structure will be reported in one of the exceptions defined below
21 	struct Location {
22 		unsigned int m_nLine = 0;       // document line, zero-indexed
23 		unsigned int m_nLineOffset = 0; // character offset from beginning of line, zero indexed
24 		unsigned int m_nDocOffset = 0;  // character offset from entire document, zero indexed
25 	};
26 
27 	// thrown during the first phase of reading. generally catches low-level
28 	// problems such as errant characters or corrupt/incomplete documents
29 	class ScanException final : public Exception {
30 	public:
ScanException(std::string const & sMessage,Reader::Location locError)31 		ScanException(std::string const& sMessage, Reader::Location locError)
32 		: Exception(sMessage)
33 		, m_locError(std::move(locError))
34 		{ }
35 
36 		Reader::Location m_locError;
37 	};
38 
39 	// thrown during the second phase of reading. generally catches
40 	// higher-level problems such as missing commas or brackets
41 	class ParseException final : public Exception {
42 	public:
ParseException(std::string const & sMessage,Reader::Location locTokenBegin,Reader::Location locTokenEnd)43 		ParseException(std::string const& sMessage, Reader::Location locTokenBegin, Reader::Location locTokenEnd)
44 		: Exception(sMessage)
45 		, m_locTokenBegin(std::move(locTokenBegin))
46 		, m_locTokenEnd(std::move(locTokenEnd))
47 		{ }
48 
49 		Reader::Location m_locTokenBegin;
50 		Reader::Location m_locTokenEnd;
51 	};
52 
53 	static void Read(UnknownElement& elementRoot, std::istream& istr);
54 
55 private:
56 	struct Token {
57 		enum Type {
58 			TOKEN_OBJECT_BEGIN,  // {
59 			TOKEN_OBJECT_END,    // }
60 			TOKEN_ARRAY_BEGIN,   // [
61 			TOKEN_ARRAY_END,     // ]
62 			TOKEN_NEXT_ELEMENT,  // ,
63 			TOKEN_MEMBER_ASSIGN, // :
64 			TOKEN_STRING,        // "xxx"
65 			TOKEN_NUMBER,        // [+/-]000.000[e[+/-]000]
66 			TOKEN_BOOLEAN,       // true -or- false
67 			TOKEN_NULL           // null
68 		};
69 
70 		Type nType;
71 		std::string sValue;
72 
73 		// for malformed file debugging
74 		Reader::Location locBegin;
75 		Reader::Location locEnd;
76 	};
77 
78 	class InputStream;
79 	class TokenStream;
80 	typedef std::vector<Token> Tokens;
81 
82 	// scanning istream into token sequence
83 	void Scan(Tokens& tokens, InputStream& inputStream);
84 
85 	void EatWhiteSpace(InputStream& inputStream);
86 	void MatchString(std::string& sValue, InputStream& inputStream);
87 	void MatchNumber(std::string& sNumber, InputStream& inputStream);
88 	void MatchExpectedString(std::string const& sExpected, InputStream& inputStream);
89 
90 	// parsing token sequence into element structure
91 	UnknownElement Parse(TokenStream& tokenStream);
92 	UnknownElement ParseObject(TokenStream& tokenStream);
93 	UnknownElement ParseArray(TokenStream& tokenStream);
94 	UnknownElement ParseString(TokenStream& tokenStream);
95 	UnknownElement ParseNumber(TokenStream& tokenStream);
96 	UnknownElement ParseBoolean(TokenStream& tokenStream);
97 	UnknownElement ParseNull(TokenStream& tokenStream);
98 
99 	std::string const& MatchExpectedToken(Token::Type nExpected, TokenStream& tokenStream);
100 };
101 
102 }
103