1 #pragma once
2 
3 #include "tokens.hpp"
4 #include "hocon/config_exception.hpp"
5 #include <hocon/config_syntax.hpp>
6 
7 #include <boost/nowide/fstream.hpp>
8 #include <vector>
9 #include <queue>
10 #include <string>
11 
12 namespace hocon {
13 
14     // This exception should not leave this file
15     class problem_exception : std::runtime_error {
16     public:
17         problem_exception(problem prob);
18         problem const& get_problem() const;
19 
20     private:
21         problem _problem;
22     };
23 
24     class iterator {
25     public:
26         virtual bool has_next() = 0;
27         virtual shared_token next() = 0;
28     };
29 
30     template <typename iter>
31     class iterator_wrapper : public iterator {
32     public:
iterator_wrapper(iter begin,iter end)33         iterator_wrapper(iter begin, iter end)
34             : _cur(begin), _end(end) { }
35 
has_next()36         bool has_next() override {
37             return _cur != _end;
38         }
39 
next()40         shared_token next() override {
41             return *_cur++;
42         }
43 
44     private:
45         iter _cur;
46         iter _end;
47     };
48 
49     class token_iterator : public iterator {
50     public:
51         token_iterator(shared_origin origin, std::unique_ptr<std::istream> input, bool allow_comments);
52         token_iterator(shared_origin origin, std::unique_ptr<std::istream> input, config_syntax flavor);
53 
54         bool has_next() override;
55         shared_token next() override;
56 
57         static std::string render(token_list tokens);
58 
59     private:
60         class whitespace_saver {
61         public:
62             whitespace_saver();
63             void add(char c);
64             shared_token check(token_type type, shared_origin base_origin, int line_number);
65 
66         private:
67             shared_token next_is_not_simple_value(shared_origin base_origin, int line_number);
68             shared_token next_is_simple_value(shared_origin origin, int line_number);
69             shared_token create_whitespace_token(shared_origin base_origin, int line_number);
70 
71             std::string _whitespace;
72             bool _last_token_was_simple_value;
73         };
74 
75         bool start_of_comment(char c);
76         shared_token pull_comment(char first_char);
77 
78         /** Get next char, skipping newline whitespace */
79         char next_char_after_whitespace(whitespace_saver& saver);
80 
81         /**
82          * The rules here are intended to maximize convenience while
83          * avoiding confusion with real valid JSON. Basically anything
84          * that parses as JSON is treated the JSON way and otherwise
85          * we assume it's a string and let the parser sort it out.
86          */
87         shared_token pull_unquoted_text();
88 
89         shared_token pull_number(char first_char);
90 
91         /**
92          * @param parsed The string with the escape sequence parsed.
93          * @param original The string with the escape sequence left as in the original text
94          */
95         void pull_escape_sequence(std::string& parsed, std::string& original);
96 
97         void append_triple_quoted_string(std::string& parsed, std::string& original);
98 
99         shared_token pull_quoted_string();
100 
101         shared_token const& pull_plus_equals();
102         shared_token pull_substitution();
103         shared_token pull_next_token(whitespace_saver& saver);
104         void queue_next_token();
105 
106         static bool is_simple_value(token_type type);
107         static std::string as_string(char c);
108         static shared_origin line_origin(shared_origin base_origin, int line_number);
109 
110         shared_origin _origin;
111         std::unique_ptr<std::istream> _input;
112         bool _allow_comments;
113         int _line_number;
114         shared_origin _line_origin;
115         std::queue<shared_token> _tokens;
116         whitespace_saver _whitespace_saver;
117     };
118 
119     class single_token_iterator : public iterator {
120     public:
121         single_token_iterator(shared_token token);
122 
123         bool has_next() override;
124         shared_token next() override;
125 
126     private:
127         shared_token _token;
128         bool _has_next;
129     };
130 
131     class token_list_iterator : public iterator {
132     public:
133         token_list_iterator(token_list tokens);
134 
135         bool has_next() override;
136         shared_token next() override;
137 
138     private:
139         token_list _tokens;
140         int _index;
141     };
142 
143 }  // namespace hocon
144