Project

General

Profile

Download (20.8 KB) Statistics
| Branch: | Tag: | Revision:
1
/********************************************************************/
2
/*                                                                  */
3
/*  The LustreC compiler toolset   /  The LustreC Development Team  */
4
/*  Copyright 2012 -    --   ONERA - CNRS - INPT                    */
5
/*                                                                  */
6
/*  LustreC is free software, distributed WITHOUT ANY WARRANTY      */
7
/*  under the terms of the GNU Lesser General Public License        */
8
/*  version 2.1.                                                    */
9
/*                                                                  */
10
/********************************************************************/
11

    
12
%{
13
open Utils
14
open Lustre_types
15
open Corelang
16
open Dimension
17

    
18
   
19
let get_loc () = Location.symbol_rloc ()
20

    
21
let mkident x = x, get_loc ()
22
let mktyp = mktyp (get_loc ())
23
let mkotyp x = match x with Some t -> Some (mktyp t) | None -> None
24
let mkclock = mkclock (get_loc ())
25
let mkvar_decl x loc = mkvar_decl loc ~orig:true x
26
let mkexpr = mkexpr (get_loc ())
27
let mkeexpr = mkeexpr (get_loc ())
28
let mkeq = mkeq (get_loc ())
29
let mkassert = mkassert (get_loc ())
30
let mktop_decl = mktop_decl (get_loc ()) (Location.get_module ())
31
let mkpredef_call = mkpredef_call (get_loc ())
32
let mkpredef_call_b f x1 x2 = mkpredef_call f [x1; x2]
33
let mkpredef_call_u f x = mkpredef_call f [x]
34

    
35
let mkdim_int = mkdim_int (get_loc ())
36
(* let mkdim_bool b = mkdim_bool (get_loc ()) b *)
37
let mkdim_ident = mkdim_ident (get_loc ())
38
let mkdim_appl = mkdim_appl (get_loc ())
39
let mkdim_appl_b f x1 x2 = mkdim_appl f [x1; x2]
40
let mkdim_appl_u f x = mkdim_appl f [x]
41
let mkdim_ite = mkdim_ite (get_loc ())
42

    
43
let mkarraytype = List.fold_left (fun t d -> Tydec_array (d, t))
44

    
45
let mkvdecls const typ clock expr =
46
  List.map (fun (id, loc) ->
47
      mkvar_decl (id,
48
                  mktyp (match typ with Some t -> t | None -> Tydec_any),
49
                  (match clock with Some ck -> ck | None -> mkclock Ckdec_any),
50
                  const, expr, None) loc)
51

    
52
(* let mkannots annots = { annots = annots; annot_loc = get_loc () } *)
53

    
54
let node_stack : ident list ref = ref []
55
(* let debug_calls () = Format.eprintf "call stack: %a@.@?" (Utils.fprintf_list ~sep:", " Format.pp_print_string) !node_stack *)
56
let push_node nd = node_stack := nd :: !node_stack; nd
57
let pop_node () = try node_stack := List.tl !node_stack with _ -> assert false
58
let get_current_node () = try List.hd !node_stack with _ -> assert false
59

    
60
let rec fby expr n init =
61
  if n <= 1 then
62
    mkexpr (Expr_arrow (init, mkexpr (Expr_pre expr)))
63
  else
64
    mkexpr (Expr_arrow (init, mkexpr (Expr_pre (fby expr (n - 1) init))))
65

    
66
 
67
%}
68

    
69
%token <int> INT
70
%token <Real.t> REAL
71

    
72
%token <string> STRING
73
%token AUTOMATON STATE UNTIL UNLESS RESTART RESUME 
74
%token ASSERT OPEN INCLUDE QUOTE POINT FUNCTION
75
%token <string> IDENT
76
%token <string> UIDENT
77
%token TRUE FALSE
78
%token <Lustre_types.expr_annot> ANNOT
79
%token <Lustre_types.spec_types> NODESPEC
80
%token LBRACKET RBRACKET LCUR RCUR LPAR RPAR SCOL COL COMMA COLCOL 
81
%token AMPERAMPER BARBAR NOT POWER
82
%token IF THEN ELSE
83
%token MERGE FBY WHEN WHENNOT EVERY
84
%token NODE LET TEL RETURNS VAR TYPE CONST
85
%token STRUCT ENUM
86
%token TINT TREAL TBOOL TCLOCK
87
%token EQ LT GT LTE GTE NEQ
88
%token AND OR XOR IMPL
89
%token MULT DIV MOD
90
%token MINUS PLUS 
91
%token PRE ARROW
92
%token REQUIRE ENSURE ASSUME GUARANTEES IMPORT CONTRACT
93
%token INVARIANT MODE CCODE MATLAB
94
%token EXISTS FORALL
95
%token PROTOTYPE LIB
96
%token EOF
97

    
98
%nonassoc p_string
99
%nonassoc p_vdecl
100
%left SCOL
101
%nonassoc EVERY
102
%nonassoc ELSE
103
%right ARROW FBY
104
%left WHEN WHENNOT 
105
%right IMPL
106
%left OR XOR BARBAR
107
%left AND AMPERAMPER
108
%left NOT
109
%nonassoc EQ LT GT LTE GTE NEQ
110
%left MINUS PLUS
111
%left MULT DIV MOD
112
%left p_uminus
113
%left POWER
114
%left PRE
115
%nonassoc RBRACKET
116
%nonassoc LBRACKET
117

    
118
%start <Lustre_types.top_decl list> prog
119

    
120
%start <Lustre_types.top_decl list> header
121

    
122
%start <Lustre_types.expr_annot> lustre_annot
123

    
124
%start <Lustre_types.spec_types> lustre_spec
125

    
126
%%
127

    
128
ident:
129
| x=UIDENT { x }
130
| x=IDENT  { x }
131

    
132
module_ident:
133
| m=ident { m }
134

    
135
file_ident:
136
| m=module_ident                    { m }
137
| m=module_ident POINT f=file_ident { m ^ "." ^ f }
138

    
139
path_ident:
140
| POINT DIV p=path_ident        { "./" ^ p }
141
| f=file_ident DIV p=path_ident { f ^ "/" ^ p }
142
| DIV p=path_ident              { "/" ^ p }
143
| f=file_ident                  { f }
144

    
145
tag_bool:
146
| TRUE  { tag_true }
147
| FALSE { tag_false }
148

    
149
tag_ident:
150
| t=UIDENT   { t }
151
| t=tag_bool { t }
152

    
153
node_ident:
154
| n=ident { n }
155

    
156
node_ident_decl:
157
| n=node_ident { push_node n }
158

    
159
vdecl_ident:
160
| x=ident { mkident x }
161

    
162
const_ident:
163
| c=ident { c }
164

    
165
type_ident:
166
| t=IDENT { t }
167

    
168
prog:
169
| p=prefix ds=flatten(top_decl*) EOF { List.map ((|>) false) p @ ds }
170

    
171
header:
172
| p=prefix ds=flatten(top_decl_header*) EOF { List.map ((|>) true) p @ ds }
173

    
174
prefix:
175
|                      { [] }
176
| o=open_lusi p=prefix { (fun _ -> o) :: p }
177
| td=typ_def p=prefix  { (fun is_header -> td is_header) :: p }
178

    
179
open_lusi:
180
| OPEN QUOTE p=path_ident QUOTE    { mktop_decl false (Open (true, p)) }
181
| INCLUDE QUOTE p=path_ident QUOTE { mktop_decl false (Include p) }
182
| OPEN LT p=path_ident GT          { mktop_decl false (Open (false, p))  }
183

    
184
state_annot:
185
| FUNCTION { true }
186
| NODE     { false }
187

    
188
top_decl_header:
189
| CONST ds=cdecl+ SCOL
190
  { List.map ((|>) true) ds }
