summaryrefslogtreecommitdiff
path: root/src/util/sexpr.h
blob: 7e326247b1a80903021c5d0efbd5b54af70d21ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/*********************                                                        */
/*! \file sexpr.h
 ** \verbatim
 ** Top contributors (to current version):
 **   Tim King, Morgan Deters, Christopher L. Conway
 ** This file is part of the CVC4 project.
 ** Copyright (c) 2009-2017 by the authors listed in the file AUTHORS
 ** in the top-level source directory) and their institutional affiliations.
 ** All rights reserved.  See the file COPYING in the top-level source
 ** directory for licensing information.\endverbatim
 **
 ** \brief Simple representation of S-expressions
 **
 ** Simple representation of S-expressions.
 ** These are used when a simple, and obvious interface for basic
 ** expressions is appropraite.
 **
 ** These are quite ineffecient.
 ** These are totally disconnected from any ExprManager.
 ** These keep unique copies of all of their children.
 ** These are VERY overly verbose and keep much more data than is needed.
 **/

#include "cvc4_public.h"

#ifndef __CVC4__SEXPR_H
#define __CVC4__SEXPR_H

#include <iomanip>
#include <iosfwd>
#include <string>
#include <vector>

#include "base/exception.h"
#include "options/language.h"
#include "util/integer.h"
#include "util/rational.h"

namespace CVC4 {

class CVC4_PUBLIC SExprKeyword {
 public:
  SExprKeyword(const std::string& s) : d_str(s) {}
  const std::string& getString() const { return d_str; }

 private:
  std::string d_str;
}; /* class SExpr::Keyword */

/**
 * A simple S-expression. An S-expression is either an atom with a
 * string value, or a list of other S-expressions.
 */
class CVC4_PUBLIC SExpr {
 public:
  typedef SExprKeyword Keyword;

  SExpr();
  SExpr(const SExpr&);
  SExpr& operator=(const SExpr& other);
  ~SExpr();

  SExpr(const CVC4::Integer& value);

  SExpr(int value);
  SExpr(long int value);
  SExpr(unsigned int value);
  SExpr(unsigned long int value);

  SExpr(const CVC4::Rational& value);

  SExpr(const std::string& value);

  /**
   * This constructs a string expression from a const char* value.
   * This cannot be removed in order to support SExpr("foo").
   * Given the other constructors this SExpr("foo") converts to bool.
   * instead of SExpr(string("foo")).
   */
  SExpr(const char* value);

  /**
   * This adds a convenience wrapper to SExpr to cast from bools.
   * This is internally handled as the strings "true" and "false"
   */
  SExpr(bool value);
  SExpr(const Keyword& value);
  SExpr(const std::vector<SExpr>& children);

  /** Is this S-expression an atom? */
  bool isAtom() const;

  /** Is this S-expression an integer? */
  bool isInteger() const;

  /** Is this S-expression a rational? */
  bool isRational() const;

  /** Is this S-expression a string? */
  bool isString() const;

  /** Is this S-expression a keyword? */
  bool isKeyword() const;

  /**
   * This wraps the toStream() printer.
   * NOTE: toString() and getValue() may differ on Keywords based on
   * the current language set in expr.
   */
  std::string toString() const;

  /**
   * Get the string value of this S-expression. This will cause an
   * error if this S-expression is not an atom.
   */
  std::string getValue() const;

  /**
   * Get the integer value of this S-expression. This will cause an
   * error if this S-expression is not an integer.
   */
  const CVC4::Integer& getIntegerValue() const;

  /**
   * Get the rational value of this S-expression. This will cause an
   * error if this S-expression is not a rational.
   */
  const CVC4::Rational& getRationalValue() const;

  /**
   * Get the children of this S-expression. This will cause an error
   * if this S-expression is not a list.
   */
  const std::vector<SExpr>& getChildren() const;

  /** Is this S-expression equal to another? */
  bool operator==(const SExpr& s) const;

  /** Is this S-expression different from another? */
  bool operator!=(const SExpr& s) const;

  /**
   * This returns the best match in the following order:
   * match atom with
   *  "true", "false" -> SExpr(value)
   * | is and integer -> as integer
   * | is a rational -> as rational
   * | _ -> SExpr()
   */
  static SExpr parseAtom(const std::string& atom);

  /**
   * Parses a list of atoms.
   */
  static SExpr parseListOfAtoms(const std::vector<std::string>& atoms);

  /**
   * Parses a list of list of atoms.
   */
  static SExpr parseListOfListOfAtoms(
      const std::vector<std::vector<std::string> >& atoms_lists);

