Skip to content

Commit db8c89a

Browse files
authored
Merge pull request #708 from diffblue/smv-prec
expr2smv: enum for precedence
2 parents 1975e77 + 9bc1249 commit db8c89a

File tree

3 files changed

+116
-86
lines changed

3 files changed

+116
-86
lines changed

regression/ebmc/smv/smv_iff2.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
smv_iff2.smv
33
--bdd
4-
^\[.*\] \(AG x != 5\) <-> \(x != 5 & AX AG x != 5\): PROVED$
4+
^\[.*\] AG x != 5 <-> x != 5 & AX AG x != 5: PROVED$
55
^EXIT=0$
66
^SIGNAL=0$
77
--

src/smvlang/expr2smv.cpp

+114-84
Original file line numberDiff line numberDiff line change
@@ -21,81 +21,99 @@ class expr2smvt
2121
{
2222
}
2323

24-
bool convert_nondet_choice(const exprt &src, std::string &dest, unsigned precedence);
24+
protected:
25+
// In NuSMV 2.6., ! (not) has a high precedence (above ::), whereas
26+
// in the CMU SMV implementation it has the same as other boolean operators.
27+
// We use the CMU SMV precedence for !.
28+
// Like CMU SMV, we give the same precedence to -> and <->, to avoid ambiguity.
29+
// Note that the precedence of mod in the CMU SMV differs from NuSMV's.
30+
// We use NuSMV's.
31+
enum class precedencet
32+
{
33+
MAX = 16,
34+
INDEX = 15, // [ ] , [ : ]
35+
CONCAT = 14, // ::
36+
UMINUS = 13, // - (unary minus)
37+
MULT = 12, // * / mod
38+
PLUS = 11, // + -
39+
SHIFT = 10, // << >>
40+
UNION = 9, // union
41+
IN = 8, // in
42+
REL = 7, // = != < > <= >=
43+
TEMPORAL = 6, // AX, AF, etc.
44+
NOT = 5, // !
45+
AND = 4, // &
46+
OR = 3, // | xor xnor
47+
IF = 2, // (• ? • : •)
48+
IFF = 1, // <->
49+
IMPLIES = 1 // ->
50+
};
51+
52+
/*
53+
From http://www.cs.cmu.edu/~modelcheck/smv/smvmanual.ps
54+
55+
The order of precedence from high to low is
56+
* /
57+
+ -
58+
mod
59+
= != < > <= >=
60+
!
61+
&
62+
|
63+
-> <->
64+
*/
65+
66+
public:
67+
bool convert_nondet_choice(
68+
const exprt &src,
69+
std::string &dest,
70+
precedencet precedence);
2571

26-
bool convert_binary(const exprt &src, std::string &dest, const std::string &symbol, unsigned precedence);
72+
bool convert_binary(
73+
const exprt &src,
74+
std::string &dest,
75+
const std::string &symbol,
76+
precedencet precedence);
2777

2878
bool convert_unary(
2979
const unary_exprt &,
3080
std::string &dest,
3181
const std::string &symbol,
32-
unsigned precedence);
82+
precedencet precedence);
3383

3484
bool
35-
convert_index(const index_exprt &, std::string &dest, unsigned precedence);
85+
convert_index(const index_exprt &, std::string &dest, precedencet precedence);
3686

37-
bool convert(const exprt &src, std::string &dest, unsigned &precedence);
87+
bool convert(const exprt &src, std::string &dest, precedencet &precedence);
3888

3989
bool convert(const exprt &src, std::string &dest);
4090

41-
bool
42-
convert_symbol(const symbol_exprt &, std::string &dest, unsigned &precedence);
91+
bool convert_symbol(
92+
const symbol_exprt &,
93+
std::string &dest,
94+
precedencet &precedence);
4395

44-
bool convert_next_symbol(const exprt &src, std::string &dest, unsigned &precedence);
96+
bool convert_next_symbol(
97+
const exprt &src,
98+
std::string &dest,
99+
precedencet &precedence);
45100

46-
bool convert_constant(const exprt &src, std::string &dest, unsigned &precedence);
101+
bool convert_constant(
102+
const exprt &src,
103+
std::string &dest,
104+
precedencet &precedence);
47105

48106
bool convert_cond(const exprt &src, std::string &dest);
49107

50-
bool convert_norep(const exprt &src, std::string &dest, unsigned &precedence);
108+
bool
109+
convert_norep(const exprt &src, std::string &dest, precedencet &precedence);
51110

52111
bool convert(const typet &src, std::string &dest);
53112

54113
protected:
55114
const namespacet &ns;
56115
};
57116