191
| nodei_spec=nodespecs nodei_stateless=state_annot nodei_id=node_ident_decl
192
  LPAR nodei_inputs=vdecl_list SCOL? RPAR
193
  RETURNS LPAR nodei_outputs=vdecl_list SCOL? RPAR
194
  nodei_prototype=preceded(PROTOTYPE, node_ident)?
195
  nodei_in_lib=preceded(LIB, module_ident)* SCOL
196
  { let nd = mktop_decl true (ImportedNode {
197
                                  nodei_id;
198
                                  nodei_type = Types.new_var ();
199
                                  nodei_clock = Clocks.new_var true;
200
                                  nodei_inputs;
201
                                  nodei_outputs;
202
                                  nodei_stateless;
203
                                  nodei_spec;
204
                                  nodei_prototype;
205
                                  nodei_in_lib
206
               })
207
    in
208
    pop_node ();
209
    [nd]
210
  }
211
| c=top_contract
212
  { [c] }
213

    
214
top_decl:
215
| CONST ds=cdecl+ SCOL
216
  { List.map ((|>) false) ds }
217
| node_dec_stateless=state_annot node_id=node_ident_decl
218
  LPAR node_inputs=vdecl_list SCOL? RPAR
219
  RETURNS LPAR node_outputs=vdecl_list SCOL? RPAR SCOL?