  /**
   * Outputs the SExpr onto the ostream out. This version reads defaults to the
   * OutputLanguage, language::SetLanguage::getLanguage(out). The indent level
   * is
   * set to 2 if PrettySExprs::getPrettySExprs() is on and is 0 otherwise.
   */
  static void toStream(std::ostream& out, const SExpr& sexpr);

  /**
   * Outputs the SExpr onto the ostream out. This version sets the indent level
   * to 2 if PrettySExprs::getPrettySExprs() is on.
   */
  static void toStream(std::ostream& out, const SExpr& sexpr,
                       OutputLanguage language);

  /**
   * Outputs the SExpr onto the ostream out.
   * If the languageQuotesKeywords(language), then a top level keyword, " X",
   * that needs quoting according to the SMT2 language standard is printed with
   * quotes, "| X|".
   * Otherwise this prints using toStreamRec().
   *
   * TIM: Keywords that are children are not currently quoted. This seems
   * incorrect but I am just reproduicing the old behavior even if it does not
   * make
   * sense.
   */
  static void toStream(std::ostream& out, const SExpr& sexpr,
                       OutputLanguage language, int indent);

 private:
  /**
   * Simple printer for SExpr to an ostream.
   * The current implementation is language independent.
   */
  static void toStreamRec(std::ostream& out, const SExpr& sexpr,
                          OutputLanguage language, int indent);

  /** Returns true if this language quotes Keywords when printing. */
  static bool languageQuotesKeywords(OutputLanguage language);

  enum SExprTypes {
    SEXPR_STRING,
    SEXPR_KEYWORD,
    SEXPR_INTEGER,
    SEXPR_RATIONAL,
    SEXPR_NOT_ATOM
  } d_sexprType;

  /** The value of an atomic integer-valued S-expression. */
  CVC4::Integer d_integerValue;

  /** The value of an atomic rational-valued S-expression. */
  CVC4::Rational d_rationalValue;

  /** The value of an atomic S-expression. */
  std::string d_stringValue;

  typedef std::vector<SExpr> SExprVector;

  /**
   * The children of a list S-expression.
   * Whenever the SExpr isAtom() holds, this points at NULL.
   *
   * This should be a pointer in case the implementation of vector<SExpr> ever
   * directly contained or allocated an SExpr. If this happened this would
   * trigger,
   * either the size being infinite or SExpr() being an infinite loop.
   */
  SExprVector* d_children;
}; /* class SExpr */

/** Prints an SExpr. */
std::ostream& operator<<(std::ostream& out, const SExpr& sexpr) CVC4_PUBLIC;

/**
 * IOStream manipulator to pretty-print SExprs.
 */
class CVC4_PUBLIC PrettySExprs {
  /**
   * The allocated index in ios_base for our setting.
   */
  static const int s_iosIndex;

  /**
   * When this manipulator is used, the setting is stored here.
   */
  bool d_prettySExprs;

 public:
  /**
   * Construct a PrettySExprs with the given setting.
   */
  PrettySExprs(bool prettySExprs) : d_prettySExprs(prettySExprs) {}

  inline void applyPrettySExprs(std::ostream& out) {
    out.iword(s_iosIndex) = d_prettySExprs;
  }

  static inline bool getPrettySExprs(std::ostream& out) {
    return out.iword(s_iosIndex);
  }

  static inline void setPrettySExprs(std::ostream& out, bool prettySExprs) {
    out.iword(s_iosIndex) = prettySExprs;
  }

  /**
   * Set the pretty-sexprs state on the output stream for the current
   * stack scope.  This makes sure the old state is reset on the
   * stream after normal OR exceptional exit from the scope, using the
   * RAII C++ idiom.
   */
  class Scope {
    std::ostream& d_out;
    bool d_oldPrettySExprs;

   public:
    inline Scope(std::ostream& out, bool prettySExprs)
        : d_out(out), d_oldPrettySExprs(PrettySExprs::getPrettySExprs(out)) {
      PrettySExprs::setPrettySExprs(out, prettySExprs);
    }

    inline ~Scope() { PrettySExprs::setPrettySExprs(d_out, d_oldPrettySExprs); }

  }; /* class PrettySExprs::Scope */

}; /* class PrettySExprs */

/**
 * Sets the default pretty-sexprs setting for an ostream.  Use like this:
 *
 *   // let out be an ostream, s an SExpr
 *   out << PrettySExprs(true) << s << endl;
 *
 * The setting stays permanently (until set again) with the stream.
 */
std::ostream& operator<<(std::ostream& out, PrettySExprs ps);

} /* CVC4 namespace */

#endif /* __CVC4__SEXPR_H */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback