File: cfg_parser.mly

package info (click to toggle)
why3 1.8.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 45,020 kB
  • sloc: xml: 185,443; ml: 111,224; ansic: 3,998; sh: 2,578; makefile: 2,568; java: 865; python: 720; javascript: 290; lisp: 205; pascal: 173
file content (116 lines) | stat: -rw-r--r-- 3,250 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
(********************************************************************)
(*                                                                  *)
(*  The Why3 Verification Platform   /   The Why3 Development Team  *)
(*  Copyright 2010-2025 --  Inria - CNRS - Paris-Saclay University  *)
(*                                                                  *)
(*  This software is distributed under the terms of the GNU Lesser  *)
(*  General Public License version 2.1, with the special exception  *)
(*  on linking described in file LICENSE.                           *)
(********************************************************************)

%{

  open Why3
  open Cfg_ast

  let floc s e = Loc.extract (s,e)

  let mk_cfginstr d s e = { cfg_instr_desc = d; cfg_instr_loc = floc s e }
  let mk_cfgterm d s e = { cfg_term_desc = d; cfg_term_loc = floc s e }

%}

(* extra tokens *)
%token CFG GOTO VAR SWITCH

%start cfgfile
%type <Cfg_ast.cfg_file> cfgfile
%type <Cfg_ast.cfg_instr list * Cfg_ast.cfg_term> sequence
%type <Cfg_ast.switch_branch list> cases

%%

cfgfile:
  | ml=cfgmodule* EOF { ml }
;

cfgmodule:
  | id=module_head_parsing_only dl=cfgdecl* END
    { (id,dl) }

cfgdecl:
  | scope_head_parsing_only cfgdecl* END
      { let loc,import,qid = $1 in (Cfg_ast.Dscope(loc,import,qid,$2))}
  | IMPORT uqualid { (Dmlw_decl (Dimport $2)) }
  | d = pure_decl | d = prog_decl | d = meta_decl { Dmlw_decl d }
  | use_clone_parsing_only { Dmlw_decl $1 }
  | LET CFG f=recdefn { Dletcfg f }
  | LET REC CFG dl=with_list1(recdefn) { Dreccfg dl }
;

recdefn:
  | cf_name=attrs(lident_rich) cf_args=binders COLON ret=return_named sp=spec EQUAL
      cf_attrs=attr* cf_locals=vardecls cf_block0=block cf_blocks=labelblock*
    { let cf_pat, cf_retty, cf_mask = ret in
      let cf_spec = apply_return cf_pat sp in
      { cf_name; cf_args; cf_retty; cf_pat; cf_mask; cf_spec; cf_attrs;
        cf_locals; cf_block0; cf_blocks } }
;

vardecls:
  | /* epsilon */ { [] }
  | vardecl vardecls { $1 @ $2 }
;

vardecl:
  | g=ghost_opt VAR vl=attrs(lident_nq)* COLON t=ty init=init_opt SEMICOLON
    { List.map (fun id -> (g,id,t, init)) vl }
;

init_opt:
| /* epsilon */ { None }
| EQUAL contract_expr { Some($2) }

ghost_opt:
  | /* epsilon */ { false }
  | GHOST         { true }

labelblock:
  | id = attrs(uident) b=block  { (id,b) }
;

block:
  | LEFTBRC sequence RIGHTBRC { $2 }
;

sequence:
  | terminator { ([], $1) }
  | x=instr SEMICOLON xl = sequence { (x :: fst xl, snd xl) }
;

instr:
  | contract_expr
    { mk_cfginstr (CFGexpr $1) $startpos $endpos }
  | VARIANT LEFTBRC t=term RIGHTBRC
    { mk_cfginstr (CFGinvariant [Variant, None, t, ref None]) $startpos $endpos }
  | INVARIANT nm=option(ident) LEFTBRC t=term RIGHTBRC
    { mk_cfginstr (CFGinvariant [Invariant, nm, t, ref None]) $startpos $endpos }
;

terminator :
  | GOTO uident
    { mk_cfgterm (CFGgoto $2) $startpos $endpos }
  | SWITCH LEFTPAR contract_expr RIGHTPAR cases END
    { mk_cfgterm (CFGswitch ($3,$5)) $startpos $endpos }
  | RETURN contract_expr
    { mk_cfgterm (CFGreturn $2) $startpos $endpos }
  | ABSURD
    { mk_cfgterm CFGabsurd $startpos $endpos }
;

cases:
  | BAR match_case(terminator)
    { [$2] }
  | BAR match_case(terminator) cases
    { $2 :: $3 }
;