1 | // SExp - A S-Expression Parser for C++ |
---|---|
2 | // Copyright (C) 2006 Matthias Braun <matze@braunis.de> |
3 | // 2015 Ingo Ruhnke <grumbel@gmail.com> |
4 | // |
5 | // This program is free software: you can redistribute it and/or modify |
6 | // it under the terms of the GNU General Public License as published by |
7 | // the Free Software Foundation, either version 3 of the License, or |
8 | // (at your option) any later version. |
9 | // |
10 | // This program is distributed in the hope that it will be useful, |
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | // GNU General Public License for more details. |
14 | // |
15 | // You should have received a copy of the GNU General Public License |
16 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | |
18 | #include "sexp/io.hpp" |
19 | |
20 | #include <sstream> |
21 | |
22 | #include "float.hpp" |
23 | |
24 | namespace sexp { |
25 | |
26 | void escape_string(std::ostream& os, std::string const& text) |
27 | { |
28 | os << '"'; |
29 | for(size_t i = 0; i < text.size(); ++i) |
30 | { |
31 | if (text[i] == '"') |
32 | { |
33 | os << "\\\""; |
34 | } |
35 | else if (text[i] == '\\') |
36 | { |
37 | os << "\\\\"; |
38 | } |
39 | else |
40 | { |
41 | os << text[i]; |
42 | } |
43 | } |
44 | os << '"'; |
45 | } |
46 | |
47 | std::ostream& operator<<(std::ostream& os, Value const& sx) |
48 | { |
49 | switch(sx.get_type()) |
50 | { |
51 | case Value::Type::NIL: |
52 | os << "()"; |
53 | break; |
54 | |
55 | case Value::Type::CONS: |
56 | { |
57 | os << '('; |
58 | Value const* cur = &sx; |
59 | do |
60 | { |
61 | if (cur->get_type() != Value::Type::CONS) |
62 | { |
63 | os << ". "<< *cur; |
64 | break; |
65 | } |
66 | else |
67 | { |
68 | os << cur->get_car(); |
69 | cur = &cur->get_cdr(); |
70 | if (*cur) |
71 | { |
72 | os << ' '; |
73 | } |
74 | } |
75 | } |
76 | while(*cur); |
77 | os << ')'; |
78 | } |
79 | break; |
80 | |
81 | case Value::Type::STRING: |
82 | escape_string(os, sx.as_string()); |
83 | break; |
84 | |
85 | case Value::Type::INTEGER: |
86 | os << sx.as_int(); |
87 | break; |
88 | |
89 | case Value::Type::REAL: |
90 | float2string(os, sx.as_float()); |
91 | break; |
92 | |
93 | case Value::Type::SYMBOL: |
94 | os << sx.as_string(); |
95 | break; |
96 | |
97 | case Value::Type::BOOLEAN: |
98 | os << (sx.as_bool() ? "#t": "#f"); |
99 | break; |
100 | |
101 | case Value::Type::ARRAY: |
102 | { |
103 | os << "#("; |
104 | auto const& arr = sx.as_array(); |
105 | for(size_t i = 0; i != arr.size(); ++i) |
106 | { |
107 | if (i != 0) { os << ' '; } |
108 | os << arr[i]; |
109 | } |
110 | os << ")"; |
111 | } |
112 | break; |
113 | } |
114 | |
115 | return os; |
116 | } |
117 | |
118 | } // namespace sexp |
119 | |
120 | /* EOF */ |
121 |