220
  node_spec=nodespecs
221
  node_locals=locals LET content=stmt_list TEL
222
  { let node_stmts, node_asserts, node_annot = content in
223
    (* Declaring eqs annots *)
224
    List.iter (fun ann ->
225
        List.iter (fun (key, _) ->
226
            Annotations.add_node_ann node_id key)
227
          ann.annots)
228
      node_annot;
229
    (* Building the node *)
230
    let nd = mktop_decl false (Node
231
                                 {node_id;
232
                                  node_type = Types.new_var ();
233
                                  node_clock = Clocks.new_var true;
234
                                  node_inputs;
235
                                  node_outputs;
236
                                  node_locals;
237
                                  node_gencalls = [];
238
                                  node_checks = [];
239
                                  node_asserts;
240
                                  node_stmts;
241
                                  node_dec_stateless;
242
                                  node_stateless = None;
243
                                  node_spec;
244
                                  node_annot;
245
                                  node_iscontract = false;
246
               })
247
    in
248
    pop_node ();
249
    (*add_node $3 nd;*)
250
    [nd]
251
  }
252
| s=NODESPEC
253
  { match s with
254
    | LocalContract _ -> assert false
255
    | TopContract c   -> c
256
  }
257

    
258
nodespecs:
259
| ss=nodespec_list
260
  { match ss with
261
    | None   -> None
262
    | Some c -> Some (Contract c)
263
  }
264

    
265
nodespec_list:
266
| { None }
267
| s=NODESPEC ss=nodespec_list
268
  { let extract x = match x with LocalContract c -> c | _ -> assert false in
269
    let s1 = extract s in
270
    match ss with
271
    | None -> Some s1
272
    | Some s2 -> Some (merge_contracts s1 s2)
273
  }
274

    
275
typ_def:
276
| TYPE tydef_id=type_ident EQ tydef_desc=typ_def_rhs SCOL
277
  { fun itf ->
278
    let typ = mktop_decl itf (TypeDef { tydef_id; tydef_desc }) in
279
    (*add_type itf $2 typ;*)
280
    typ
281
  }
282

    
283
typ_def_rhs:
284
| t=typeconst
285
  { t }
286
| ENUM LCUR ts=separated_nonempty_list(COMMA, UIDENT) RCUR
287
  { Tydec_enum ts }
288
| STRUCT LCUR fs=separated_list(SCOL, separated_pair(IDENT, COL, typeconst)) RCUR
289
  { Tydec_struct fs }
290

    
291
%inline array_typ_decl:
292
|                          { [] }
293
| ds=preceded(POWER, dim)+ { ds }
294

    
295
typeconst:
296
| TINT ds=array_typ_decl         { mkarraytype Tydec_int ds }
297
| TBOOL ds=array_typ_decl        { mkarraytype Tydec_bool ds }
298
| TREAL ds=array_typ_decl        { mkarraytype Tydec_real ds }
299
/* | TFLOAT ds=array_typ_decl { mkarraytype Tydec_float ds } */
300
| t=type_ident ds=array_typ_decl { mkarraytype (Tydec_const t) ds }
301
| TBOOL TCLOCK                   { Tydec_clock Tydec_bool }
302
| t=IDENT TCLOCK                 { Tydec_clock (Tydec_const t) }
303

    
304
stmt_list:
305
| { [], [], [] }
306
| e=eq ss=stmt_list
307
  { let eql, assertl, annotl = ss in
308
    Eq e :: eql, assertl, annotl
309
  }