58-
/*
59-
From http://www.cs.cmu.edu/~modelcheck/smv/smvmanual.ps
60-
61-
The order of precedence from high to low is
62-
* /
63-
+ -
64-
mod
65-
= != < > <= >=
66-
!
67-
&
68-
|
69-
-> <->
70-
71-
SMV Operator Precedences:
72-
73-
1 %left COMMA
74-
2 %right IMPLIES
75-
3 %left IFF
76-
4 %left OR XOR XNOR
77-
5 %left AND
78-
6 %left NOT
79-
7 %left EX AX EF AF EG AG EE AA SINCE UNTIL TRIGGERED RELEASES EBF EBG ABF ABG BUNTIL MMIN MMAX
80-
8 %left OP_NEXT OP_GLOBAL OP_FUTURE
81-
9 %left OP_PREC OP_NOTPRECNOT OP_HISTORICAL OP_ONCE
82-
10 %left APATH EPATH
83-
11 %left EQUAL NOTEQUAL LT GT LE GE
84-
12 %left UNION
85-
13 %left SETIN
86-
14 %left MOD
87-
15 %left PLUS MINUS
88-
16 %left TIMES DIVIDE
89-
17 %left UMINUS
90-
18 %left NEXT SMALLINIT
91-
19 %left DOT
92-
20 [ ]
93-
21 = max
94-
95-
*/
96-
97-
#define SMV_MAX_PRECEDENCE 21
98-
99117
/*******************************************************************\
100118
101119
Function: expr2smvt::convert_nondet_choice
@@ -111,7 +129,7 @@ Function: expr2smvt::convert_nondet_choice
111129
bool expr2smvt::convert_nondet_choice(
112130
const exprt &src,
113131
std::string &dest,
114-
unsigned precedence)
132+
precedencet precedence)
115133
{
116134
dest="{ ";
117135

@@ -187,7 +205,7 @@ bool expr2smvt::convert_binary(
187205
const exprt &src,
188206
std::string &dest,
189207
const std::string &symbol,
190-
unsigned precedence)
208+
precedencet precedence)
191209
{
192210
if(src.operands().size()<2)
193211
return convert_norep(src, dest, precedence);
@@ -206,7 +224,7 @@ bool expr2smvt::convert_binary(
206224
}
207225

208226
std::string op;
209-
unsigned p;
227+
precedencet p;
210228

211229
if(convert(*it, op, p)) return true;
212230

@@ -234,10 +252,10 @@ bool expr2smvt::convert_unary(
234252
const unary_exprt &src,
235253
std::string &dest,
236254
const std::string &symbol,
237-
unsigned precedence)
255+
precedencet precedence)
238256
{
239257
std::string op;
240-
unsigned p;
258+
precedencet p;
241259

242260
if(convert(src.op(), op, p))
243261
return true;
@@ -265,10 +283,10 @@ Function: expr2smvt::convert_index
265283
bool expr2smvt::convert_index(
266284
const index_exprt &src,
267285
std::string &dest,
268-
unsigned precedence)
286+
precedencet precedence)
269287
{
270288
std::string op;
271-
unsigned p;
289+
precedencet p;
272290

273291
if(convert(src.op0(), op, p)) return true;
274292

@@ -300,9 +318,9 @@ Function: expr2smvt::convert_norep
300318
bool expr2smvt::convert_norep(
301319
const exprt &src,
302320
std::string &dest,
303-
unsigned &precedence)
321+
precedencet &precedence)
304322
{
305-
precedence=SMV_MAX_PRECEDENCE;
323+
precedence = precedencet::MAX;
306324
dest=src.pretty();
307325
return false;
308326
}
@@ -322,9 +340,9 @@ Function: expr2smvt::convert_symbol
322340
bool expr2smvt::convert_symbol(
323341
const symbol_exprt &src,
324342
std::string &dest,
325-
unsigned &precedence)
343+
precedencet &precedence)
326344
{
327-
precedence=SMV_MAX_PRECEDENCE;
345+
precedence = precedencet::MAX;
328346

329347
auto &symbol = ns.lookup(src);
330348

@@ -348,7 +366,7 @@ Function: expr2smvt::convert_next_symbol
348366
bool expr2smvt::convert_next_symbol(
349367
const exprt &src,
350368
std::string &dest,
351-
unsigned &precedence)
369+
precedencet &precedence)
352370
{
353371
std::string tmp;
354372
convert_symbol(
@@ -374,9 +392,9 @@ Function: expr2smvt::convert_constant
374392
bool expr2smvt::convert_constant(
375393
const exprt &src,
376394
std::string &dest,
377-
unsigned &precedence)
395+
precedencet &precedence)
378396
{
379-
precedence=SMV_MAX_PRECEDENCE;
397+
precedence = precedencet::MAX;
380398

381399
const typet &type=src.type();
382400
const std::string &value=src.get_string(ID_value);
@@ -414,19 +432,19 @@ Function: expr2smvt::convert
414432
bool expr2smvt::convert(
415433
const exprt &src,
416434
std::string &dest,
417-
unsigned &precedence)
435+
precedencet &precedence)
418436
{
419-
precedence=SMV_MAX_PRECEDENCE;
437+
precedence = precedencet::MAX;
420438

421439
if(src.id()==ID_plus)
422-
return convert_binary(src, dest, "+", precedence=15);
440+
return convert_binary(src, dest, "+", precedence = precedencet::PLUS);
423441

424442
else if(src.id()==ID_minus)
425443
{
426444
if(src.operands().size()<2)
427445
return convert_norep(src, dest, precedence);
428-
else
429-
return convert_binary(src, dest, "-", precedence=15);
446+
else
447+
return convert_binary(src, dest, "-", precedence = precedencet::PLUS);
430448
}
431449

432450
else if(src.id()==ID_unary_minus)
@@ -435,55 +453,67 @@ bool expr2smvt::convert(
435453
return convert_norep(src, dest, precedence);
436454
else
437455
return convert_unary(
438-
to_unary_minus_expr(src), dest, "-", precedence = 17);
456+
to_unary_minus_expr(src), dest, "-", precedence = precedencet::UMINUS);
439457
}
440458

441459
else if(src.id()==ID_index)
442-
return convert_index(to_index_expr(src), dest, precedence = 20);
460+
return convert_index(
461+
to_index_expr(src), dest, precedence = precedencet::INDEX);
443462

444463
else if(src.id()==ID_mult || src.id()==ID_div)
445-
return convert_binary(src, dest, src.id_string(), precedence=16);
464+
return convert_binary(
465+
src, dest, src.id_string(), precedence = precedencet::MULT);
446466

447467
else if(src.id()==ID_lt || src.id()==ID_gt ||
448468
src.id()==ID_le || src.id()==ID_ge)
449-
return convert_binary(src, dest, src.id_string(), precedence=11);
469+
return convert_binary(
470+
src, dest, src.id_string(), precedence = precedencet::REL);
450471

451472
else if(src.id()==ID_equal)
452473
{
453474
if(src.get_bool(ID_C_smv_iff))
454-
return convert_binary(src, dest, "<->", precedence = 16);
475+
return convert_binary(src, dest, "<->", precedence = precedencet::IFF);
455476
else
456-
return convert_binary(src, dest, "=", precedence = 11);
477+
return convert_binary(src, dest, "=", precedence = precedencet::REL);
457478
}
458479

459480
else if(src.id()==ID_notequal)
460-
return convert_binary(src, dest, "!=", precedence=11);
481+
return convert_binary(src, dest, "!=", precedence = precedencet::REL);
461482

462483
else if(src.id()==ID_not)
463-
return convert_unary(to_not_expr(src), dest, "!", precedence = 6);
484+
return convert_unary(
485+
to_not_expr(src), dest, "!", precedence = precedencet::NOT);
464486

465487
else if(src.id()==ID_and)
466-
return convert_binary(src, dest, "&", precedence=5);
488+
return convert_binary(src, dest, "&", precedence = precedencet::AND);
467489

468490
else if(src.id()==ID_or)
469-
return convert_binary(src, dest, "|", precedence=4);
491+
return convert_binary(src, dest, "|", precedence = precedencet::OR);
470492

471493
else if(src.id()==ID_implies)
472-
return convert_binary(src, dest, "->", precedence=2);
494+
return convert_binary(src, dest, "->", precedence = precedencet::IMPLIES);
473495

474496
else if(
475497
src.id() == ID_AG || src.id() == ID_EG || src.id() == ID_AF ||
476498
src.id() == ID_EF || src.id() == ID_AX || src.id() == ID_EX ||
477499
src.id() == ID_G || src.id() == ID_F || src.id() == ID_X)
500+
{
478501
return convert_unary(
479-
to_unary_expr(src), dest, src.id_string() + " ", precedence = 7);
502+
to_unary_expr(src),
503+
dest,
504+
src.id_string() + " ",
505+
precedence = precedencet::TEMPORAL);
506+
}
480507

481508
else if(
482509
src.id() == ID_AU || src.id() == ID_EU || src.id() == ID_AR ||
483510
src.id() == ID_ER || src.id() == ID_U || src.id() == ID_R)
484511
{
485512
return convert_binary(
486-
to_binary_expr(src), dest, src.id_string(), precedence = 7);
513+
to_binary_expr(src),
514+
dest,
515+
src.id_string(),
516+
precedence = precedencet::TEMPORAL);
487517
}
488518

489519
else if(src.id()==ID_symbol)
@@ -530,7 +560,7 @@ Function: expr2smvt::convert
530560

531561
bool expr2smvt::convert(const exprt &src, std::string &dest)
532562
{
533-
unsigned precedence;
563+
precedencet precedence;
534564
return convert(src, dest, precedence);
535565
}
536566

src/smvlang/parser.y

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ static void new_module(YYSTYPE &module)
177177
%left EQUAL_Token NOTEQUAL_Token LT_Token GT_Token LE_Token GE_Token
178178
%left UNION_Token
179179
%left IN_Token NOTIN_Token
180-
%left MOD_Token
180+
%left MOD_Token /* Precedence from CMU SMV, different from NuSMV */
181181
%left PLUS_Token MINUS_Token
182182
%left TIMES_Token DIVIDE_Token
183183
%left UMINUS /* supplies precedence for unary minus */

0 commit comments

Comments
 (0)