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/util.hpp"
19
20 #include <sstream>
21 #include <stdexcept>
22
23 #include "sexp/io.hpp"
24
25 namespace sexp {
26
27 bool
is_list(Value const & sx)28 is_list(Value const& sx)
29 {
30 if (sx.is_nil())
31 {
32 return true;
33 }
34 else if (sx.is_cons())
35 {
36 return is_list(sx.get_cdr());
37 }
38 else
39 {
40 return false;
41 }
42 }
43
44 int
list_length(Value const & sx)45 list_length(Value const& sx)
46 {
47 if (sx.is_nil())
48 {
49 return 0;
50 }
51 else if (sx.is_cons())
52 {
53 return 1 + list_length(sx.get_cdr());
54 }
55 else
56 {
57 // silently ignoring malformed list content
58 return 0;
59 }
60 }
61
62 Value const&
list_ref(Value const & sx,int index)63 list_ref(Value const& sx, int index)
64 {
65 if (index == 0)
66 {
67 return sx.get_car();
68 }
69 else
70 {
71 return list_ref(sx.get_cdr(), index - 1);
72 }
73 }
74
75 Value const&
assoc_ref(Value const & sx,std::string const & key)76 assoc_ref(Value const& sx, std::string const& key)
77 {
78 if (sx.is_nil())
79 {
80 return Value::nil_ref();
81 }
82 else if (sx.is_cons())
83 {
84 Value const& pair = sx.get_car();
85 if (pair.is_cons() &&
86 pair.get_car().is_symbol() &&
87 pair.get_car().as_string() == key)
88 {
89 return pair.get_cdr();
90 }
91 else
92 {
93 return assoc_ref(sx.get_cdr(), key);
94 }
95 }
96 else
97 {
98 std::ostringstream msg;
99 msg << "malformed input to sexp::assoc_ref(): sx:\"" << sx << "\" key:\"" << key << "\"";
100 throw std::runtime_error(msg.str());
101 }
102 }
103
104 } // namespace sexp
105
106 /* EOF */
107