310
| a=assert_ ss=stmt_list
311
  { let eql, assertl, annotl = ss in
312
    eql, a :: assertl, annotl
313
  }
314
| a=ANNOT ss=stmt_list
315
  { let eql, assertl, annotl = ss in
316
    eql, assertl, a :: annotl
317
  }
318
| a=automaton ss=stmt_list
319
  { let eql, assertl, annotl = ss in
320
    Aut a :: eql, assertl, annotl
321
  }
322

    
323
automaton:
324
| AUTOMATON t=type_ident hs=handler* { Automata.mkautomata (get_loc ()) t hs }
325

    
326
handler:
327
| STATE x=UIDENT COL ul=unless* l=locals LET ss=stmt_list TEL ut=until*
328
  { Automata.mkhandler (get_loc ()) x ul ut l ss }
329

    
330
unless:
331
| UNLESS e=expr RESTART s=UIDENT { get_loc (), e, true, s  }
332
| UNLESS e=expr RESUME s=UIDENT  { get_loc (), e, false, s }
333

    
334
until:
335
| UNTIL e=expr RESTART s=UIDENT { get_loc (), e, true, s }
336
| UNTIL e=expr RESUME s=UIDENT  { get_loc (), e, false, s }
337

    
338
assert_:
339
| ASSERT e=expr SCOL { mkassert e }
340

    
341
eq:
342
| xs=pattern EQ e=expr SCOL {mkeq (List.map fst xs, e)}
343

    
344
%inline pattern:
345
| xs=ident_list           { xs }
346
| LPAR xs=ident_list RPAR { xs }
347

    
348
lustre_spec:
349
| cs=top_contract+ EOF   { TopContract cs }
350
| c=contract_content EOF { LocalContract c }
351

    
352
top_contract:
353
| CONTRACT node_id=node_ident_decl
354
  LPAR node_inputs=vdecl_list SCOL? RPAR
355
  RETURNS LPAR node_outputs=vdecl_list SCOL? RPAR SCOL?
356
  LET cc=contract_content TEL
357
  { let nd = mktop_decl true (Node {
358
                                  node_id;
359
                                  node_type = Types.new_var ();
360
                                  node_clock = Clocks.new_var true;
361
                                  node_inputs;
362
                                  node_outputs;
363
                                  node_locals = []; (* will be filled later *)
364
                                  node_gencalls = [];
365
                                  node_checks = [];
366
                                  node_asserts = [];
367
                                  node_stmts = []; (* will be filled later *)
368
                                  node_dec_stateless = false;
369
                                  (* By default we assume contracts as stateful *)
370
                                  node_stateless = None;
371
                                  node_spec = Some (Contract cc);
372
                                  node_annot = [];
373
                                  node_iscontract = true;
374
                                }
375
               )
376
    in
377
    pop_node ();
378
    (*add_imported_node $3 nd;*)
379
    nd
380
  }
381

    
382
contract_content:
383
| { empty_contract }
384
| CONTRACT cc=contract_content
385
  { cc }
386
| CONST x=IDENT COL t=typeconst? EQ e=expr SCOL cc=contract_content
387
  { merge_contracts (mk_contract_var x true (mkotyp t) e (get_loc())) cc }
388
| VAR x=IDENT COL t=typeconst EQ e=expr SCOL cc=contract_content
389
  { merge_contracts (mk_contract_var x false (Some (mktyp t)) e (get_loc())) cc }
390
| ASSUME x=ioption(STRING) e=qexpr SCOL cc=contract_content
391
  { merge_contracts (mk_contract_assume x e) cc }
392
| GUARANTEES x=ioption(STRING) e=qexpr SCOL cc=contract_content
393
  { merge_contracts (mk_contract_guarantees x e) cc }
394
| MODE x=IDENT LPAR mc=mode_content RPAR SCOL cc=contract_content
395
  { merge_contracts (
396
        let r, e = mc in
397
        mk_contract_mode x r e (get_loc())) cc
398
  }
399
| IMPORT x=IDENT LPAR xs=expr_or_tuple RPAR RETURNS LPAR ys=expr_or_tuple RPAR
400
  SCOL cc=contract_content
401
  { merge_contracts (mk_contract_import x xs ys (get_loc())) cc }
