1 // SExp - A S-Expression Parser for C++
2 // Copyright (C) 2015 Ingo Ruhnke <grumbel@gmail.com>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef HEADER_SEXP_UTIL_HPP
18 #define HEADER_SEXP_UTIL_HPP
19 
20 #include <sexp/value.hpp>
21 
22 namespace sexp {
23 
24 class Value;
25 
car(Value & sx)26 inline Value& car(Value& sx) { return sx.get_car(); }
cdr(Value & sx)27 inline Value& cdr(Value& sx) { return sx.get_cdr(); }
caar(Value & sx)28 inline Value& caar(Value& sx) { return sx.get_car().get_car(); }
cadr(Value & sx)29 inline Value& cadr(Value& sx) { return sx.get_car().get_cdr(); }
cdar(Value & sx)30 inline Value& cdar(Value& sx) { return sx.get_cdr().get_car(); }
cddr(Value & sx)31 inline Value& cddr(Value& sx) { return sx.get_cdr().get_cdr(); }
caaar(Value & sx)32 inline Value& caaar(Value& sx) { return sx.get_car().get_car().get_car(); }
caadr(Value & sx)33 inline Value& caadr(Value& sx) { return sx.get_car().get_car().get_cdr(); }
cadar(Value & sx)34 inline Value& cadar(Value& sx) { return sx.get_car().get_cdr().get_car(); }
caddr(Value & sx)35 inline Value& caddr(Value& sx) { return sx.get_car().get_cdr().get_cdr(); }
cdaar(Value & sx)36 inline Value& cdaar(Value& sx) { return sx.get_cdr().get_car().get_car(); }
cdadr(Value & sx)37 inline Value& cdadr(Value& sx) { return sx.get_cdr().get_car().get_cdr(); }
cddar(Value & sx)38 inline Value& cddar(Value& sx) { return sx.get_cdr().get_cdr().get_car(); }
cdddr(Value & sx)39 inline Value& cdddr(Value& sx) { return sx.get_cdr().get_cdr().get_cdr(); }
caaaar(Value & sx)40 inline Value& caaaar(Value& sx) { return sx.get_car().get_car().get_car().get_car(); }
caaadr(Value & sx)41 inline Value& caaadr(Value& sx) { return sx.get_car().get_car().get_car().get_cdr(); }
caadar(Value & sx)42 inline Value& caadar(Value& sx) { return sx.get_car().get_car().get_cdr().get_car(); }
caaddr(Value & sx)43 inline Value& caaddr(Value& sx) { return sx.get_car().get_car().get_cdr().get_cdr(); }
cadaar(Value & sx)44 inline Value& cadaar(Value& sx) { return sx.get_car().get_cdr().get_car().get_car(); }
cadadr(Value & sx)45 inline Value& cadadr(Value& sx) { return sx.get_car().get_cdr().get_car().get_cdr(); }
caddar(Value & sx)46 inline Value& caddar(Value& sx) { return sx.get_car().get_cdr().get_cdr().get_car(); }
cadddr(Value & sx)47 inline Value& cadddr(Value& sx) { return sx.get_car().get_cdr().get_cdr().get_cdr(); }
cdaaar(Value & sx)48 inline Value& cdaaar(Value& sx) { return sx.get_cdr().get_car().get_car().get_car(); }
cdaadr(Value & sx)49 inline Value& cdaadr(Value& sx) { return sx.get_cdr().get_car().get_car().get_cdr(); }
cdadar(Value & sx)50 inline Value& cdadar(Value& sx) { return sx.get_cdr().get_car().get_cdr().get_car(); }
cdaddr(Value & sx)51 inline Value& cdaddr(Value& sx) { return sx.get_cdr().get_car().get_cdr().get_cdr(); }
cddaar(Value & sx)52 inline Value& cddaar(Value& sx) { return sx.get_cdr().get_cdr().get_car().get_car(); }
cddadr(Value & sx)53 inline Value& cddadr(Value& sx) { return sx.get_cdr().get_cdr().get_car().get_cdr(); }
cdddar(Value & sx)54 inline Value& cdddar(Value& sx) { return sx.get_cdr().get_cdr().get_cdr().get_car(); }
cddddr(Value & sx)55 inline Value& cddddr(Value& sx) { return sx.get_cdr().get_cdr().get_cdr().get_cdr(); }
56 
car(Value const & sx)57 inline Value const& car(Value const& sx) { return sx.get_car(); }
cdr(Value const & sx)58 inline Value const& cdr(Value const& sx) { return sx.get_cdr(); }
caar(Value const & sx)59 inline Value const& caar(Value const& sx) { return sx.get_car().get_car(); }
cadr(Value const & sx)60 inline Value const& cadr(Value const& sx) { return sx.get_car().get_cdr(); }
cdar(Value const & sx)61 inline Value const& cdar(Value const& sx) { return sx.get_cdr().get_car(); }
cddr(Value const & sx)62 inline Value const& cddr(Value const& sx) { return sx.get_cdr().get_cdr(); }
caaar(Value const & sx)63 inline Value const& caaar(Value const& sx) { return sx.get_car().get_car().get_car(); }
caadr(Value const & sx)64 inline Value const& caadr(Value const& sx) { return sx.get_car().get_car().get_cdr(); }
cadar(Value const & sx)65 inline Value const& cadar(Value const& sx) { return sx.get_car().get_cdr().get_car(); }
caddr(Value const & sx)66 inline Value const& caddr(Value const& sx) { return sx.get_car().get_cdr().get_cdr(); }
cdaar(Value const & sx)67 inline Value const& cdaar(Value const& sx) { return sx.get_cdr().get_car().get_car(); }
cdadr(Value const & sx)68 inline Value const& cdadr(Value const& sx) { return sx.get_cdr().get_car().get_cdr(); }
cddar(Value const & sx)69 inline Value const& cddar(Value const& sx) { return sx.get_cdr().get_cdr().get_car(); }
cdddr(Value const & sx)70 inline Value const& cdddr(Value const& sx) { return sx.get_cdr().get_cdr().get_cdr(); }
caaaar(Value const & sx)71 inline Value const& caaaar(Value const& sx) { return sx.get_car().get_car().get_car().get_car(); }
caaadr(Value const & sx)72 inline Value const& caaadr(Value const& sx) { return sx.get_car().get_car().get_car().get_cdr(); }
caadar(Value const & sx)73 inline Value const& caadar(Value const& sx) { return sx.get_car().get_car().get_cdr().get_car(); }
caaddr(Value const & sx)74 inline Value const& caaddr(Value const& sx) { return sx.get_car().get_car().get_cdr().get_cdr(); }
cadaar(Value const & sx)75 inline Value const& cadaar(Value const& sx) { return sx.get_car().get_cdr().get_car().get_car(); }
cadadr(Value const & sx)76 inline Value const& cadadr(Value const& sx) { return sx.get_car().get_cdr().get_car().get_cdr(); }
caddar(Value const & sx)77 inline Value const& caddar(Value const& sx) { return sx.get_car().get_cdr().get_cdr().get_car(); }
cadddr(Value const & sx)78 inline Value const& cadddr(Value const& sx) { return sx.get_car().get_cdr().get_cdr().get_cdr(); }
cdaaar(Value const & sx)79 inline Value const& cdaaar(Value const& sx) { return sx.get_cdr().get_car().get_car().get_car(); }
cdaadr(Value const & sx)80 inline Value const& cdaadr(Value const& sx) { return sx.get_cdr().get_car().get_car().get_cdr(); }
cdadar(Value const & sx)81 inline Value const& cdadar(Value const& sx) { return sx.get_cdr().get_car().get_cdr().get_car(); }
cdaddr(Value const & sx)82 inline Value const& cdaddr(Value const& sx) { return sx.get_cdr().get_car().get_cdr().get_cdr(); }
cddaar(Value const & sx)83 inline Value const& cddaar(Value const& sx) { return sx.get_cdr().get_cdr().get_car().get_car(); }
cddadr(Value const & sx)84 inline Value const& cddadr(Value const& sx) { return sx.get_cdr().get_cdr().get_car().get_cdr(); }
cdddar(Value const & sx)85 inline Value const& cdddar(Value const& sx) { return sx.get_cdr().get_cdr().get_cdr().get_car(); }
cddddr(Value const & sx)86 inline Value const& cddddr(Value const& sx) { return sx.get_cdr().get_cdr().get_cdr().get_cdr(); }
87 
88 int list_length(Value const& sx);
89 Value const& list_ref(Value const& sx, int index);
90 bool is_list(Value const& sx);
91 Value const& assoc_ref(Value const& sx, std::string const& key);
92 
93 class ListIterator
94 {
95 private:
96   Value const* cur;
97 
98 public:
ListIterator()99   ListIterator() :
100     cur(nullptr)
101   {}
102 
ListIterator(Value const & sx)103   ListIterator(Value const& sx) :
104     cur(!sx.is_cons() ? nullptr : &sx)
105   {}
106 
operator ==(ListIterator const & rhs) const107   bool operator==(ListIterator const& rhs) const { return cur == rhs.cur; }
operator !=(ListIterator const & rhs) const108   bool operator!=(ListIterator const& rhs) const { return cur != rhs.cur; }
109 
operator *() const110   Value const& operator*() const { return cur->get_car(); /* NOLINT */ }
operator ->() const111   Value const* operator->() const { return &cur->get_car(); }
112 
operator ++()113   ListIterator& operator++()
114   {
115     if (cur)
116     {
117       cur = &cur->get_cdr();
118       if (!cur->is_cons())
119       {
120         // if the list is malformed we stop at the last valid element
121         // and silently ignore the rest
122         cur = nullptr;
123       }
124     }
125     return *this;
126   }
127 
operator ++(int)128   ListIterator operator++(int)
129   {
130     ListIterator tmp = *this;
131     operator++();
132     return tmp;
133   }
134 };
135 
136 class ListAdapter
137 {
138 private:
139   Value const& m_sx;
140 
141 public:
ListAdapter(Value const & sx)142   ListAdapter(Value const& sx) :
143     m_sx(sx)
144   {}
145 
begin() const146   ListIterator begin() const { return ListIterator(m_sx); }
end() const147   ListIterator end() const { return ListIterator(); }
148 };
149 
150 } // namespace sexp
151 
152 #endif
153 
154 /* EOF */
155