this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Guido Tack <tack@gecode.org>
5 *
6 * Copyright:
7 * Guido Tack, 2007
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#ifndef GECODE_FLATZINC_AST_HH
35#define GECODE_FLATZINC_AST_HH
36
37#include <vector>
38#include <string>
39#include <iostream>
40#include <cstdlib>
41
42/**
43 * \namespace Gecode::FlatZinc::AST
44 * \brief Abstract syntax trees for the %FlatZinc interpreter
45 */
46
47namespace Gecode { namespace FlatZinc { namespace AST {
48
49 class Call;
50 class Array;
51 class Atom;
52 class SetLit;
53
54 /// %Exception signaling type error
55 class GECODE_VTABLE_EXPORT TypeError {
56 private:
57 std::string _what;
58 public:
59 TypeError() : _what("") {}
60 TypeError(std::string what) : _what(what) {}
61 std::string what(void) const { return _what; }
62 };
63
64 /**
65 * \brief A node in a %FlatZinc abstract syntax tree
66 */
67 class GECODE_VTABLE_EXPORT Node {
68 public:
69 /// Destructor
70 virtual ~Node(void);
71
72 /// Append \a n to an array node
73 void append(Node* n);
74
75 /// Test if node has atom with \a id
76 bool hasAtom(const std::string& id);
77 /// Test if node is int, if yes set \a i to the value
78 bool isInt(int& i);
79 /// Test if node is float, if yes set \a d to the value
80 bool isFloat(double& i);
81 /// Test if node is function call with \a id
82 bool isCall(const std::string& id);
83 /// Return function call
84 Call* getCall(void);
85 /// Test if node is function call or array containing function call \a id
86 bool hasCall(const std::string& id);
87 /// Return function call \a id
88 Call* getCall(const std::string& id);
89 /// Cast this node to an array node
90 Array* getArray(void);
91 /// Cast this node to an Atom node
92 Atom* getAtom(void);
93 /// Return name of variable represented by this node
94 std::string getVarName(void);
95 /// Cast this node to an integer variable node
96 int getIntVar(void);
97 /// Cast this node to a Boolean variable node
98 int getBoolVar(void);
99 /// Cast this node to a Float variable node
100 int getFloatVar(void);
101 /// Cast this node to a set variable node
102 int getSetVar(void);
103
104 /// Cast this node to an integer node
105 int getInt(void);
106 /// Cast this node to a Boolean node
107 bool getBool(void);
108 /// Cast this node to a Float node
109 double getFloat(void);
110 /// Cast this node to a set literal node
111 SetLit *getSet(void);
112
113 /// Cast this node to a string node
114 std::string getString(void);
115
116 /// Test if node is an integer variable node
117 bool isIntVar(void);
118 /// Test if node is a Boolean variable node
119 bool isBoolVar(void);
120 /// Test if node is a set variable node
121 bool isSetVar(void);
122 /// Test if node is a float variable node
123 bool isFloatVar(void);
124 /// Test if node is an integer node
125 bool isInt(void);
126 /// Test if node is a float node
127 bool isFloat(void);
128 /// Test if node is a Boolean node
129 bool isBool(void);
130 /// Test if node is a string node
131 bool isString(void);
132 /// Test if node is an array node
133 bool isArray(void);
134 /// Test if node is a set literal node
135 bool isSet(void);
136 /// Test if node is an atom node
137 bool isAtom(void);
138
139 /// Output string representation
140 virtual void print(std::ostream&) = 0;
141 };
142
143 /// Boolean literal node
144 class GECODE_VTABLE_EXPORT BoolLit : public Node {
145 public:
146 bool b;
147 BoolLit(bool b0) : b(b0) {}
148 virtual void print(std::ostream& os) {
149 os << "b(" << (b ? "true" : "false") << ")";
150 }
151 };
152 /// Integer literal node
153 class GECODE_VTABLE_EXPORT IntLit : public Node {
154 public:
155 int i;
156 IntLit(int i0) : i(i0) {}
157 virtual void print(std::ostream& os) {
158 os << "i("<<i<<")";
159 }
160 };
161 /// Float literal node
162 class GECODE_VTABLE_EXPORT FloatLit : public Node {
163 public:
164 double d;
165 FloatLit(double d0) : d(d0) {}
166 virtual void print(std::ostream& os) {
167 os << "f("<<d<<")";
168 }
169 };
170 /// %Set literal node
171 class GECODE_VTABLE_EXPORT SetLit : public Node {
172 public:
173 bool interval;
174 int min; int max;
175 std::vector<int> s;
176 SetLit(void) {}
177 SetLit(int min0, int max0) : interval(true), min(min0), max(max0) {}
178 SetLit(const std::vector<int>& s0) : interval(false), s(s0) {}
179 explicit SetLit(SetLit* s0) : interval(s0->interval), min(s0->min), max(s0->max), s(s0->s) {}
180 bool empty(void) const {
181 return ( (interval && min>max) || (!interval && s.size() == 0));
182 }
183 virtual void print(std::ostream& os) {
184 os << "s()";
185 }
186 };
187
188 /// Variable node base class
189 class GECODE_VTABLE_EXPORT Var : public Node {
190 public:
191 int i; //< Index
192 std::string n; //< Name
193 /// Constructor
194 Var(int i0, const std::string& n0) : i(i0), n(n0) {}
195 };
196 /// Boolean variable node
197 class GECODE_VTABLE_EXPORT BoolVar : public Var {
198 public:
199 /// Constructor
200 BoolVar(int i0, const std::string& n0="") : Var(i0,n0) {}
201 virtual void print(std::ostream& os) {
202 os << "xb("<<i<<")";
203 }
204 };
205 /// Integer variable node
206 class GECODE_VTABLE_EXPORT IntVar : public Var {
207 public:
208 IntVar(int i0, const std::string& n0="") : Var(i0,n0) {}
209 virtual void print(std::ostream& os) {
210 os << "xi("<<i<<")";
211 }
212 };
213 /// Float variable node
214 class GECODE_VTABLE_EXPORT FloatVar : public Var {
215 public:
216 FloatVar(int i0, const std::string& n0="") : Var(i0,n0) {}
217 virtual void print(std::ostream& os) {
218 os << "xf("<<i<<")";
219 }
220 };
221 /// %Set variable node
222 class GECODE_VTABLE_EXPORT SetVar : public Var {
223 public:
224 SetVar(int i0, const std::string& n0="") : Var(i0,n0) {}
225 virtual void print(std::ostream& os) {
226 os << "xs("<<i<<")";
227 }
228 };
229
230 /// %Array node
231 class GECODE_VTABLE_EXPORT Array : public Node {
232 public:
233 std::vector<Node*> a;
234 Array(const std::vector<Node*>& a0)
235 : a(a0) {}
236 Array(Node* n)
237 : a(1) { a[0] = n; }
238 Array(int n=0) : a(n) {}
239 virtual void print(std::ostream& os) {
240 os << "[";
241 for (unsigned int i=0; i<a.size(); i++) {
242 a[i]->print(os);
243 if (i<a.size()-1)
244 os << ", ";
245 }
246 os << "]";
247 }
248 ~Array(void) {
249 for (int i=a.size(); i--;)
250 delete a[i];
251 }
252 };
253
254 /// %Node representing a function call
255 class GECODE_VTABLE_EXPORT Call : public Node {
256 public:
257 std::string id;
258 Node* args;
259 Call(const std::string& id0, Node* args0)
260 : id(id0), args(args0) {}
261 ~Call(void) { delete args; }
262 virtual void print(std::ostream& os) {
263 os << id << "("; args->print(os); os << ")";
264 }
265 Array* getArgs(unsigned int n) {
266 Array *a = args->getArray();
267 if (a->a.size() != n)
268 throw TypeError("arity mismatch");
269 return a;
270 }
271 };
272
273 /// %Node representing an array access
274 class GECODE_VTABLE_EXPORT ArrayAccess : public Node {
275 public:
276 Node* a;
277 Node* idx;
278 ArrayAccess(Node* a0, Node* idx0)
279 : a(a0), idx(idx0) {}
280 ~ArrayAccess(void) { delete a; delete idx; }
281 virtual void print(std::ostream& os) {
282 a->print(os);
283 os << "[";
284 idx->print(os);
285 os << "]";
286 }
287 };
288
289 /// %Node representing an atom
290 class GECODE_VTABLE_EXPORT Atom : public Node {
291 public:
292 std::string id;
293 Atom(const std::string& id0) : id(id0) {}
294 virtual void print(std::ostream& os) {
295 os << id;
296 }
297 };
298
299 /// %String node
300 class GECODE_VTABLE_EXPORT String : public Node {
301 public:
302 std::string s;
303 String(const std::string& s0) : s(s0) {}
304 virtual void print(std::ostream& os) {
305 os << "s(\"" << s << "\")";
306 }
307 };
308
309 inline
310 Node::~Node(void) {}
311
312 inline void
313 Node::append(Node* newNode) {
314 Array* a = dynamic_cast<Array*>(this);
315 if (!a)
316 throw TypeError("array expected");
317 a->a.push_back(newNode);
318 }
319
320 inline bool
321 Node::hasAtom(const std::string& id) {
322 if (Array* a = dynamic_cast<Array*>(this)) {
323 for (int i=a->a.size(); i--;)
324 if (Atom* at = dynamic_cast<Atom*>(a->a[i]))
325 if (at->id == id)
326 return true;
327 } else if (Atom* a = dynamic_cast<Atom*>(this)) {
328 return a->id == id;
329 }
330 return false;
331 }
332
333 inline bool
334 Node::isCall(const std::string& id) {
335 if (Call* a = dynamic_cast<Call*>(this)) {
336 if (a->id == id)
337 return true;
338 }
339 return false;
340 }
341
342 inline Call*
343 Node::getCall(void) {
344 if (Call* a = dynamic_cast<Call*>(this))
345 return a;
346 throw TypeError("call expected");
347 }
348
349 inline bool
350 Node::hasCall(const std::string& id) {
351 if (Array* a = dynamic_cast<Array*>(this)) {
352 for (int i=a->a.size(); i--;)
353 if (Call* at = dynamic_cast<Call*>(a->a[i]))
354 if (at->id == id) {
355 return true;
356 }
357 } else if (Call* a = dynamic_cast<Call*>(this)) {
358 return a->id == id;
359 }
360 return false;
361 }
362
363 inline bool
364 Node::isInt(int& i) {
365 if (IntLit* il = dynamic_cast<IntLit*>(this)) {
366 i = il->i;
367 return true;
368 }
369 return false;
370 }
371
372 inline bool
373 Node::isFloat(double& d) {
374 if (FloatLit* fl = dynamic_cast<FloatLit*>(this)) {
375 d = fl->d;
376 return true;
377 }
378 return false;
379 }
380
381 inline Call*
382 Node::getCall(const std::string& id) {
383 if (Array* a = dynamic_cast<Array*>(this)) {
384 for (int i=a->a.size(); i--;)
385 if (Call* at = dynamic_cast<Call*>(a->a[i]))
386 if (at->id == id)
387 return at;
388 } else if (Call* a = dynamic_cast<Call*>(this)) {
389 if (a->id == id)
390 return a;
391 }
392 throw TypeError("call expected");
393 }
394
395 inline Array*
396 Node::getArray(void) {
397 if (Array* a = dynamic_cast<Array*>(this))
398 return a;
399 throw TypeError("array expected");
400 }
401
402 inline Atom*
403 Node::getAtom(void) {
404 if (Atom* a = dynamic_cast<Atom*>(this))
405 return a;
406 throw TypeError("atom expected");
407 }
408
409 inline std::string
410 Node::getVarName(void) {
411 if (Var* a = dynamic_cast<Var*>(this))
412 return a->n;
413 throw TypeError("variable expected");
414 }
415 inline int
416 Node::getIntVar(void) {
417 if (IntVar* a = dynamic_cast<IntVar*>(this))
418 return a->i;
419 throw TypeError("integer variable expected");
420 }
421 inline int
422 Node::getBoolVar(void) {
423 if (BoolVar* a = dynamic_cast<BoolVar*>(this))
424 return a->i;
425 throw TypeError("bool variable expected");
426 }
427 inline int
428 Node::getFloatVar(void) {
429 if (FloatVar* a = dynamic_cast<FloatVar*>(this))
430 return a->i;
431 throw TypeError("integer variable expected");
432 }
433 inline int
434 Node::getSetVar(void) {
435 if (SetVar* a = dynamic_cast<SetVar*>(this))
436 return a->i;
437 throw TypeError("set variable expected");
438 }
439 inline int
440 Node::getInt(void) {
441 if (IntLit* a = dynamic_cast<IntLit*>(this))
442 return a->i;
443 throw TypeError("integer literal expected");
444 }
445 inline bool
446 Node::getBool(void) {
447 if (BoolLit* a = dynamic_cast<BoolLit*>(this))
448 return a->b;
449 throw TypeError("bool literal expected");
450 }
451 inline double
452 Node::getFloat(void) {
453 if (FloatLit* a = dynamic_cast<FloatLit*>(this))
454 return a->d;
455 throw TypeError("float literal expected");
456 }
457 inline SetLit*
458 Node::getSet(void) {
459 if (SetLit* a = dynamic_cast<SetLit*>(this))
460 return a;
461 throw TypeError("set literal expected");
462 }
463 inline std::string
464 Node::getString(void) {
465 if (String* a = dynamic_cast<String*>(this))
466 return a->s;
467 throw TypeError("string literal expected");
468 }
469 inline bool
470 Node::isIntVar(void) {
471 return (dynamic_cast<IntVar*>(this) != nullptr);
472 }
473 inline bool
474 Node::isBoolVar(void) {
475 return (dynamic_cast<BoolVar*>(this) != nullptr);
476 }
477 inline bool
478 Node::isSetVar(void) {
479 return (dynamic_cast<SetVar*>(this) != nullptr);
480 }
481 inline bool
482 Node::isFloatVar(void) {
483 return (dynamic_cast<FloatVar*>(this) != nullptr);
484 }
485 inline bool
486 Node::isInt(void) {
487 return (dynamic_cast<IntLit*>(this) != nullptr);
488 }
489 inline bool
490 Node::isBool(void) {
491 return (dynamic_cast<BoolLit*>(this) != nullptr);
492 }
493 inline bool
494 Node::isFloat(void) {
495 return (dynamic_cast<FloatLit*>(this) != nullptr);
496 }
497 inline bool
498 Node::isSet(void) {
499 return (dynamic_cast<SetLit*>(this) != nullptr);
500 }
501 inline bool
502 Node::isString(void) {
503 return (dynamic_cast<String*>(this) != nullptr);
504 }
505 inline bool
506 Node::isArray(void) {
507 return (dynamic_cast<Array*>(this) != nullptr);
508 }
509 inline bool
510 Node::isAtom(void) {
511 return (dynamic_cast<Atom*>(this) != nullptr);
512 }
513
514 inline Node*
515 extractSingleton(Node* n) {
516 if (Array* a = dynamic_cast<Array*>(n)) {
517 if (a->a.size() == 1) {
518 Node *ret = a->a[0];
519 a->a[0] = nullptr;
520 delete a;
521 return ret;
522 }
523 }
524 return n;
525 }
526
527}}}
528
529#endif
530
531// STATISTICS: flatzinc-any