402

    
403
%inline expr_or_tuple:
404
| e=expr                     { e }
405
| e=expr COMMA es=array_expr { mkexpr (Expr_tuple (e :: es)) }
406

    
407
mode_content:
408
| { [], [] }
409
| REQUIRE eexpr_name=ioption(STRING) qe=qexpr SCOL mc=mode_content
410
  { let (r, e) = mc in
411
    { qe with eexpr_name } :: r, e }
412
| ENSURE eexpr_name=ioption(STRING) qe=qexpr SCOL mc=mode_content
413
  { let (r, e) = mc in
414
    r, { qe with eexpr_name } :: e }
415

    
416
(* /* WARNING: UNUSED RULES */
417
 * tuple_qexpr:
418
 * | qexpr COMMA qexpr {[$3;$1]}
419
 * | tuple_qexpr COMMA qexpr {$3::$1} *)
420

    
421
qexpr:
422
| e=expr                      { mkeexpr e }
423
  /* Quantifiers */
424
| EXISTS x=vdecl SCOL e=qexpr { extend_eexpr [Exists, x] e }
425
| FORALL x=vdecl SCOL e=qexpr { extend_eexpr [Forall, x] e }
426

    
427
(* %inline tuple_expr:
428
 * | e=expr COMMA es=array_expr { e :: es } *)
429

    
430
// Same as tuple expr but accepting lists with single element
431
%inline array_expr:
432
| es=separated_nonempty_list(COMMA, expr) { es }
433

    
434
expr:
435
/* constants */
436
| c=INT                   { mkexpr (Expr_const (Const_int c)) }
437
| c=REAL                  { mkexpr (Expr_const (Const_real c)) }
438
| c=STRING %prec p_string { mkexpr (Expr_const (Const_string c)) }
439
| COLCOL c=IDENT          { mkexpr (Expr_const (Const_modeid c)) }
440
/* | c=FLOAT { mkexpr (Expr_const (Const_float c)) }*/
441

    
442
/* Idents or type enum tags */
443
| x=IDENT    { mkexpr (Expr_ident x) }
444
| x=UIDENT   { mkexpr (Expr_ident x) (* TODO we will differenciate enum constants from variables later *) }
445
| t=tag_bool { mkexpr (Expr_const (Const_tag t)) } (* on sept 2014, X changed the Const to
446
                                                      mkexpr (Expr_ident $1)
447
                                                      reverted back to const on july 2019 *)
448
| LPAR a=ANNOT e=expr RPAR  { update_expr_annot (get_current_node ()) e a }
449
| LPAR e=expr_or_tuple RPAR { e }
450

    
451
/* Array expressions */
452
| LBRACKET es=array_expr RBRACKET
453
  { mkexpr (Expr_array es) }
454
| e=expr POWER d=dim
455
  { mkexpr (Expr_power (e, d)) }
456
| e=expr ds=delimited(LBRACKET, dim, RBRACKET)+
457
  { List.fold_left (fun base d -> mkexpr (Expr_access (base, d))) e ds }
458

    
459
/* Temporal operators */
460
| PRE e=expr
461
  { mkexpr (Expr_pre e) }
462
| e1=expr ARROW e2=expr
463
  { mkexpr (Expr_arrow (e1, e2)) }
464
| e1=expr FBY e2=expr
465
  { mkexpr (Expr_arrow (e1, mkexpr (Expr_pre e2))) }
466
| e=expr WHEN x=vdecl_ident
467
  { mkexpr (Expr_when (e, fst x, tag_true)) }
468
| e=expr WHENNOT x=vdecl_ident
469
  { mkexpr (Expr_when (e, fst x, tag_false)) }
470
| e=expr WHEN t=tag_ident LPAR x=vdecl_ident RPAR
471
  { mkexpr (Expr_when (e, fst x, t)) }
472
| MERGE x=vdecl_ident
473
  hs=delimited(LPAR, separated_pair(tag_ident, ARROW, expr), RPAR)*
474
  { mkexpr (Expr_merge (fst x, hs)) }
