libutap  0.93
Uppaal Timed Automata Parser
prettyprinter.cpp
Go to the documentation of this file.
1 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 
3 /* libutap - Uppaal Timed Automata Parser.
4  Copyright (C) 2002-2006 Uppsala University and Aalborg University.
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public License
8  as published by the Free Software Foundation; either version 2.1 of
9  the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  USA
20 */
21 
22 #include "utap/prettyprinter.h"
23 
24 #include <cstring>
25 #include <stack>
26 #include <sstream>
27 #include <stdexcept>
28 
29 using namespace UTAP;
30 using namespace UTAP::Constants;
31 
32 using std::stack;
33 using std::string;
34 using std::ostream;
35 using std::endl;
36 using std::ostringstream;
37 using std::stringstream;
38 
39 static const char *const prefix_label[] =
40 {
41  "", "const ", "urgent ", "", "broadcast ", "", "urgent broadcast ", "",
42  "meta "
43 };
44 
45 void PrettyPrinter::indent()
46 {
47  for (uint32_t i = 0; i < level; i++)
48  {
49  *o.top() << '\t';
50  }
51 }
52 
54 {
55  o.push(&stream);
56 
57  first = true;
58  level = 0;
59  select = guard = sync = update = probability = -1;
60 }
61 
63  uint32_t position, uint32_t offset, uint32_t line, const std::string& path)
64 {
65 
66 }
67 
68 void PrettyPrinter::handleError(const std::string& msg)
69 {
70  throw std::runtime_error(msg);
71 }
72 
73 void PrettyPrinter::handleWarning(const std::string& msg)
74 {
75  throw std::runtime_error(msg);
76 }
77 
78 // FIXME: Scoping of type names is not handled
79 bool PrettyPrinter::isType(const char *name)
80 {
81  return types.find(name) != types.end();
82 }
83 
85 {
86  type.push(type.top());
87 }
88 
90 {
91  type.pop();
92 }
93 
95 {
96  string res;
97  res += prefix_label[prefix];
98  res += "bool";
99  type.push(res);
100 }
101 
103 {
104  string res;
105  res += prefix_label[prefix];
106  res += "int";
107  type.push(res);
108 }
109 
111 {
112  string res;
113  res += prefix_label[prefix];
114  res += "double";
115  type.push(res);
116 }
117 
119 {
120  string l, u;
121  u = st.back();
122  st.pop_back();
123  l = st.back();
124  st.pop_back();
125 
126  string res;
127  res += prefix_label[prefix];
128  res += "int[" + l + "," + u + "]";
129  type.push(res);
130 }
131 
133 {
134  type.push(string(prefix_label[prefix])+"chan");
135 }
136 
138 {
139  type.push(string(prefix_label[prefix])+"clock");
140 }
141 
143 {
144  type.push("void");
145 }
146 
148 {
149  string size = st.back();
150  st.pop_back();
151  string res;
152  res += prefix_label[prefix];
153  res += "scalar[" + size + "]";
154  type.push(res);
155 }
156 
157 void PrettyPrinter::typeName(PREFIX prefix, const char *name)
158 {
159  string res;
160  res += prefix_label[prefix];
161  res += name;
162  type.push(res);
163 }
164 
166 {
167  array.push(st.back());
168  st.pop_back();
169 }
170 
172 {
173  array.push(type.top());
174  type.pop();
175 }
176 void PrettyPrinter::typeStruct(PREFIX prefix, uint32_t n)
177 {
178  stringstream ss;
179  ss << prefix_label[prefix];
180  ss << "struct {\n";
181  assert(fields.size()>=n);
182  for (std::vector<string>::const_iterator
183  i = fields.begin()+(fields.size()-n),
184  e = fields.end(); i != e; ++i)
185  {
186  ss << " " << (*i) << ";\n";
187  }
188  ss << "}";
189  fields.erase(fields.begin()+(fields.size()-n), fields.end());
190  type.push(ss.str());
191 }
192 
193 void PrettyPrinter::structField(const char* name)
194 {
195  stringstream ss;
196  ss << type.top() << " " << name;
197  type.pop();
198  while (!array.empty()) {
199  ss << "[" << array.top() << "]";
200  array.pop();
201  }
202  fields.push_back(ss.str());
203 }
204 
205 void PrettyPrinter::declTypeDef(const char* name)
206 {
207  indent();
208  *o.top() << "typedef " << type.top() << " " << name;
209  type.pop();
210 
211  while (!array.empty())
212  {
213  *o.top() << '[' << array.top() << ']';
214  array.pop();
215  }
216 
217  *o.top() << ';' << endl;
218 
219  types.insert(name);
220 }
221 
222 void PrettyPrinter::declVar(const char *id, bool init)
223 {
224  string i;
225 
226  if (init)
227  {
228  i = st.back();
229  st.pop_back();
230  }
231 
232  indent();
233  *o.top() << type.top() << ' ' << id;
234  type.pop();
235 
236  while (!array.empty())
237  {
238  *o.top() << '[' << array.top() << ']';
239  array.pop();
240  }
241 
242  if (init)
243  {
244  *o.top() << " = " << i;
245  }
246 
247  *o.top() << ';' << endl;
248 }
249 
251 {
252  string s = st.back();
253  st.pop_back();
254  while (--num)
255  {
256  s = st.back() + ", " + s;
257  st.pop_back();
258  }
259  st.push_back("{ " + s + " }");
260 }
261 
262 void PrettyPrinter::exprScenario(const char *name)
263 {
264  string s = "scenario:";
265  s += name;
266  st.push_back(s);
267 }
268 
269 void PrettyPrinter::exprNary(kind_t kind, uint32_t num)
270 {
271  const char *opString = NULL;
272  switch(kind) {
273  case LIST:
274  opString = ", ";
275  break;
276  case TIOCONJUNCTION:
277  opString = " && ";
278  break;
279  case TIOCOMPOSITION:
280  opString = " || ";
281  break;
282  case SYNTAX_COMPOSITION:
283  opString = " + ";
284  break;
285  default:
286  throw TypeException("Invalid operator");
287  }
288 
289  string s = st.back();
290  st.pop_back();
291  while (--num)
292  {
293  s = st.back() + opString + s;
294  st.pop_back();
295  }
296  st.push_back("{ " + s + " }");
297 }
298 
299 void PrettyPrinter::declFieldInit(const char* name)
300 {
301  if (name && strlen(name))
302  {
303  st.back() = string(name) + ": " + st.back();
304  }
305 }
306 
307 void PrettyPrinter::declParameter(const char* name, bool ref)
308 {
309  if (!array.empty())
310  {
311  throw TypeException("Array parameters are not supported");
312  }
313 
314  if (!param.empty()) param += ", ";
315 
316  if (ref)
317  {
318  param += type.top() + " &" + name;
319  }
320  else
321  {
322  param += type.top() + " " + name;
323  }
324  type.pop();
325 }
326 
327 void PrettyPrinter::declFuncBegin(const char* name)
328 {
329  indent();
330  *o.top() << type.top() << " " << name << "(" << param << ")" << endl;
331  indent();
332  *o.top() << "{" << endl;
333  param.clear();
334  level++;
335  type.pop();
336 }
337 
339 {
340  level--;
341  indent();
342  *o.top() << "}" << endl;
343 }
344 
346 {
347  level--;
348  indent();
349  *o.top() << "{" << endl;
350  level++;
351 }
352 
354 {
355  level--; // The level delimiters are indented one level less
356  indent();
357  level++;
358  *o.top() << "}" << endl;
359 }
360 
362 {
363  indent();
364  *o.top() << ';' << endl;
365 }
366 
367 void PrettyPrinter::iterationBegin (const char *id)
368 {
369  indent();
370  *o.top() << "for ( "<< id << " : " << type.top() << " )" << endl;
371  level++;
372  type.pop();
373 }
374 
375 void PrettyPrinter::iterationEnd (const char *id)
376 {
377  *o.top() << endl;
378  level--;
379 }
380 
382 {
383  level++;
384  o.push(new ostringstream());
385 }
386 
387 void PrettyPrinter::forEnd() // 3 expr, 1 stat
388 {
389  string expr3 = st.back(); st.pop_back();
390  string expr2 = st.back(); st.pop_back();
391  string expr1 = st.back(); st.pop_back();
392  ostringstream *s = (ostringstream*)o.top();
393  o.pop();
394 
395  level--;
396  indent();
397  *o.top() << "for ( " << expr1 << "; " << expr2 << "; "
398  << expr3 << ")" << endl
399  << s->str() << endl;
400  delete s;
401 }
402 
404 {
405  level++;
406  o.push(new ostringstream());
407 }
408 
409 void PrettyPrinter::whileEnd() // 1 expr, 1 stat
410 {
411  string expr = st.back(); st.pop_back();
412  ostringstream *s = (ostringstream*)o.top();
413  o.pop();
414 
415  level--;
416  indent();
417 
418  *o.top() << "while (" << expr << ")" << endl
419  << s->str() << endl;
420  delete s;
421 }
422 
424 {
425 
426 }
427 
429 {
430 
431 }
432 
434 {
435  level++;
436  o.push(new ostringstream()); // prepare for THEN statement
437 }
438 
440 {
441 }
442 
444 {
445  o.push(new ostringstream()); // prepare for ELSE statement
446 }
447 
448 void PrettyPrinter::ifEnd(bool hasElse) // 1 expr, 1 or 2 statements
449 {
450  auto e = static_cast<ostringstream*>(o.top()); o.pop(); // ELSE
451  auto t = static_cast<ostringstream*>(o.top()); o.pop(); // THEN
452  auto c = st.back(); st.pop_back(); // COND
453 
454  level--;
455  indent();
456  *o.top() << "if (" << c << ")" << endl
457  << t->str();
458  delete t;
459  if (hasElse)
460  {
461  indent();
462  *o.top() << "else" << endl;
463  *o.top() << e->str();
464  }
465  delete e;
466 }
467 
469 {
470  indent();
471  *o.top() << "break;" << endl;
472 }
473 
475 {
476  indent();
477  *o.top() << "continue;" << endl;
478 }
479 
481 {
482  indent();
483  *o.top() << st.back() << ';' << endl;
484  st.pop_back();
485 }
486 
488 {
489  indent();
490  if (hasValue)
491  {
492  *o.top() << "return " << st.back() << ";" << endl;
493  st.pop_back();
494  }
495  else
496  {
497  *o.top() << "return;" << endl;
498  }
499 }
500 
501 void PrettyPrinter::procBegin(const char *id, const bool isTA,
502  const string type, const string mode)
503 {
504  *o.top() << "process " << (id ? id : "")
505  << templateset
506  << '(' << param << ")" << endl
507  << "{" << endl;
508  param.clear();
509  templateset = "" ;
510 
511  level += 1;
512 }
513 
514 void PrettyPrinter::procState(const char *id, bool hasInvariant, bool hasExpRate)
515 {
516  if (first)
517  {
518  first = false;
519  indent();
520  *o.top() << "state\n";
521  }
522  else
523  {
524  *o.top() << ",\n";
525  }
526 
527  level++;
528  indent();
529  level--;
530 
531  *o.top() << id;
532  string expRate; // pop expressions from stack in reverse order
533  if (hasExpRate)
534  {
535  expRate = st.back();
536  st.pop_back();
537  }
538  if (hasInvariant)
539  {
540  *o.top() << " {" << st.back();
541  st.pop_back();
542  if (hasExpRate) *o.top() << " ; " << expRate;
543  *o.top() << "}";
544  }
545  else if (hasExpRate)
546  {
547  *o.top() << " { ; " << expRate << "}";
548  }
549 }
550 
551 void PrettyPrinter::procBranchpoint(const char *id)
552 {
553  if (!branchpoints.empty()) branchpoints += ", ";
554  branchpoints += id;
555 }
556 
557 void PrettyPrinter::procStateUrgent(const char *id)
558 {
559  if (!urgent.empty()) urgent += ", ";
560  urgent += id;
561 }
562 
563 void PrettyPrinter::procStateCommit(const char *id)
564 {
565  if (!committed.empty()) committed += ", ";
566  committed += id;
567 }
568 
569 void PrettyPrinter::procStateInit(const char *id)
570 {
571  first = true;
572  *o.top() << ";" << endl; // end of states
573 
574  if (!branchpoints.empty())
575  {
576  indent();
577  *o.top() << "branchpoint " << branchpoints << ';' << endl;
578  branchpoints.clear();
579  }
580 
581  if (!committed.empty())
582  {
583  indent();
584  *o.top() << "commit " << committed << ';' << endl;
585  committed.clear();
586  }
587 
588  if (!urgent.empty())
589  {
590  indent();
591  *o.top() << "urgent " << urgent << ';' << endl;
592  urgent.clear();
593  }
594 
595  indent();
596  *o.top() << "init " << id << ';' << endl;
597 }
598 
599 void PrettyPrinter::procSelect(const char *id)
600 {
601  string t = type.top();
602  type.pop();
603  if (select == -1)
604  {
605  st.push_back(string(id) + ":" + t);
606  select = st.size();
607  }
608  else
609  {
610  st.back() += string(", ") + id + ":" + t;
611  }
612 }
613 
615 {
616  guard = st.size();
617 }
618 
620 {
621  switch (type)
622  {
623  case SYNC_QUE:
624  st.back() += '?';
625  break;
626  case SYNC_BANG:
627  st.back() += '!';
628  break;
629  case SYNC_CSP:
630  // no append
631  break;
632  }
633  sync = st.size();
634 }
635 
637 {
638  update = st.size();
639 }
640 
642 {
643  probability = st.size();
644 }
645 
646 void PrettyPrinter::procEdgeBegin(const char* from, const char* to, const bool control)
647 
648 {
649  procEdgeBegin(from, to, control, NULL);
650 }
651 
652 void PrettyPrinter::procEdgeBegin(const char *source, const char *target,
653  const bool control, const char* actname)
654 {
655  if (first)
656  {
657  // this is the first transition
658  first = false;
659 
660  indent();
661  *o.top() << "trans" << endl;
662 
663  level++;
664  }
665  else
666  {
667  *o.top() << ',' << endl;
668  }
669  indent();
670 
671  *o.top() << source << (control ? " -> " : " -u-> ") << target << " {" << endl;
672  if (actname != NULL) {
673  level++;
674  indent();
675  *o.top() << "action " << actname << ";" << endl;
676  level--;
677  }
678 }
679 
680 void PrettyPrinter::procEdgeEnd(const char *source, const char *target)
681 {
682  level++;
683 
684  if (select > -1)
685  {
686  indent();
687  *o.top() << "select " << st[select-1] << ';' << endl;
688  }
689 
690  if (guard > -1)
691  {
692  indent();
693  *o.top() << "guard " << st[guard-1] << ';' << endl;
694  }
695 
696  if (sync > -1)
697  {
698  indent();
699  *o.top() << "sync " << st[sync-1] << ';' << endl;
700  }
701 
702  if (update > -1)
703  {
704  indent();
705  *o.top() << "assign " << st[update-1] << ';' << endl;
706  }
707 
708  if (probability > -1)
709  {
710  indent();
711  *o.top() << "probability " << st[probability-1] << ';' << endl;
712  }
713 
714  level--;
715 
716  if (probability > -1) st.pop_back();
717  if (update > -1) st.pop_back();
718  if (sync > -1) st.pop_back();
719  if (guard > -1) st.pop_back();
720  if (select > -1) st.pop_back();
721 
722  probability = update = sync = guard = select = -1;
723 
724  indent();
725  *o.top() << '}';
726 }
727 
729 {
730  if (!first)
731  {
732  *o.top() << ';' << endl;
733  level--;
734  first = true;
735  }
736  level--;
737  *o.top() << '}' << endl << endl;
738 }
739 
740 void PrettyPrinter::exprId(const char *id)
741 {
742  st.push_back(id);
743 }
744 
745 void PrettyPrinter::exprNat(int32_t n)
746 {
747  char s[20];
748  if (20 <= snprintf(s, 20, "%d", n))
749  {
750  fprintf(stderr, "Error: the integer number was truncated\n");
751  }
752  st.push_back(s);
753 }
754 
756 {
757  char s[60];
758  if (60 <= snprintf(s, 60, "%.52g", d))
759  {
760  fprintf(stderr, "Error: the floating point number was truncated\n");
761  }
762  st.push_back(s);
763 }
764 
766 {
767  st.push_back("true");
768 }
769 
771 {
772  st.push_back("false");
773 }
774 
776 {
777  st.back() += "(";
778 }
779 
781 {
782  string s = ")";
783  while (n--)
784  {
785  s = st.back() + s;
786  st.pop_back();
787  if (n > 0)
788  {
789  s = ", " + s;
790  }
791  }
792  st.back() += s;
793 }
794 
796 {
797  string f = st.back();
798  st.pop_back();
799  st.back() += '[' + f + ']';
800 }
801 
803 {
804  st.back() += "++";
805 }
806 
808 {
809  st.back() = "++" + st.back();
810 }
811 
813 {
814  st.back() += "--";
815 }
816 
818 {
819  st.back() = "--" + st.back();
820 }
821 
822 static
823 const char* getBuiltinFunName(kind_t kind)
824 {
825  // the order must match declarations in include/utap/common.h
826  static const char* funNames[] = {
827  "abs", "fabs", "fmod", "fma", "fmax", "fmin", "fdim",
828  "exp", "exp2", "expm1", "ln", "log", "log10", "log2", "log1p",
829  "pow", "sqrt", "cbrt", "hypot",
830  "sin", "cos", "tan", "asin", "acos", "atan", "atan2",
831  "sinh", "cosh", "tanh", "asinh", "acosh", "atanh",
832  "erf", "erfc", "tgamma", "lgamma",
833  "ceil", "floor", "trunc", "round", "fint",
834  "ldexp", "ilogb", "logb", "nextafter", "copysign",
835  "fpclassify", "isfinite", "isinf", "isnan", "isnormal", "signbit",
836  "isunordered", "random", "random_arcsine", "random_beta",
837  "random_gamma", "random_normal", "random_poisson", "random_weibull",
838  "random_tri"
839  };
840  static_assert(RANDOM_TRI_F-ABS_F+1 == sizeof(funNames)/sizeof(funNames[0]),
841  "Builtin function name list is wrong");
842  assert(ABS_F <= kind && kind <= RANDOM_TRI_F);
843  return funNames[kind-ABS_F];
844 }
845 
846 /*
847 abs ifabs fabs fmod fma fmax fmin fdim
848 exp exp2 expm1 ln log log10 log2 log1p
849 pow sqrt cbrt hypot
850 sin cos tan asin acos atan atan2
851 sinh cosh tanh asinh acosh atanh
852 erf erfc tgamma lgamma
853 ceil floor trunc round
854 iceil ifloor itrunc iround
855 ldexp ilogb logb nextafter copysign
856 fpclassify isfinite isinf isnan isnormal signbit isunordered
857 random
858 */
859 
861 {
862  st.back() = string(getBuiltinFunName(kind)) + '(' + st.back() + ')';
863 }
864 
866 {
867  auto arg2 = st.back(); st.pop_back();
868  st.back() = string(getBuiltinFunName(kind)) + '(' + st.back()+ ',' + arg2 + ')';
869 }
870 
872 {
873  auto arg3 = st.back(); st.pop_back();
874  auto arg2 = st.back(); st.pop_back();
875  st.back() = string(getBuiltinFunName(kind))
876  + '(' + st.back()+ ',' + arg2 + ',' + arg3 + ')';
877 }
878 
880 {
881  string rhs = st.back(); st.pop_back();
882  string lhs = st.back(); st.pop_back();
883 
884  st.push_back(string());
885  switch (op)
886  {
887  case ASSIGN:
888  st.back() = '(' + lhs + " = " + rhs + ')';
889  break;
890  case ASSPLUS:
891  st.back() = '(' + lhs + " += " + rhs + ')';
892  break;
893  case ASSMINUS:
894  st.back() = '(' + lhs + " -= " + rhs + ')';
895  break;
896  case ASSMULT:
897  st.back() = '(' + lhs + " *= " + rhs + ')';
898  break;
899  case ASSDIV:
900  st.back() = '(' + lhs + " /= " + rhs + ')';
901  break;
902  case ASSMOD:
903  st.back() = '(' + lhs + " %= " + rhs + ')';
904  break;
905  case ASSOR:
906  st.back() = '(' + lhs + " |= " + rhs + ')';
907  break;
908  case ASSAND:
909  st.back() = '(' + lhs + " &= " + rhs + ')';
910  break;
911  case ASSXOR:
912  st.back() = '(' + lhs + " ^= " + rhs + ')';
913  break;
914  case ASSLSHIFT:
915  st.back() = '(' + lhs + " <<= " + rhs + ')';
916  break;
917  case ASSRSHIFT:
918  st.back() = '(' + lhs + " >>= " + rhs + ')';
919  break;
920  default:
921  throw TypeException("Invalid assignment operator");
922  }
923 }
924 
926 {
927  string exp = st.back(); st.pop_back();
928 
929  st.push_back(string());
930  switch (op)
931  {
932  case MINUS:
933  st.back() = '-' + exp;
934  break;
935  case NOT:
936  st.back() = '!' + exp;
937  break;
938  case PLUS:
939  st.back() = '+' + exp;
940  break;
941  case RATE:
942  st.back() = exp + '\'';
943  break;
944  case CONTROL_TOPT_DEF2:
945  st.back() = "control_t*: " + exp;
946  break;
947  case CONTROL:
948  st.back() = "control: " + exp;
949  break;
950  case EF_CONTROL:
951  st.back() = "E<> control: " + exp;
952  break;
953  case IMPLEMENTATION:
954  st.back() = "implementation: " + exp;
955  break;
956  case SPECIFICATION:
957  st.back() = "specification: " + exp;
958  break;
959  default:
960  throw TypeException("Invalid operator");
961  }
962 }
963 
965 {
966  string exp2 = st.back(); st.pop_back();
967  string exp1 = st.back(); st.pop_back();
968 
969  st.push_back(string());
970  switch (op)
971  {
972  case PO_CONTROL:
973  st.back() = exp1 + " control: " + exp2;
974  break;
975  case CONTROL_TOPT_DEF1:
976  st.back() = "control_t*(" + exp1 + "): " + exp2;
977  break;
978  case PLUS:
979  st.back() = '(' + exp1 + " + " + exp2 + ')';
980  break;
981  case MINUS:
982  st.back() = '(' + exp1 + " - " + exp2 + ')';
983  break;
984  case MULT:
985  st.back() = '(' + exp1 + " * " + exp2 + ')';
986  break;
987  case DIV:
988  st.back() = '(' + exp1 + " / " + exp2 + ')';
989  break;
990  case MOD:
991  st.back() = '(' + exp1 + " % " + exp2 + ')';
992  break;
993  case FRACTION:
994  st.back() = '(' + exp1 + " : " + exp2 + ')';
995  break;
996  case MIN:
997  st.back() = '(' + exp1 + " <? " + exp2 + ')';
998  break;
999  case MAX:
1000  st.back() = '(' + exp1 + " >? " + exp2 + ')';
1001  break;
1002  case LT:
1003  st.back() = '(' + exp1 + " < " + exp2 + ')';
1004  break;
1005  case SIMULATION_LE:
1006  st.back() = "simulation: " + exp1 + " <= " + exp2;
1007  break;
1008  case REFINEMENT_LE:
1009  st.back() = "refinement: " + exp1 + " <= " + exp2;
1010  break;
1011  case CONSISTENCY:
1012  st.back() = '(' + exp1 + " : " + exp2 + ')';
1013  break;
1014  case TIOQUOTIENT:
1015  st.back() = '(' + exp1 + " \\ " + exp2 + ')';
1016  break;
1017  case LE:
1018  st.back() = '(' + exp1 + " <= " + exp2 + ')';
1019  break;
1020  case EQ:
1021  st.back() = '(' + exp1 + " == " + exp2 + ')';
1022  break;
1023  case NEQ:
1024  st.back() = '(' + exp1 + " != " + exp2 + ')';
1025  break;
1026  case SIMULATION_GE:
1027  st.back() = "simulation: " + exp1 + " >= " + exp2;
1028  break;
1029  case REFINEMENT_GE:
1030  st.back() = "refinement: " + exp1 + " >= " + exp2;
1031  break;
1032  case GE:
1033  st.back() = '(' + exp1 + " >= " + exp2 + ')';
1034  break;
1035  case GT:
1036  st.back() = '(' + exp1 + " > " + exp2 + ')';
1037  break;
1038  case AND:
1039  st.back() = '(' + exp1 + " && " + exp2 + ')';
1040  break;
1041  case OR:
1042  st.back() = '(' + exp1 + " || " + exp2 + ')';
1043  break;
1044  case BIT_AND:
1045  st.back() = '(' + exp1 + " & " + exp2 + ')';
1046  break;
1047  case BIT_OR:
1048  st.back() = '(' + exp1 + " | " + exp2 + ')';
1049  break;
1050  case BIT_XOR:
1051  st.back() = '(' + exp1 + " ^ " + exp2 + ')';
1052  break;
1053  case BIT_LSHIFT:
1054  st.back() = '(' + exp1 + " << " + exp2 + ')';
1055  break;
1056  case BIT_RSHIFT:
1057  st.back() = '(' + exp1 + " >> " + exp2 + ')';
1058  break;
1059  default:
1060  throw TypeException("Invalid operator");
1061  }
1062 }
1063 
1064 
1065 void PrettyPrinter::exprTernary(kind_t op, bool firstMissing)
1066 {
1067  string exp3 = st.back(); st.pop_back();
1068  string exp2 = st.back(); st.pop_back();
1069  string exp1;
1070  if (firstMissing) exp1 = "1";
1071  else { exp1 = st.back(); st.pop_back(); }
1072 
1073  st.push_back(string());
1074  switch (op)
1075  {
1076  case CONTROL_TOPT:
1077  st.back() = "control_t*(" + exp1 + "," + exp2 + "): " + exp3;
1078  break;
1079  case SMC_CONTROL:
1080  st.back() = "control[" + exp1 + "<=" + exp2 + "]: " + exp3;
1081  break;
1082  default:
1083  throw TypeException("Invalid operator");
1084  }
1085 }
1086 
1088 {
1089  string expr3 = st.back(); st.pop_back();
1090  string expr2 = st.back(); st.pop_back();
1091  string expr1 = st.back(); st.pop_back();
1092 
1093  st.push_back(string());
1094  st.back() = expr1 + " ? " + expr2 + " : " + expr3;
1095 }
1096 
1098 {
1099  string expr2 = st.back(); st.pop_back();
1100  string expr1 = st.back(); st.pop_back();
1101 
1102  st.push_back(string());
1103  st.back() = expr1 + ", " + expr2;
1104 }
1105 
1106 void PrettyPrinter::exprDot(const char *field)
1107 {
1108  st.back() = st.back() + "." + field;
1109 }
1110 
1112 {
1113  st.push_back("deadlock");
1114 }
1115 
1116 void PrettyPrinter::exprForAllBegin(const char *name)
1117 {
1118  st.push_back(string("forall (") + name + ":" + type.top() + ") ");
1119  type.pop();
1120 }
1121 
1122 void PrettyPrinter::exprForAllEnd(const char *name)
1123 {
1124  string expr = st.back();
1125  st.pop_back();
1126  st.back() += expr;
1127 }
1128 
1129 void PrettyPrinter::exprExistsBegin(const char *name)
1130 {
1131  st.push_back(string("exists (") + name + ":" + type.top() + ") ");
1132  type.pop();
1133 }
1134 
1135 void PrettyPrinter::exprExistsEnd(const char *name)
1136 {
1137  string expr = st.back();
1138  st.pop_back();
1139  st.back() += expr;
1140 }
1141 
1142 void PrettyPrinter::exprSumBegin(const char *name)
1143 {
1144  st.push_back(string("sum (") + name + ":" + type.top() + ") ");
1145  type.pop();
1146 }
1147 
1148 void PrettyPrinter::exprSumEnd(const char *name)
1149 {
1150  string expr = st.back();
1151  st.pop_back();
1152  st.back() += expr;
1153 }
1154 
1156 {
1157  *o.top() << "{" << endl;
1158  level++;
1159  indent();
1160  level--;
1161  *o.top() << st.back() << endl;
1162  *o.top() << "}" << endl;
1163 }
1164 
1166 {
1167  *o.top() << "{" << endl;
1168  level++;
1169  indent();
1170  level--;
1171  *o.top() << st.back() << endl;
1172  *o.top() << "}" << endl;
1173 }
1174 
1175 void PrettyPrinter::instantiationBegin(const char *id, size_t, const char *templ)
1176 {
1177  // Ignore
1178 }
1179 
1180 void PrettyPrinter::instantiationEnd(const char* id, size_t parameters,
1181  const char* templ, size_t arguments)
1182 {
1183  stack<string> s;
1184  while (arguments--)
1185  {
1186  s.push(st.back());
1187  st.pop_back();
1188  }
1189 
1190  *o.top() << id << " = " << templ << '(';
1191  while (!s.empty())
1192  {
1193  *o.top() << s.top();
1194  s.pop();
1195  if (!s.empty())
1196  {
1197  *o.top() << ", ";
1198  }
1199  }
1200  *o.top() << ");" << endl;
1201 }
1202 
1203 void PrettyPrinter::process(const char *id)
1204 {
1205  if (first)
1206  {
1207  *o.top() << "system " << id;
1208  first = false;
1209  }
1210  else
1211  {
1212  *o.top() << ", " << id;
1213  }
1214 }
1215 
1217 {
1218  *o.top() << ';' << endl;
1219 }
1220 
1222 
1224 {
1225  stringstream ss;
1226  string pred2 = st.back(); st.pop_back();
1227  string pred1 = st.back(); st.pop_back();
1228  string bound = st.back(); st.pop_back();
1229  string bounded = st.back(); st.pop_back();
1230 /* FIXME
1231  ss << "Pr[" << (isTimedBound ? "time" : "steps") << "<="
1232  << bound << "](" << (type == BOX ? "[] " : "<> ");
1233  if (usesUntil) ss << pred1 << " U " << pred2;
1234  else ss << pred2;
1235  ss << ")";
1236  st.push_back(ss.str());
1237 */
1238 }
1239 
1240 void PrettyPrinter::exprMitlDiamond (int low, int high)
1241 {
1242  stringstream ss;
1243  string expr = st.back(); st.pop_back();
1244 
1245  ss << "(<>[" << low << "," << high << "] " << expr << ")";
1246  st.push_back(ss.str());
1247 }
1248 
1249 void PrettyPrinter::exprMitlBox (int low, int high)
1250 {
1251  stringstream ss;
1252  string expr = st.back(); st.pop_back();
1253 
1254  ss << "([][" << low << "," << high << "] " << expr << ")";
1255  st.push_back(ss.str());
1256 }
1257 
1259  bool hasReach,
1260  int nbOfAcceptingRuns)
1261 {
1262  stringstream ss;
1263  string reachExpr = st.back();
1264  if (hasReach)
1265  st.pop_back();
1266 
1267  stack<string> exprs;
1268  for (int i=0; i<nbExpr; i++)
1269  {
1270  exprs.push(st.back()); st.pop_back();
1271  }
1272  string nbRuns = st.back(); st.pop_back();
1273  string bound = st.back(); st.pop_back();
1274  string boundedExpr = st.back(); st.pop_back();
1275  if (boundedExpr=="0")
1276  boundedExpr="#";
1277  else if (boundedExpr=="1")
1278  boundedExpr=" ";
1279 
1280  ss << "simulate [" << boundedExpr << "<=" << bound << "; "<< nbRuns << "] {";
1281  if (!exprs.empty())
1282  {
1283  ss << exprs.top(); exprs.pop();
1284  while (!exprs.empty()) {
1285  ss << ", " << exprs.top();
1286  exprs.pop();
1287  }
1288  }
1289  ss << "}";
1290  if (hasReach)
1291  {
1292  if (nbOfAcceptingRuns>0)
1293  {
1294  ss << " : " << nbOfAcceptingRuns;
1295  }
1296  ss << " : " << reachExpr;
1297  }
1298  st.push_back(ss.str());
1299 }
1300 
1303 {
1304  *o.top() << "\n/* Query begin: */" << endl;
1305 }
1306 void PrettyPrinter::queryFormula(const char* formula, const char* location)
1307 {
1308  if (formula) *o.top() << "/* Formula: "<<formula << "*/" << endl;
1309 }
1311 {
1312  if (comment) *o.top() << "/* Comment: " << comment << "*/" << endl;
1313 }
1315 {
1316  *o.top() << "/* Query end. */" << endl;
1317 }
void ifCondition() override
void exprDeadlock() override
void exprSumBegin(const char *name) override
void typeClock(PREFIX) override
Called whenever a clock type is parsed.
void beforeUpdate() override
void blockBegin() override
void typeName(PREFIX, const char *type) override
Called when a type name has been parsed.
void declParameter(const char *name, bool) override
void procStateCommit(const char *id) override
void exprTrue() override
void whileBegin() override
bool isType(const char *) override
Must return true if and only if name is registered in the symbol table as a named type...
void exprPostIncrement() override
void exprPreIncrement() override
void typeArrayOfSize(size_t n) override
Called to create an array type.
static const char *const prefix_label[]
void procEnd() override
void typeDouble(PREFIX) override
Called whenever a double type is parsed.
void procBegin(const char *name, const bool isTA=true, const std::string type="", const std::string mode="") override
void exprFalse() override
void process(const char *id) override
void exprMitlDiamond(int, int) override
void procGuard() override
void instantiationEnd(const char *, size_t, const char *, size_t) override
void declFuncEnd() override
void returnStatement(bool hasValue) override
void typeStruct(PREFIX prefix, uint32_t n) override
Called when a struct-type has been parsed.
void iterationBegin(const char *name) override
void instantiationBegin(const char *, size_t, const char *) override
void exprNary(Constants::kind_t op, uint32_t num) override
void exprDot(const char *) override
void processListEnd() override
void procProb() override
void exprExistsBegin(const char *name) override
void declVar(const char *id, bool init) override
Called to when a variable declaration has been parsed.
void exprAssignment(Constants::kind_t op) override
void exprInlineIf() override
void afterUpdate() override
void exprSimulate(int, bool, int) override
void typeBool(PREFIX) override
Called whenever a boolean type is parsed.
void exprId(const char *id) override
void addPosition(uint32_t position, uint32_t offset, uint32_t line, const std::string &path) override
Add mapping from an absolute position to a relative XML element.
void emptyStatement() override
void exprBuiltinFunction2(Constants::kind_t kind) override
void procSelect(const char *id) override
void exprForAllEnd(const char *name) override
void typeVoid() override
Called whenever a void type is parsed.
void procStateInit(const char *id) override
void exprNat(int32_t n) override
void iterationEnd(const char *name) override
void exprUnary(Constants::kind_t op) override
void typeBoundedInt(PREFIX) override
Called whenever an integer type with a range is parsed.
#define comment
Definition: lexer.cc:856
void queryEnd() override
void typeChannel(PREFIX) override
Called whenever a channel type is parsed.
void procUpdate() override
void forBegin() override
void structField(const char *name) override
Called to declare a field of a structure.
void typeInt(PREFIX) override
Called whenever an integer type is parsed.
void queryBegin() override
Verification queries.
void breakStatement() override
void exprDouble(double d) override
void procEdgeBegin(const char *source, const char *target, const bool control)
void declFuncBegin(const char *name) override
Exception indicating a type error.
Definition: builder.h:39
void done() override
void exprArray() override
void ifEnd(bool) override
void exprExistsEnd(const char *name) override
void ifThen() override
void typePop() override
Pop type at the topof the type stack.
void exprCallBegin() override
void exprProbaQuantitative(Constants::kind_t) override
void handleError(const std::string &) override
void exprBuiltinFunction3(Constants::kind_t kind) override
void procSync(Constants::synchronisation_t type) override
void declTypeDef(const char *name) override
Used when a typedef declaration was parsed.
void exprCallEnd(uint32_t n) override
static const char * getBuiltinFunName(kind_t kind)
void exprPostDecrement() override
void declFieldInit(const char *name) override
void exprBuiltinFunction1(Constants::kind_t kind) override
void procState(const char *id, bool hasInvariant, bool hasExpRate) override
void procBranchpoint(const char *id) override
void typeDuplicate() override
Duplicate type at the top of the type stack.
void forEnd() override
void queryFormula(const char *formula, const char *location) override
void exprStatement() override
void exprTernary(Constants::kind_t op, bool firstMissing) override
void exprMitlBox(int, int) override
void blockEnd() override
void exprScenario(const char *name) override
void procStateUrgent(const char *id) override
void typeScalar(PREFIX) override
Called whenever a scalar type is parsed.
void handleWarning(const std::string &) override
void exprBinary(Constants::kind_t op) override
void declInitialiserList(uint32_t num) override
void ifBegin() override
void doWhileEnd() override
Definition: lexer.cc:817
PrettyPrinter(std::ostream &stream)
void exprSumEnd(const char *name) override
void whileEnd() override
static int types
Definition: parser.cc:127
void exprComma() override
void typeArrayOfType(size_t n) override
Called to create an array type.
void exprPreDecrement() override
void continueStatement() override
void queryComment(const char *comment) override
void exprForAllBegin(const char *name) override
void doWhileBegin() override
void procEdgeEnd(const char *source, const char *target) override