1
|
%{
|
2
|
(********************************************************************)
|
3
|
(* *)
|
4
|
(* The LustreC compiler toolset / The LustreC Development Team *)
|
5
|
(* Copyright 2012 - -- ONERA - CNRS - INPT *)
|
6
|
(* *)
|
7
|
(* LustreC is free software, distributed WITHOUT ANY WARRANTY *)
|
8
|
(* under the terms of the GNU Lesser General Public License *)
|
9
|
(* version 2.1. *)
|
10
|
(* *)
|
11
|
(********************************************************************)
|
12
|
|
13
|
open Utils
|
14
|
open Corelang
|
15
|
open LustreSpec
|
16
|
|
17
|
let mkexpr x = mkexpr (Location.symbol_rloc ()) x
|
18
|
let mkpredef_call x = mkpredef_call (Location.symbol_rloc ()) x
|
19
|
let mkpredef_unary_call x = mkpredef_unary_call (Location.symbol_rloc ()) x
|
20
|
|
21
|
let mkeexpr x = mkeexpr (Location.symbol_rloc ()) x
|
22
|
(*
|
23
|
let mkepredef_call x = mkepredef_call (Location.symbol_rloc ()) x
|
24
|
let mkepredef_unary_call x = mkepredef_unary_call (Location.symbol_rloc ()) x
|
25
|
*)
|
26
|
|
27
|
let mktyp x = mktyp (Location.symbol_rloc ()) x
|
28
|
let mkvar_decl x = mkvar_decl (Location.symbol_rloc ()) x
|
29
|
let mkclock x = mkclock (Location.symbol_rloc ()) x
|
30
|
|
31
|
%}
|
32
|
|
33
|
|
34
|
%token <int> INT
|
35
|
%token <string> REAL
|
36
|
%token <float> FLOAT
|
37
|
%token <string> STRING
|
38
|
%token TRUE FALSE STATELESS ASSERT INCLUDE QUOTE
|
39
|
%token <string> IDENT
|
40
|
%token LPAR RPAR SCOL COL COMMA COLCOL
|
41
|
%token AMPERAMPER BARBAR NOT POWER
|
42
|
%token IF THEN ELSE
|
43
|
%token UCLOCK DCLOCK PHCLOCK TAIL
|
44
|
%token MERGE FBY WHEN WHENNOT EVERY
|
45
|
%token NODE LET TEL RETURNS VAR IMPORTED SENSOR ACTUATOR WCET TYPE CONST
|
46
|
%token TINT TFLOAT TREAL TBOOL TCLOCK
|
47
|
%token RATE DUE
|
48
|
%token EQ LT GT LTE GTE NEQ
|
49
|
%token AND OR XOR IMPL
|
50
|
%token MULT DIV MOD
|
51
|
%token MINUS PLUS UMINUS
|
52
|
%token PRE ARROW
|
53
|
%token EOF
|
54
|
%token REQUIRES ENSURES OBSERVER
|
55
|
%token INVARIANT BEHAVIOR ASSUMES
|
56
|
%token EXISTS FORALL
|
57
|
|
58
|
%nonassoc prec_exists prec_forall
|
59
|
%nonassoc COMMA POWER
|
60
|
%left MERGE IF
|
61
|
%nonassoc ELSE
|
62
|
%right ARROW FBY
|
63
|
%left WHEN WHENNOT UCLOCK DCLOCK PHCLOCK
|
64
|
%right COLCOL
|
65
|
%right IMPL
|
66
|
%left OR XOR BARBAR
|
67
|
%left AND AMPERAMPER
|
68
|
%left NOT
|
69
|
%nonassoc EQ LT GT LTE GTE NEQ
|
70
|
%left MINUS PLUS
|
71
|
%left MULT DIV MOD
|
72
|
%left PRE
|
73
|
%nonassoc UMINUS
|
74
|
|
75
|
%start lustre_annot
|
76
|
%type <LustreSpec.ident -> LustreSpec.expr_annot> lustre_annot
|
77
|
|
78
|
%start lustre_spec
|
79
|
%type <LustreSpec.node_annot> lustre_spec
|
80
|
|
81
|
%%
|
82
|
|
83
|
lustre_spec:
|
84
|
| contract EOF { $1 }
|
85
|
|
86
|
contract:
|
87
|
requires ensures behaviors { { requires = $1; ensures = $2; behaviors = $3; } }
|
88
|
|
89
|
requires:
|
90
|
{ [] }
|
91
|
| REQUIRES qexpr SCOL requires { $2::$4 }
|
92
|
|
93
|
ensures:
|
94
|
{ [] }
|
95
|
| ENSURES qexpr SCOL ensures { (EnsuresExpr $2) :: $4 }
|
96
|
| OBSERVER IDENT LPAR tuple_qexpr RPAR SCOL ensures { (SpecObserverNode($2,$4)) :: $7 }
|
97
|
|
98
|
behaviors:
|
99
|
{ [] }
|
100
|
| BEHAVIOR IDENT COL assumes ensures behaviors { ($2,$4,$5)::$6 }
|
101
|
|
102
|
assumes:
|
103
|
{ [] }
|
104
|
| ASSUMES qexpr SCOL assumes { $2::$4 }
|
105
|
|
106
|
tuple_qexpr:
|
107
|
| qexpr COMMA qexpr {[$3;$1]}
|
108
|
| tuple_qexpr COMMA qexpr {$3::$1}
|
109
|
|
110
|
|
111
|
tuple_expr:
|
112
|
expr COMMA expr {[$3;$1]}
|
113
|
| tuple_expr COMMA expr {$3::$1}
|
114
|
|
115
|
// Same as tuple expr but accepting lists with single element
|
116
|
array_expr:
|
117
|
expr {[$1]}
|
118
|
| expr COMMA array_expr {$1::$3}
|
119
|
|
120
|
dim_list:
|
121
|
dim RBRACKET { fun base -> mkexpr (Expr_access (base, $1)) }
|
122
|
| dim RBRACKET LBRACKET dim_list { fun base -> $4 (mkexpr (Expr_access (base, $1))) }
|
123
|
|
124
|
expr:
|
125
|
/* constants */
|
126
|
INT {mkexpr (Expr_const (Const_int $1))}
|
127
|
| REAL {mkexpr (Expr_const (Const_real $1))}
|
128
|
| FLOAT {mkexpr (Expr_const (Const_float $1))}
|
129
|
/* Idents or type enum tags */
|
130
|
| IDENT {
|
131
|
if Hashtbl.mem tag_table $1
|
132
|
then mkexpr (Expr_const (Const_tag $1))
|
133
|
else mkexpr (Expr_ident $1)}
|
134
|
| LPAR ANNOT expr RPAR
|
135
|
{update_expr_annot $3 $2}
|
136
|
| LPAR expr RPAR
|
137
|
{$2}
|
138
|
| LPAR tuple_expr RPAR
|
139
|
{mkexpr (Expr_tuple (List.rev $2))}
|
140
|
|
141
|
/* Array expressions */
|
142
|
| LBRACKET array_expr RBRACKET { mkexpr (Expr_array $2) }
|
143
|
| expr POWER dim { mkexpr (Expr_power ($1, $3)) }
|
144
|
| expr LBRACKET dim_list { $3 $1 }
|
145
|
|
146
|
/* Temporal operators */
|
147
|
| PRE expr
|
148
|
{mkexpr (Expr_pre $2)}
|
149
|
| expr ARROW expr
|
150
|
{mkexpr (Expr_arrow ($1,$3))}
|
151
|
| expr FBY expr
|
152
|
{(*mkexpr (Expr_fby ($1,$3))*)
|
153
|
mkexpr (Expr_arrow ($1, mkexpr (Expr_pre $3)))}
|
154
|
| expr WHEN IDENT
|
155
|
{mkexpr (Expr_when ($1,$3,tag_true))}
|
156
|
| expr WHENNOT IDENT
|
157
|
{mkexpr (Expr_when ($1,$3,tag_false))}
|
158
|
| expr WHEN IDENT LPAR IDENT RPAR
|
159
|
{mkexpr (Expr_when ($1, $5, $3))}
|
160
|
| MERGE IDENT handler_expr_list
|
161
|
{mkexpr (Expr_merge ($2,$3))}
|
162
|
|
163
|
/* Applications */
|
164
|
| IDENT LPAR expr RPAR
|
165
|
{mkexpr (Expr_appl ($1, $3, None))}
|
166
|
| IDENT LPAR expr RPAR EVERY IDENT
|
167
|
{mkexpr (Expr_appl ($1, $3, Some ($6, tag_true)))}
|
168
|
| IDENT LPAR expr RPAR EVERY IDENT LPAR IDENT RPAR
|
169
|
{mkexpr (Expr_appl ($1, $3, Some ($8, $6))) }
|
170
|
| IDENT LPAR tuple_expr RPAR
|
171
|
{mkexpr (Expr_appl ($1, mkexpr (Expr_tuple (List.rev $3)), None))}
|
172
|
| IDENT LPAR tuple_expr RPAR EVERY IDENT
|
173
|
{mkexpr (Expr_appl ($1, mkexpr (Expr_tuple (List.rev $3)), Some ($6, tag_true))) }
|
174
|
| IDENT LPAR tuple_expr RPAR EVERY IDENT LPAR IDENT RPAR
|
175
|
{mkexpr (Expr_appl ($1, mkexpr (Expr_tuple (List.rev $3)), Some ($8, $6))) }
|
176
|
|
177
|
/* Boolean expr */
|
178
|
| expr AND expr
|
179
|
{mkpredef_call "&&" [$1;$3]}
|
180
|
| expr AMPERAMPER expr
|
181
|
{mkpredef_call "&&" [$1;$3]}
|
182
|
| expr OR expr
|
183
|
{mkpredef_call "||" [$1;$3]}
|
184
|
| expr BARBAR expr
|
185
|
{mkpredef_call "||" [$1;$3]}
|
186
|
| expr XOR expr
|
187
|
{mkpredef_call "xor" [$1;$3]}
|
188
|
| NOT expr
|
189
|
{mkpredef_unary_call "not" $2}
|
190
|
| expr IMPL expr
|
191
|
{mkpredef_call "impl" [$1;$3]}
|
192
|
|
193
|
/* Comparison expr */
|
194
|
| expr EQ expr
|
195
|
{mkpredef_call "=" [$1;$3]}
|
196
|
| expr LT expr
|
197
|
{mkpredef_call "<" [$1;$3]}
|
198
|
| expr LTE expr
|
199
|
{mkpredef_call "<=" [$1;$3]}
|
200
|
| expr GT expr
|
201
|
{mkpredef_call ">" [$1;$3]}
|
202
|
| expr GTE expr
|
203
|
{mkpredef_call ">=" [$1;$3]}
|
204
|
| expr NEQ expr
|
205
|
{mkpredef_call "!=" [$1;$3]}
|
206
|
|
207
|
/* Arithmetic expr */
|
208
|
| expr PLUS expr
|
209
|
{mkpredef_call "+" [$1;$3]}
|
210
|
| expr MINUS expr
|
211
|
{mkpredef_call "-" [$1;$3]}
|
212
|
| expr MULT expr
|
213
|
{mkpredef_call "*" [$1;$3]}
|
214
|
| expr DIV expr
|
215
|
{mkpredef_call "/" [$1;$3]}
|
216
|
| MINUS expr %prec UMINUS
|
217
|
{mkpredef_unary_call "uminus" $2}
|
218
|
| expr MOD expr
|
219
|
{mkpredef_call "mod" [$1;$3]}
|
220
|
|
221
|
/* If */
|
222
|
| IF expr THEN expr ELSE expr
|
223
|
{mkexpr (Expr_ite ($2, $4, $6))}
|
224
|
|
225
|
|
226
|
handler_expr_list:
|
227
|
{ [] }
|
228
|
| handler_expr handler_expr_list { $1 :: $2 }
|
229
|
|
230
|
handler_expr:
|
231
|
LPAR IDENT ARROW expr RPAR { ($2, $4) }
|
232
|
|
233
|
qexpr:
|
234
|
| expr { mkeexpr [] $1 }
|
235
|
/* Quantifiers */
|
236
|
| EXISTS vdecl SCOL qexpr %prec prec_exists { extend_eepxr (Exists, $2) $4 }
|
237
|
| FORALL vdecl SCOL qexpr %prec prec_forall { extend_eepxr (Forall, $2) $4 }
|
238
|
|
239
|
vdecl:
|
240
|
| ident_list COL typ clock
|
241
|
{List.map mkvar_decl (List.map (fun id -> (id, $3, $4, false)) $1)}
|
242
|
| CONST ident_list COL typ clock
|
243
|
{List.map mkvar_decl (List.map (fun id -> (id, $4, $5, true)) $2)}
|
244
|
|
245
|
|
246
|
ident_list:
|
247
|
IDENT {[$1]}
|
248
|
| ident_list COMMA IDENT {$3::$1}
|
249
|
|
250
|
|
251
|
typ:
|
252
|
{mktyp Tydec_any}
|
253
|
| TINT {mktyp Tydec_int}
|
254
|
| IDENT {
|
255
|
try
|
256
|
mktyp (Hashtbl.find Corelang.type_table (Tydec_const $1))
|
257
|
with Not_found -> raise (Corelang.Error (Location.symbol_rloc(), Corelang.Unbound_symbol ("type " ^ $1)))
|
258
|
}
|
259
|
| TFLOAT {mktyp Tydec_float}
|
260
|
| TREAL {mktyp Tydec_real}
|
261
|
| TBOOL {mktyp Tydec_bool}
|
262
|
| TCLOCK {mktyp (Tydec_clock Tydec_bool) }
|
263
|
| typ POWER INT {mktyp Tydec_any (*(mktyptuple $3 $1)*)}
|
264
|
| typ POWER IDENT {mktyp Tydec_any (*(mktyptuple (try
|
265
|
match get_const $3 with Const_int i -> i with _ -> failwith "Const power error") $1)*)}
|
266
|
|
267
|
clock:
|
268
|
{mkclock Ckdec_any}
|
269
|
| when_list
|
270
|
{mkclock (Ckdec_bool (List.rev $1))}
|
271
|
|
272
|
when_cond:
|
273
|
WHEN IDENT {($2, tag_true)}
|
274
|
| WHENNOT IDENT {($2, tag_false)}
|
275
|
|
276
|
when_list:
|
277
|
when_cond {[$1]}
|
278
|
| when_list when_cond {$2::$1}
|
279
|
|
280
|
|
281
|
const:
|
282
|
| INT {Const_int $1}
|
283
|
| REAL {Const_real $1}
|
284
|
| FLOAT {Const_float $1}
|
285
|
| TRUE {Const_bool true}
|
286
|
| FALSE {Const_bool false}
|
287
|
| STRING {Const_string $1}
|
288
|
|
289
|
lustre_annot:
|
290
|
lustre_annot_list EOF { fun node_id -> $1 }
|
291
|
|
292
|
lustre_annot_list:
|
293
|
{ [] }
|
294
|
| kwd COL expr SCOL lustre_annot_list { ($1,$3)::$5 }
|
295
|
| IDENT COL expr SCOL lustre_annot_list { ([$1],$3)::$5 }
|
296
|
| INVARIANT COL expr SCOL lustre_annot_list{ (["invariant"],$3)::$5 }
|
297
|
| OBSERVER COL expr SCOL lustre_annot_list { (["observer"],$3)::$5 }
|
298
|
|
299
|
kwd:
|
300
|
DIV { [] }
|
301
|
| DIV IDENT kwd { $2::$3}
|