475

    
476
/* Applications */
477
| f=node_ident LPAR es=expr_or_tuple RPAR r=preceded(EVERY, expr)?
478
  { match f, es.expr_desc, r with
479
    | "fbyn", Expr_tuple [expr; n; init], None ->
480
       let n = match n.expr_desc with
481
         | Expr_const (Const_int n) -> n
482
         | _ -> assert false
483
       in
484
       fby expr n init
485
    | "fbyn", _ , Some _ ->
486
       assert false (* TODO Ca veut dire quoi fby (e,n,init) every c *)
487
    | _ -> mkexpr (Expr_appl (f, es, r))
488
  }
489

    
490
/* Boolean expr */
491
| e1=expr AND e2=expr         { mkpredef_call_b "&&" e1 e2 }
492
| e1=expr AMPERAMPER e2=expr  { mkpredef_call_b "&&" e1 e2 }
493
| e1=expr OR e2=expr          { mkpredef_call_b "||" e1 e2 }
494
| e1=expr BARBAR e2=expr      { mkpredef_call_b "||" e1 e2 }
495
| e1=expr XOR e2=expr         { mkpredef_call_b "xor" e1 e2 }
496
| NOT e=expr                  { mkpredef_call_u "not" e }
497
| e1=expr IMPL e2=expr        { mkpredef_call_b "impl" e1 e2 }
498

    
499
/* Comparison expr */
500
| e1=expr EQ e2=expr          { mkpredef_call_b "=" e1 e2 }
501
| e1=expr LT e2=expr          { mkpredef_call_b "<" e1 e2 }
502
| e1=expr LTE e2=expr         { mkpredef_call_b "<=" e1 e2 }
503
| e1=expr GT e2=expr          { mkpredef_call_b ">" e1 e2 }
504
| e1=expr GTE e2=expr         { mkpredef_call_b ">=" e1 e2 }
505
| e1=expr NEQ e2=expr         { mkpredef_call_b "!=" e1 e2 }
506

    
507
/* Arithmetic expr */
508
| e1=expr PLUS e2=expr        { mkpredef_call_b "+" e1 e2 }
509
| e1=expr MINUS e2=expr       { mkpredef_call_b "-" e1 e2 }
510
| e1=expr MULT e2=expr        { mkpredef_call_b "*" e1 e2 }
511
| e1=expr DIV e2=expr         { mkpredef_call_b "/" e1 e2 }
512
| MINUS e=expr %prec p_uminus { mkpredef_call_u "uminus" e }
513
| e1=expr MOD e2=expr         { mkpredef_call_b "mod" e1 e2 }
514

    
515
/* If */
516
| IF e=expr THEN t=expr ELSE f=expr { mkexpr (Expr_ite (e, t, f)) }
517

    
518
signed_const:
519
| c=INT
520
  { Const_int c }
521
| c=REAL
522
  { Const_real c }
523
/* | c=FLOAT { Const_float c } */
524
| t=tag_ident { Const_tag t }
525
| MINUS c=INT
526
  { Const_int (-1 * c) }
527
| MINUS c=REAL
528
  { Const_real (Real.uminus c) }
529
/* | MINUS c=FLOAT { Const_float (-1. *. c) } */
530
| LCUR
531
  cs=separated_nonempty_list(COMMA, separated_pair(IDENT, EQ, signed_const))
532
  RCUR
533
  { Const_struct cs }
534
| LBRACKET cs=separated_nonempty_list(COMMA, signed_const) RBRACKET
535
  { Const_array cs }
536

    
537
dim:
538
| i=INT                      { mkdim_int i }
539
| LPAR d=dim RPAR            { d }
540
| x=ident                    { mkdim_ident x }
541
| d1=dim AND d2=dim          { mkdim_appl_b "&&" d1 d2 }
542
| d1=dim AMPERAMPER d2=dim   { mkdim_appl_b "&&" d1 d2 }
543
| d1=dim OR d2=dim           { mkdim_appl_b "||" d1 d2 }
544
| d1=dim BARBAR d2=dim       { mkdim_appl_b "||" d1 d2 }
545
| d1=dim XOR d2=dim          { mkdim_appl_b "xor" d1 d2 }
546
| NOT d=dim                  { mkdim_appl_u "not" d }
547
| d1=dim IMPL d2=dim         { mkdim_appl_b "impl" d1 d2 }
548

    
549
/* Comparison dim */
550
| d1=dim EQ d2=dim           { mkdim_appl_b "=" d1 d2 }
551
| d1=dim LT d2=dim           { mkdim_appl_b "<" d1 d2 }
552
| d1=dim LTE d2=dim          { mkdim_appl_b "<=" d1 d2 }
553
| d1=dim GT d2=dim           { mkdim_appl_b ">" d1 d2 }
554
| d1=dim GTE  d2=dim         { mkdim_appl_b ">=" d1 d2 }
555
| d1=dim NEQ d2=dim          { mkdim_appl_b "!=" d1 d2 }
556

    
557
/* Arithmetic dim */
558
| d1=dim PLUS d2=dim         { mkdim_appl_b "+" d1 d2 }
559
| d1=dim MINUS d2=dim        { mkdim_appl_b "-" d1 d2 }
560
| d1=dim MULT d2=dim         { mkdim_appl_b "*" d1 d2 }
561
| d1=dim DIV d2=dim          { mkdim_appl_b "/" d1 d2 }
562
| MINUS d=dim %prec p_uminus { mkdim_appl_u "uminus" d }
563
| d1=dim MOD d2=dim          { mkdim_appl_b "mod" d1 d2 }
564

    
565
/* If */
566
| IF d=dim THEN t=dim ELSE f=dim { mkdim_ite d t f }
567

    
568
%inline locals:
569
| xs=loption(preceded(VAR, flatten(separated_nonempty_list(SCOL, local_vdecl))))
570
  { xs }
571

    
572
vdecl_list:
573
| d=vdecl %prec p_vdecl { d }
574
| d=vdecl SCOL ds=vdecl_list { d @ ds }
575

    
576
vdecl:
577
| xs=ident_list COL t=typeconst c=clock?
578
  { mkvdecls false (Some t) c None xs }
579
| CONST xs=ident_list t=preceded(COL, typeconst)?
580
  /* static parameters don't have clocks */
581
  { mkvdecls true t None None xs }
582

    
583
local_vdecl:
584
| xs=ident_list /* Useless no ?*/
585
  { mkvdecls false None None None xs }
586
| xs=ident_list COL t=typeconst c=clock?
587
  { mkvdecls false (Some t) c None xs }
588
| CONST x=vdecl_ident t=preceded(COL, typeconst)? EQ e=expr
589
  /* static parameters don't have clocks */
590
  { mkvdecls true t None (Some e) [x] }
591

    
592
cdecl:
593
| x=const_ident EQ c=signed_const
594
  { fun itf ->
595
    let c = mktop_decl itf (Const {
596
                                const_id = x;
597
                                const_loc = get_loc ();
598
                                const_type = Types.new_var ();
599
                                const_value = c
600
              })
601
    in
602
    (*add_const itf $1 c;*)
603
    c
604
  }
605

    
606
%inline clock:
607
| l=when_cond+ { mkclock (Ckdec_bool l) }
608

    
609
when_cond:
610
| WHEN x=IDENT                       { x, tag_true }
611
| WHENNOT x=IDENT                    { x, tag_false }
612
| WHEN t=tag_ident LPAR x=IDENT RPAR { x, t }
613

    
614
%inline ident_list:
615
| ds=separated_nonempty_list(COMMA, vdecl_ident) { ds }
616

    
617
lustre_annot:
618
| lustre_annot_list EOF { { annots = $1; annot_loc = get_loc () } }
619

    
620
lustre_annot_list:
621
  { [] } 
622
| kwd COL qexpr SCOL lustre_annot_list { ($1,$3)::$5 }
623
| IDENT COL qexpr SCOL lustre_annot_list { ([$1],$3)::$5 }
624
| INVARIANT COL qexpr SCOL lustre_annot_list{ (["invariant"],$3)::$5 }
625
// (* | OBSERVER COL qexpr SCOL lustre_annot_list { (["observer"],$3)::$5 } *)
626
| CCODE COL qexpr SCOL lustre_annot_list{ (["c_code"],$3)::$5 }
627
| MATLAB COL qexpr SCOL lustre_annot_list{ (["matlab"],$3)::$5 }
628

    
629

    
630
kwd:
631
DIV { [] }
632
| DIV IDENT kwd { $2::$3}
633

    
634
%%
635
(* Local Variables: *)
636
(* compile-command:"make -C .." *)
637
(* End: *)
638

    
639

    
(7-7/7)