From e266b9bafdbf11f1da509cc3cf5b5b0ccfc663bf Mon Sep 17 00:00:00 2001
From: Patrick Baudin <patrick.baudin@cea.fr>
Date: Fri, 13 Jan 2023 10:25:00 +0100
Subject: [PATCH] init using menhir for the logic parser

---
 src/kernel_internals/parsing/dune             |   6 +-
 src/kernel_internals/parsing/logic_parser.mly | 395 +++++++++---------
 2 files changed, 207 insertions(+), 194 deletions(-)

diff --git a/src/kernel_internals/parsing/dune b/src/kernel_internals/parsing/dune
index 9e358da57e0..62f70545cee 100644
--- a/src/kernel_internals/parsing/dune
+++ b/src/kernel_internals/parsing/dune
@@ -24,7 +24,11 @@
 (ocamllex logic_preprocess)
 (ocamllex logic_lexer)
 
-(ocamlyacc logic_parser)
+(menhir
+  (modules logic_parser)
+  ; "--fixed-exception" fixes compatibility with ocamlyacc Parsing.Parse_error
+  (flags --fixed-exception --explain --dump --comment)
+)
 
 (menhir
   (modules cparser)
diff --git a/src/kernel_internals/parsing/logic_parser.mly b/src/kernel_internals/parsing/logic_parser.mly
index be05d3183e0..7303ac32078 100644
--- a/src/kernel_internals/parsing/logic_parser.mly
+++ b/src/kernel_internals/parsing/logic_parser.mly
@@ -30,20 +30,19 @@
   open Logic_ptree
   open Logic_utils
 
-  let loc () =
+  let loc (start_pos, end_pos) =
     Cil_datatype.Location.of_lexing_loc
-      (symbol_start_pos (), symbol_end_pos ())
-  let lexeme_start nb =
-    Cil_datatype.Position.of_lexing_pos (Parsing.rhs_start_pos nb)
-  let lexeme_end nb =
-    Cil_datatype.Position.of_lexing_pos (Parsing.rhs_end_pos nb)
-  let lexeme_loc nb = (lexeme_start nb, lexeme_end nb)
-
-  let info x = { lexpr_node = x; lexpr_loc = loc () }
-  let loc_info loc x = { lexpr_node = x; lexpr_loc = loc }
+      (start_pos, end_pos)
+
+  let pos pos =
+    Cil_datatype.Position.of_lexing_pos pos
+
+  let loc_info lexpr_loc x = { lexpr_node = x; lexpr_loc }
   let loc_start x = fst x.lexpr_loc
   let loc_end x = snd x.lexpr_loc
 
+  let info start_end x = loc_info (loc start_end) x
+
   (* Normalize p1 && (p2 && p3) into (p1 && p2) && p3 *)
   let rec pland p1 p2 =
     match p2.lexpr_node with
@@ -59,17 +58,17 @@
         PLor(loc_info loc (plor p1 p3),p4)
       | _ -> PLor(p1,p2)
 
-  let clause_order i name1 name2 =
+  let clause_order start_end name1 name2 =
     raise
       (Not_well_formed
-         (lexeme_loc i,
+         (loc start_end,
           "wrong order of clause in contract: "
           ^ name1 ^ " after " ^ name2 ^ "."))
 
-  let missing i token next_token =
+  let missing start_end token next_token =
     raise
       (Not_well_formed
-         (lexeme_loc i,
+         (loc start_end,
           Format.asprintf "expecting '%s' before %s" token next_token))
 
   type sense_of_relation = Unknown | Disequal | Less | Greater
@@ -105,9 +104,9 @@
 
   let is_rt_type () = !rt_type
 
-  let loc_decl d = { decl_node = d; decl_loc = loc () }
+  let loc_decl start_end d = { decl_node = d; decl_loc = loc start_end }
 
-  let loc_ext d = { extended_node = d; extended_loc = loc () }
+  let loc_ext start_end d = { extended_node = d; extended_loc = loc start_end }
 
   let filter_from l = function
     | FromAny ->
@@ -168,16 +167,16 @@
       | FreeAlloc(f1,a1),FreeAlloc(f2,a2) -> FreeAlloc(f2@f1,a2@a1)
 
   (* a1 represents the assigns _after_ the current clause a2. *)
-  let concat_assigns a1 a2 =
+  let concat_assigns start_pos a1 a2 =
     match a1,a2 with
         WritesAny,a -> Writes (concat_froms [] a)
       | Writes [], [] -> a1
       | Writes [], _  | Writes _, [] ->
         raise (
-          Not_well_formed (loc(),"Mixing \\nothing and a real location"))
+          Not_well_formed (loc start_pos,"Mixing \\nothing and a real location"))
       | Writes a1, a2 -> Writes (concat_froms (concat_froms [] a2) a1)
 
-  let concat_loop_assigns_allocation annots bhvs2 a2 fa2=
+  let concat_loop_assigns_allocation start_pos annots bhvs2 a2 fa2=
     (* NB: this is supposed to merge assigns related to named behaviors, in
        case of annotation like
        for a,b: assigns x,y;
@@ -203,7 +202,7 @@
             (match both with
               | [] -> bhvs2, ca::acc
               | _ ->
-                let common_annot = AAssigns(both,concat_assigns a1 a2) in
+                let common_annot = AAssigns(both,concat_assigns start_pos a1 a2) in
                 let annots =
                   match only1 with
                     | [] -> common_annot :: acc
@@ -340,22 +339,27 @@
 %%
 
 enter_kw_c_mode:
-/* empty */ { enter_kw_c_mode () }
+| /* empty */ { enter_kw_c_mode () }
+;
 
 exit_kw_c_mode:
-/* empty */ { exit_kw_c_mode () }
+| /* empty */ { exit_kw_c_mode () }
+;
 
 enter_rt_type:
-/* empty */ { if is_rt_type () then enter_rt_type_mode () }
+| /* empty */ { if is_rt_type () then enter_rt_type_mode () }
+;
 
 exit_rt_type:
-/* empty */ { if is_rt_type () then exit_rt_type_mode () }
+| /* empty */ { if is_rt_type () then exit_rt_type_mode () }
+;
 
 begin_rt_type:
-/* empty */ { set_rt_type () }
+| /* empty */ { set_rt_type () }
 
 end_rt_type:
-/* empty */ { reset_rt_type () }
+| /* empty */ { reset_rt_type () }
+;
 
 /*** predicates and terms ***/
 
@@ -380,30 +384,30 @@ lexpr_option:
 
 lexpr:
   /* predicates */
-| lexpr IMPLIES lexpr { info (PLimplies ($1, $3)) }
-| lexpr IFF lexpr { info (PLiff ($1, $3)) }
-| lexpr OR lexpr     { info (plor $1 $3) }
-| lexpr AND lexpr    { info (pland $1 $3) }
-| lexpr HATHAT lexpr    { info (PLxor ($1, $3)) }
+| lexpr IMPLIES lexpr { info $sloc (PLimplies ($1, $3)) }
+| lexpr IFF lexpr { info $sloc (PLiff ($1, $3)) }
+| lexpr OR lexpr     { info $sloc (plor $1 $3) }
+| lexpr AND lexpr    { info $sloc (pland $1 $3) }
+| lexpr HATHAT lexpr    { info $sloc (PLxor ($1, $3)) }
 /* terms */
-| lexpr AMP lexpr { info (PLbinop ($1, Bbw_and, $3)) }
-| lexpr PIPE lexpr { info (PLbinop ($1, Bbw_or, $3)) }
-| lexpr HAT lexpr { info (PLbinop ($1, Bbw_xor, $3)) }
-| lexpr BIMPLIES lexpr { info (PLbinop (info (PLunop (Ubw_not, $1)), Bbw_or, $3)) }
-| lexpr BIFF lexpr { info (PLbinop (info (PLunop (Ubw_not, $1)), Bbw_xor, $3)) }
-| lexpr IN lexpr { info (PLapp ("\\subset", [], [info ((PLset [$1]));$3])) }
+| lexpr AMP lexpr { info $sloc (PLbinop ($1, Bbw_and, $3)) }
+| lexpr PIPE lexpr { info $sloc (PLbinop ($1, Bbw_or, $3)) }
+| lexpr HAT lexpr { info $sloc (PLbinop ($1, Bbw_xor, $3)) }
+| lexpr BIMPLIES lexpr { info $sloc (PLbinop (info $sloc (PLunop (Ubw_not, $1)), Bbw_or, $3)) }
+| lexpr BIFF lexpr { info $sloc (PLbinop (info $sloc (PLunop (Ubw_not, $1)), Bbw_xor, $3)) }
+| lexpr IN lexpr { info $sloc (PLapp ("\\subset", [], [info $sloc (PLset [$1]);$3])) }
 | lexpr QUESTION lexpr COLON2 lexpr %prec prec_question
-    { info (PLif ($1, $3, $5)) }
+    { info $sloc (PLif ($1, $3, $5)) }
 /* both terms and predicates */
-| any_identifier COLON lexpr %prec prec_named { info (PLnamed ($1, $3)) }
+| any_identifier COLON lexpr %prec prec_named { info $sloc (PLnamed ($1, $3)) }
 | string COLON lexpr %prec prec_named
       { let (iswide,str) = $1 in
         if iswide then begin
-           let l = loc () in
+           let l = loc $sloc in
            raise (Not_well_formed(l, "Wide strings are not allowed as labels."))
          end;
         let str = escape str in
-         info (PLnamed (str, $3))
+         info $sloc (PLnamed (str, $3))
        }
 | lexpr_rel { $1 }
 ;
@@ -416,24 +420,25 @@ lexpr_rel:
         let relation = loc_info loc (PLrel($1,rel,rhs)) in
         match oth_rel with
             None -> relation
-          | Some oth_relation -> info (pland relation oth_relation)
+          | Some oth_relation -> info $sloc (pland relation oth_relation)
       }
 ;
 
 lexpr_binder:
-| LET bounded_var EQUAL lexpr SEMICOLON lexpr %prec LET {info (PLlet($2,$4,$6))}
+| LET bounded_var EQUAL lexpr SEMICOLON lexpr %prec LET
+      { info $sloc (PLlet($2,$4,$6))}
 | FORALL binders SEMICOLON lexpr  %prec prec_forall
-      { info (PLforall ($2, $4)) }
+      { info $sloc (PLforall ($2, $4)) }
 | EXISTS binders SEMICOLON lexpr  %prec prec_exists
-      { info (PLexists ($2, $4)) }
+      { info $sloc (PLexists ($2, $4)) }
 | LAMBDA binders SEMICOLON lexpr  %prec prec_lambda
-      { info (PLlambda ($2,$4)) }
+      { info $sloc (PLlambda ($2,$4)) }
 ;
 
 lexpr_end_rel:
   lexpr_inner  { $1 }
 | lexpr_binder { $1 }
-| NOT lexpr_binder { info (PLnot $2) }
+| NOT lexpr_binder { info $sloc (PLnot $2) }
 ;
 
 rel_list:
@@ -455,7 +460,7 @@ rel_list:
       in
       $1,$2,sense,Some oth_rel
     else begin
-      let loc = lexeme_start 1, lexeme_end 3 in
+      let loc = loc $sloc in
       raise (Not_well_formed(loc,"Inconsistent relation chain."));
     end
   }
@@ -470,7 +475,7 @@ relation:
 | NE    { Neq }
     /* C. Marche: added to produce better error messages */
 | EQUAL {
-      let l = loc () in
+      let l = loc $sloc in
       raise
         (Not_well_formed(l,
                          "Assignment operators not allowed in annotations."))
@@ -485,114 +490,114 @@ lexpr_inner:
       else
         StringConstant content
       in
-      info (PLconstant cst)
+      info $sloc (PLconstant cst)
     }
-| NOT lexpr_inner { info (PLnot $2) }
-| TRUE { info PLtrue }
-| FALSE { info PLfalse }
-| OBJECT_POINTER opt_label_1 LPAR lexpr RPAR { info (PLobject_pointer ($2,$4)) }
-| VALID opt_label_1 LPAR lexpr RPAR { info (PLvalid ($2,$4)) }
-| VALID_READ opt_label_1 LPAR lexpr RPAR { info (PLvalid_read ($2,$4)) }
-| VALID_FUNCTION LPAR lexpr RPAR { info (PLvalid_function $3) }
+| NOT lexpr_inner { info $sloc (PLnot $2) }
+| TRUE { info $sloc PLtrue }
+| FALSE { info $sloc PLfalse }
+| OBJECT_POINTER opt_label_1 LPAR lexpr RPAR { info $sloc (PLobject_pointer ($2,$4)) }
+| VALID opt_label_1 LPAR lexpr RPAR { info $sloc (PLvalid ($2,$4)) }
+| VALID_READ opt_label_1 LPAR lexpr RPAR { info $sloc (PLvalid_read ($2,$4)) }
+| VALID_FUNCTION LPAR lexpr RPAR { info $sloc (PLvalid_function $3) }
 | VALID_INDEX opt_label_1 LPAR lexpr COMMA lexpr RPAR {
-  let source = fst (loc ()) in
+  let source = pos $symbolstartpos in
   obsolete ~source "\\valid_index(addr,idx)" ~now:"\\valid(addr+idx)";
-  info (PLvalid ($2,info (PLbinop ($4, Badd, $6)))) }
+  info $sloc (PLvalid ($2,info $sloc (PLbinop ($4, Badd, $6)))) }
 | VALID_RANGE opt_label_1 LPAR lexpr COMMA lexpr COMMA lexpr RPAR {
-  let source = fst (loc ()) in
+  let source = pos $symbolstartpos in
   obsolete "\\valid_range(addr,min,max)"
     ~source ~now:"\\valid(addr+(min..max))";
-  info (PLvalid
-          ($2,info (PLbinop ($4, Badd, (info (PLrange((Some $6),Some $8)))))))
+  info $sloc (PLvalid
+          ($2,info $sloc (PLbinop ($4, Badd, (info $sloc (PLrange((Some $6),Some $8)))))))
 }
-| INITIALIZED opt_label_1 LPAR lexpr RPAR { info (PLinitialized ($2,$4)) }
-| DANGLING opt_label_1 LPAR lexpr RPAR { info (PLdangling ($2,$4)) }
-| FRESH opt_label_2 LPAR lexpr COMMA lexpr RPAR { info (PLfresh ($2,$4, $6)) }
-| BASE_ADDR opt_label_1 LPAR lexpr RPAR { info (PLbase_addr ($2,$4)) }
-| BLOCK_LENGTH opt_label_1 LPAR lexpr RPAR { info (PLblock_length ($2,$4)) }
-| OFFSET opt_label_1 LPAR lexpr RPAR { info (PLoffset ($2,$4)) }
-| ALLOCABLE opt_label_1 LPAR lexpr RPAR { info (PLallocable ($2,$4)) }
-| FREEABLE opt_label_1 LPAR lexpr RPAR { info (PLfreeable ($2,$4)) }
+| INITIALIZED opt_label_1 LPAR lexpr RPAR { info $sloc (PLinitialized ($2,$4)) }
+| DANGLING opt_label_1 LPAR lexpr RPAR { info $sloc (PLdangling ($2,$4)) }
+| FRESH opt_label_2 LPAR lexpr COMMA lexpr RPAR { info $sloc (PLfresh ($2,$4, $6)) }
+| BASE_ADDR opt_label_1 LPAR lexpr RPAR { info $sloc (PLbase_addr ($2,$4)) }
+| BLOCK_LENGTH opt_label_1 LPAR lexpr RPAR { info $sloc (PLblock_length ($2,$4)) }
+| OFFSET opt_label_1 LPAR lexpr RPAR { info $sloc (PLoffset ($2,$4)) }
+| ALLOCABLE opt_label_1 LPAR lexpr RPAR { info $sloc (PLallocable ($2,$4)) }
+| FREEABLE opt_label_1 LPAR lexpr RPAR { info $sloc (PLfreeable ($2,$4)) }
 | ALLOCATION opt_label_1 LPAR lexpr RPAR
-  { let source = fst(loc()) in
+  { let source = pos $symbolstartpos in
     Kernel.not_yet_implemented ~source "\\allocation" }
 | AUTOMATIC {
-  let source = fst(loc()) in
+  let source = pos $symbolstartpos in
   Kernel.not_yet_implemented ~source "\\automatic" }
 | DYNAMIC {
-  let source = fst(loc()) in
+  let source = pos $symbolstartpos in
   Kernel.not_yet_implemented ~source "\\dynamic" }
 | REGISTER {
-  let source = fst(loc()) in
+  let source = pos $symbolstartpos in
   Kernel.not_yet_implemented ~source "\\register" }
 | STATIC {
-  let source = fst(loc()) in
+  let source = pos $symbolstartpos in
   Kernel.not_yet_implemented ~source "\\static" }
 | UNALLOCATED {
-  let source = fst(loc()) in
+  let source = pos $symbolstartpos in
   Kernel.not_yet_implemented ~source "\\unallocated" }
-| NULL { info PLnull }
-| constant { info (PLconstant $1) }
-| lexpr_inner PLUS lexpr_inner { info (PLbinop ($1, Badd, $3)) }
-| lexpr_inner MINUS lexpr_inner { info (PLbinop ($1, Bsub, $3)) }
-| lexpr_inner STAR lexpr_inner { info (PLbinop ($1, Bmul, $3)) }
-| lexpr_inner SLASH lexpr_inner { info (PLbinop ($1, Bdiv, $3)) }
-| lexpr_inner PERCENT lexpr_inner { info (PLbinop ($1, Bmod, $3)) }
-| lexpr_inner STARHAT lexpr_inner  { info (PLrepeat ($1, $3)) }
-| lexpr_inner ARROW identifier_or_typename { info (PLarrow ($1, $3)) }
-| lexpr_inner DOT identifier_or_typename { info (PLdot ($1, $3)) }
-| lexpr_inner LSQUARE range RSQUARE { info (PLarrget ($1, $3)) }
-| lexpr_inner LSQUARE lexpr RSQUARE { info (PLarrget ($1, $3)) }
-| LSQUAREPIPE lexpr_list RSQUAREPIPE {info (PLlist $2) }
-| MINUS lexpr_inner %prec prec_unary_op { info (PLunop (Uminus, $2)) }
+| NULL { info $sloc PLnull }
+| constant { info $sloc (PLconstant $1) }
+| lexpr_inner PLUS lexpr_inner { info $sloc (PLbinop ($1, Badd, $3)) }
+| lexpr_inner MINUS lexpr_inner { info $sloc (PLbinop ($1, Bsub, $3)) }
+| lexpr_inner STAR lexpr_inner { info $sloc (PLbinop ($1, Bmul, $3)) }
+| lexpr_inner SLASH lexpr_inner { info $sloc (PLbinop ($1, Bdiv, $3)) }
+| lexpr_inner PERCENT lexpr_inner { info $sloc (PLbinop ($1, Bmod, $3)) }
+| lexpr_inner STARHAT lexpr_inner  { info $sloc (PLrepeat ($1, $3)) }
+| lexpr_inner ARROW identifier_or_typename { info $sloc (PLarrow ($1, $3)) }
+| lexpr_inner DOT identifier_or_typename { info $sloc (PLdot ($1, $3)) }
+| lexpr_inner LSQUARE range RSQUARE { info $sloc (PLarrget ($1, $3)) }
+| lexpr_inner LSQUARE lexpr RSQUARE { info $sloc (PLarrget ($1, $3)) }
+| LSQUAREPIPE lexpr_list RSQUAREPIPE { info $sloc (PLlist $2) }
+| MINUS lexpr_inner %prec prec_unary_op { info $sloc (PLunop (Uminus, $2)) }
 | PLUS  lexpr_inner %prec prec_unary_op { $2 }
-| TILDE lexpr_inner { info (PLunop (Ubw_not, $2)) }
-| STAR  lexpr_inner %prec prec_unary_op { info (PLunop (Ustar, $2)) }
-| AMP   lexpr_inner %prec prec_unary_op { info (PLunop (Uamp, $2)) }
-| SIZEOF LPAR lexpr RPAR { info (PLsizeofE $3) }
-| SIZEOF LPAR cast_logic_type RPAR { info (PLsizeof $3) }
-| OLD LPAR lexpr RPAR { info (PLold $3) }
-| AT LPAR lexpr COMMA label_name RPAR { info (PLat ($3, $5)) }
-| RESULT { info PLresult }
+| TILDE lexpr_inner { info $sloc (PLunop (Ubw_not, $2)) }
+| STAR  lexpr_inner %prec prec_unary_op { info $sloc (PLunop (Ustar, $2)) }
+| AMP   lexpr_inner %prec prec_unary_op { info $sloc (PLunop (Uamp, $2)) }
+| SIZEOF LPAR lexpr RPAR { info $sloc (PLsizeofE $3) }
+| SIZEOF LPAR cast_logic_type RPAR { info $sloc (PLsizeof $3) }
+| OLD LPAR lexpr RPAR { info $sloc (PLold $3) }
+| AT LPAR lexpr COMMA label_name RPAR { info $sloc (PLat ($3, $5)) }
+| RESULT { info $sloc PLresult }
 | SEPARATED LPAR ne_lexpr_list RPAR
-      { info (PLseparated $3) }
+      { info $sloc (PLseparated $3) }
 | identifier LPAR ne_lexpr_list RPAR
-      { info (PLapp ($1, [], $3)) }
+      { info $sloc (PLapp ($1, [], $3)) }
 | identifier LBRACE ne_label_args RBRACE LPAR ne_lexpr_list RPAR
-      { info (PLapp ($1, $3, $6)) }
+      { info $sloc (PLapp ($1, $3, $6)) }
 | identifier LBRACE ne_label_args RBRACE
-      { info (PLapp ($1, $3, [])) }
-| identifier  { info (PLvar $1) }
-| PI  { info (PLvar "\\pi") }
-| lexpr_inner GTGT lexpr_inner { info (PLbinop ($1, Brshift, $3))}
-| lexpr_inner LTLT lexpr_inner { info (PLbinop ($1, Blshift, $3))}
-| LPAR lexpr RPAR { info $2.lexpr_node }
-| LPAR range RPAR { info $2.lexpr_node }
+      { info $sloc (PLapp ($1, $3, [])) }
+| identifier  { info $sloc (PLvar $1) }
+| PI  { info $sloc (PLvar "\\pi") }
+| lexpr_inner GTGT lexpr_inner { info $sloc (PLbinop ($1, Brshift, $3))}
+| lexpr_inner LTLT lexpr_inner { info $sloc (PLbinop ($1, Blshift, $3))}
+| LPAR lexpr RPAR { info $sloc $2.lexpr_node }
+| LPAR range RPAR { info $sloc $2.lexpr_node }
 | LPAR cast_logic_type RPAR lexpr_inner %prec prec_cast
-      { info (PLcast ($2, $4)) }
-| TYPEOF LPAR lexpr RPAR { info (PLtypeof $3) }
-| BSTYPE LPAR type_spec RPAR { info (PLtype $3) }
-| BSTYPE LPAR type_spec stars RPAR { info (PLtype ($4 $3)) }
+      { info $sloc (PLcast ($2, $4)) }
+| TYPEOF LPAR lexpr RPAR { info $sloc (PLtypeof $3) }
+| BSTYPE LPAR type_spec RPAR { info $sloc (PLtype $3) }
+| BSTYPE LPAR type_spec stars RPAR { info $sloc (PLtype ($4 $3)) }
     /* tsets */
-| EMPTY { info PLempty }
-| BSUNION LPAR lexpr_list RPAR { info (PLunion $3) }
-| INTER LPAR lexpr_list RPAR { info (PLinter $3) }
+| EMPTY { info $sloc PLempty }
+| BSUNION LPAR lexpr_list RPAR { info $sloc (PLunion $3) }
+| INTER LPAR lexpr_list RPAR { info $sloc (PLinter $3) }
 | LBRACE lexpr_list RBRACE
-      { info (PLset ($2)) }
+      { info $sloc (PLset ($2)) }
 | LBRACE lexpr PIPE binders RBRACE
-      {info (PLcomprehension ($2,$4,None)) }
+      { info $sloc (PLcomprehension ($2,$4,None)) }
 | LBRACE lexpr PIPE binders SEMICOLON lexpr RBRACE
-      { info (PLcomprehension ($2,$4,Some $6)) }
+      { info $sloc (PLcomprehension ($2,$4,Some $6)) }
     /* Aggregated object initialization */
 | LBRACE field_init RBRACE
-      { info (PLinitField($2)) }
+      { info $sloc (PLinitField($2)) }
 | LBRACE array_init RBRACE
-      { info (PLinitIndex($2)) }
+      { info $sloc (PLinitIndex($2)) }
 | LBRACE lexpr WITH update RBRACE
       { List.fold_left
-	  (fun a (path,upd_val) -> info (PLupdate(a,path,upd_val))) $2 $4 }
+	  (fun a (path,upd_val) -> info $sloc (PLupdate(a,path,upd_val))) $2 $4 }
 /*
-| LET bounded_var EQUAL lexpr SEMICOLON lexpr %prec LET {info (PLlet($2,$4,$6))}*/
+| LET bounded_var EQUAL lexpr SEMICOLON lexpr %prec LET { info $sloc (PLlet($2,$4,$6))}*/
 ;
 
 ne_label_args:
@@ -609,7 +614,7 @@ string:
 ;
 
 range:
-| lexpr_option DOTDOT lexpr_option { info (PLrange($1,$3)) }
+| lexpr_option DOTDOT lexpr_option { info $sloc (PLrange($1,$3)) }
 ;
 
 /*** Aggregated object initialization ***/
@@ -723,7 +728,7 @@ abs_param_type_list:
 | /* empty */    { [ ] }
 | abs_param_list { $1 }
 | abs_param_list COMMA DOTDOTDOT {
-  let source = fst(loc()) in
+  let source = pos $symbolstartpos in
   Kernel.not_yet_implemented ~source "variadic C function types"
   }
 ;
@@ -942,6 +947,7 @@ full_logic_type:
 
 full_logic_rt_type:
 | enter_kw_c_mode logic_rt_type exit_kw_c_mode { $2 }
+;
 
 full_assigns:
 | enter_kw_c_mode assigns exit_kw_c_mode { $2 }
@@ -964,10 +970,10 @@ ext_global_clauses:
 ;
 
 ext_global_clause:
-| decl  { Ext_decl (loc_decl $1) }
+| decl  { Ext_decl (loc_decl $sloc $1) }
 | EXT_LET any_identifier EQUAL full_lexpr SEMICOLON { Ext_macro (false, $2, $4) }
 | GLOBAL EXT_LET any_identifier EQUAL full_lexpr SEMICOLON { Ext_macro (true, $3, $5) }
-| INCLUDE string SEMICOLON { let b,s = $2 in Ext_include(b,s, loc()) }
+| INCLUDE string SEMICOLON { let b,s = $2 in Ext_include(b,s, loc $sloc) }
 ;
 
 ext_global_specs_opt:
@@ -1026,7 +1032,7 @@ ext_fun_specs:
 
 ext_fun_spec:
 | ext_at_stmt_markup ext_stmt_loop_spec
-    { Ext_stmt($1,$2,loc()) }
+    { Ext_stmt($1,$2,loc $sloc) }
 | ext_contract_markup contract
     { let s,pos = $2 in Ext_spec (s,pos) }
 ;
@@ -1050,7 +1056,7 @@ ext_module_markup:
 ;
 
 ext_function_markup:
-| FUNCTION ext_identifier COLON { $2, loc() }
+| FUNCTION ext_identifier COLON { $2, loc $sloc }
 ;
 
 ext_contract_markup:
@@ -1094,54 +1100,54 @@ contract:
         else if $2<>None || $3<>None ||
                 behaviors<>[] || completes<>[] ||disjoints<>[]
         then behaviors
-        else raise (Not_well_formed (loc(),"Empty annotation is not allowed"))
+        else raise (Not_well_formed (loc $sloc,"Empty annotation is not allowed"))
       in
         { spec_terminates = $2;
           spec_variant = $3;
           spec_behavior = behaviors;
           spec_complete_behaviors = completes;
           spec_disjoint_behaviors = disjoints;
-        }, loc()
+        }, loc $sloc
     }
-| requires ne_terminates REQUIRES { clause_order 3 "requires" "terminates" }
+| requires ne_terminates REQUIRES { clause_order $loc($3) "requires" "terminates" }
 | requires terminates ne_decreases REQUIRES
-      { clause_order 4 "requires" "decreases" }
+      { clause_order $loc($4) "requires" "decreases" }
 | requires terminates ne_decreases TERMINATES
-      { clause_order 4 "terminates" "decreases" }
+      { clause_order $loc($4) "terminates" "decreases" }
 | requires terminates decreases ne_simple_clauses REQUIRES
-      { clause_order 5 "requires" "post-condition, assigns or allocates" }
+      { clause_order $loc($5) "requires" "post-condition, assigns or allocates" }
 | requires terminates decreases ne_simple_clauses TERMINATES
-      { clause_order 5 "terminates" "post-condition, assigns or allocates" }
+      { clause_order $loc($5) "terminates" "post-condition, assigns or allocates" }
 | requires terminates decreases ne_simple_clauses DECREASES
-      { clause_order 5 "decreases" "post-condition, assigns or allocates" }
+      { clause_order $loc($5) "decreases" "post-condition, assigns or allocates" }
 | requires terminates decreases simple_clauses ne_behaviors TERMINATES
-      { clause_order 6 "terminates" "behavior" }
+      { clause_order $loc($6) "terminates" "behavior" }
 | requires terminates decreases simple_clauses ne_behaviors DECREASES
-      { clause_order 6 "decreases" "behavior" }
+      { clause_order $loc($6) "decreases" "behavior" }
 | requires terminates decreases simple_clauses behaviors ne_complete_or_disjoint
   REQUIRES
-      { clause_order 7 "requires" "complete or disjoint" }
+      { clause_order $loc($7) "requires" "complete or disjoint" }
 | requires terminates decreases simple_clauses behaviors ne_complete_or_disjoint
   TERMINATES
-      { clause_order 7 "terminates" "complete or disjoint" }
+      { clause_order $loc($7) "terminates" "complete or disjoint" }
 | requires terminates decreases simple_clauses behaviors ne_complete_or_disjoint
   DECREASES
-      { clause_order 7 "decreases" "complete or disjoint" }
+      { clause_order $loc($7) "decreases" "complete or disjoint" }
 | requires terminates decreases simple_clauses behaviors ne_complete_or_disjoint
   BEHAVIOR
-      { clause_order 7 "behavior" "complete or disjoint" }
+      { clause_order $loc($7) "behavior" "complete or disjoint" }
 | requires terminates decreases simple_clauses behaviors ne_complete_or_disjoint
   ASSIGNS
-      { clause_order 7 "assigns" "complete or disjoint" }
+      { clause_order $loc($7) "assigns" "complete or disjoint" }
 | requires terminates decreases simple_clauses behaviors ne_complete_or_disjoint
   ALLOCATES
-      { clause_order 7 "allocates" "complete or disjoint" }
+      { clause_order $loc($7) "allocates" "complete or disjoint" }
 | requires terminates decreases simple_clauses behaviors ne_complete_or_disjoint
   FREES
-      { clause_order 7 "frees" "complete or disjoint" }
+      { clause_order $loc($7) "frees" "complete or disjoint" }
 | requires terminates decreases simple_clauses behaviors ne_complete_or_disjoint
   post_cond_kind
-      { clause_order 7 "post-condition" "complete or disjoint" }
+      { clause_order $loc($7) "post-condition" "complete or disjoint" }
 ;
 
 // use that to detect potentially missing ';' at end of clause
@@ -1180,19 +1186,19 @@ ne_requires:
 | REQUIRES full_lexpr SEMICOLON requires { toplevel_pred Assert $2::$4 }
 | CHECK_REQUIRES full_lexpr SEMICOLON requires { toplevel_pred Check $2 :: $4 }
 | ADMIT_REQUIRES full_lexpr SEMICOLON requires { toplevel_pred Admit $2 :: $4 }
-| REQUIRES full_lexpr clause_kw { missing 2 ";" $3 }
-| CHECK_REQUIRES full_lexpr clause_kw { missing 2 ";" $3 }
-| ADMIT_REQUIRES full_lexpr clause_kw { missing 2 ";" $3 }
+| REQUIRES full_lexpr clause_kw { missing $loc($2) ";" $3 }
+| CHECK_REQUIRES full_lexpr clause_kw { missing $loc($2) ";" $3 }
+| ADMIT_REQUIRES full_lexpr clause_kw { missing $loc($2) ";" $3 }
 ;
 
 terminates:
-| /* epsilon */              { None }
+| /* epsilon */ { None }
 | ne_terminates { Some $1 }
 ;
 
 ne_terminates:
 | TERMINATES full_lexpr SEMICOLON { $2 }
-| TERMINATES full_lexpr clause_kw { missing 2 ";" $3 }
+| TERMINATES full_lexpr clause_kw { missing $loc($2) ";" $3 }
 ;
 
 decreases:
@@ -1202,7 +1208,7 @@ decreases:
 
 ne_decreases:
 | DECREASES variant SEMICOLON { $2 }
-| DECREASES variant clause_kw { missing 2 ";" $3 }
+| DECREASES variant clause_kw { missing $loc($2) ";" $3 }
 ;
 
 variant:
@@ -1232,7 +1238,7 @@ ne_simple_clauses:
     }
 | ASSIGNS full_assigns SEMICOLON simple_clauses
     { let allocation,assigns,post_cond,extended = $4 in
-      let a = concat_assigns assigns $2
+      let a = concat_assigns $sloc assigns $2
       in allocation,a,post_cond,extended
     }
 | EXT_CONTRACT grammar_extension SEMICOLON simple_clauses
@@ -1240,10 +1246,10 @@ ne_simple_clauses:
       let processed = Logic_env.preprocess_extension $1 $2 in
       allocation,assigns,post_cond,($1,processed)::extended
     }
-| post_cond_kind full_lexpr clause_kw { missing 2 ";" $3 }
-| allocation clause_kw { missing 1 ";" $2 }
-| ASSIGNS full_assigns clause_kw { missing 2 ";" $3 }
-| EXT_CONTRACT ne_grammar_extension clause_kw { missing 1 ";" $3 }
+| post_cond_kind full_lexpr clause_kw { missing $loc($2) ";" $3 }
+| allocation clause_kw { missing $loc($1) ";" $2 }
+| ASSIGNS full_assigns clause_kw { missing $loc($2) ";" $3 }
+| EXT_CONTRACT ne_grammar_extension clause_kw { missing $loc($1) ";" $3 }
 ;
 
 ne_grammar_extension:
@@ -1278,21 +1284,22 @@ ne_behaviors:
             ~assumes ~requires ~post_cond ~assigns ~allocation ~extended ()
         in b::behaviors
       }
+;
 
 behavior_body:
 | assumes requires simple_clauses { $1,$2,$3 }
 | assumes ne_requires ASSUMES
-      { clause_order 3 "assumes" "requires" }
+      { clause_order $loc($3) "assumes" "requires" }
 | assumes requires ne_simple_clauses ASSUMES
-      { clause_order 4 "assumes" "assigns or post-condition" }
+      { clause_order $loc($4) "assumes" "assigns or post-condition" }
 | assumes requires ne_simple_clauses REQUIRES
-      { clause_order 4 "requires" "assigns or post-condition" }
+      { clause_order $loc($4) "requires" "assigns or post-condition" }
 ;
 
 assumes:
 | /* epsilon */ { [] }
 | ASSUMES full_lexpr SEMICOLON assumes { $2::$4 }
-| ASSUMES full_lexpr clause_kw { missing 2 ";" $3 }
+| ASSUMES full_lexpr clause_kw { missing $loc($2) ";" $3 }
 ;
 
 complete_or_disjoint:
@@ -1309,8 +1316,8 @@ ne_complete_or_disjoint:
 /* complete behaviors decreases; is valid (provided there's a behavior
    named decreases)
 */
-| COMPLETE BEHAVIORS ne_behavior_name_list clause_kw { missing 3 ";" $4 }
-| DISJOINT BEHAVIORS ne_behavior_name_list clause_kw { missing 3 ";" $4 }
+| COMPLETE BEHAVIORS ne_behavior_name_list clause_kw { missing $loc($3) ";" $4 }
+| DISJOINT BEHAVIORS ne_behavior_name_list clause_kw { missing $loc($3) ";" $4 }
 ;
 
 /*** assigns and tsets ***/
@@ -1342,23 +1349,23 @@ annotation:
       { let (b,v,p) = $1 in
         (* TODO: do better, do not lose the structure ! *)
         let l = b@v@p in
-        Aloop_annot (loc (), l) }
+        Aloop_annot (loc $sloc, l) }
 | FOR ne_behavior_name_list COLON contract_or_code_annotation
       { $4 $2 }
-| pragma_or_code_annotation { Acode_annot (loc(),$1) }
+| pragma_or_code_annotation { Acode_annot (loc $sloc,$1) }
 | pragma_or_code_annotation beg_pragma_or_code_annotation
       { raise
-          (Not_well_formed (loc(),
+          (Not_well_formed (loc $sloc,
                             "Only one code annotation is allowed per comment"))
       }
-| full_identifier_or_typename { Aattribute_annot (loc (), $1) }
+| full_identifier_or_typename { Aattribute_annot (loc $sloc, $1) }
 | BSGHOST { Aattribute_annot(loc(),"\\ghost") }
 ;
 
 contract_or_code_annotation:
 | contract
       { fun bhvs -> let s, pos = $1 in Acode_annot (pos, AStmtSpec (bhvs,s)) }
-| code_annotation { fun bhvs -> Acode_annot (loc(), ($1 bhvs)) }
+| code_annotation { fun bhvs -> Acode_annot (loc $sloc, ($1 bhvs)) }
 ;
 
 /*** loop annotations ***/
@@ -1388,7 +1395,7 @@ loop_annot_stack:
 | loop_invariant loop_annot_opt
     { let (i,fa,a,b,v,p,e) = $2 in ($1::i,fa,a,b,v,p,e) }
 | loop_effects loop_annot_opt
-    { let (i,fa,a,b,v,p,e) = $2 in (i,fa,concat_assigns a $1,b,v,p,e) }
+    { let (i,fa,a,b,v,p,e) = $2 in (i,fa,concat_assigns $sloc a $1,b,v,p,e) }
 | loop_allocation loop_annot_opt
     { let (i,fa,a,b,v,p,e) = $2 in (i,concat_allocation fa $1,a,b,v,p,e) }
 | FOR ne_behavior_name_list COLON loop_annot_stack
@@ -1396,7 +1403,7 @@ loop_annot_stack:
       let behav = $2 in
       let invs = List.map (fun i -> AInvariant(behav,true,i)) i in
       let ext = List.map (fun x -> AExtended(behav,true,x)) e in
-      let oth = concat_loop_assigns_allocation b behav a fa in
+      let oth = concat_loop_assigns_allocation $sloc b behav a fa in
       ([],FreeAllocAny,WritesAny,invs@ext@oth,v,p,[])
     }
 | loop_variant loop_annot_opt
@@ -1454,7 +1461,7 @@ loop_invariant:
 ;
 
 loop_variant:
-| LOOP VARIANT variant SEMICOLON { loc(),$3 }
+| LOOP VARIANT variant SEMICOLON { loc $sloc,$3 }
 ;
 
 /* Grammar Extensibility for plugins */
@@ -1470,11 +1477,11 @@ loop_grammar_extension:
       | Ext_code_annot (Ext_here | Ext_next_stmt) ->
         raise
           (Not_well_formed
-            (lexeme_loc 2, ext ^ " is not a loop annotation extension"))
+            (loc $loc($2), ext ^ " is not a loop annotation extension"))
       | _ -> raise Not_found
     end
   with Not_found ->
-    Kernel.fatal ~source:(lexeme_start 2)
+    Kernel.fatal ~source:(pos $startpos($2))
       "%s is not a code annotation extension. Parser got wrong lexeme." ext
 }
 ;
@@ -1489,7 +1496,7 @@ loop_pragma:
       Widen_variables $4
     else if $3 = "WIDEN_HINTS" then
       Widen_hints $4
-    else raise (Not_well_formed (loc(),"Unknown loop pragma")) }
+    else raise (Not_well_formed (loc $sloc,"Unknown loop pragma")) }
 ;
 
 /*** code annotations ***/
@@ -1540,13 +1547,13 @@ code_annotation:
         | Ext_code_annot Ext_next_loop ->
           raise
             (Not_well_formed
-               (lexeme_loc 1,
+               (loc $loc($1),
                  ext ^ " is not a loop annotation extension. It can't be used \
                          as plain code annotation extension"))
         | _ -> raise Not_found
       end
     with Not_found ->
-      Kernel.fatal ~source:(lexeme_start 1)
+      Kernel.fatal ~source:(pos $startpos($1))
         "%s is not a code annotation extension. Parser got wrong lexeme" ext
   }
 ;
@@ -1554,27 +1561,28 @@ code_annotation:
 slice_pragma:
 | SLICE PRAGMA any_identifier full_lexpr SEMICOLON
     { if $3 = "expr" then SPexpr $4
-      else raise (Not_well_formed (loc(), "Unknown slice pragma")) }
+      else raise (Not_well_formed (loc $sloc, "Unknown slice pragma")) }
 | SLICE PRAGMA any_identifier SEMICOLON
     { if $3 = "ctrl" then SPctrl
       else if $3 = "stmt" then SPstmt
-      else raise (Not_well_formed (loc(), "Unknown slice pragma")) }
+      else raise (Not_well_formed (loc $sloc, "Unknown slice pragma")) }
 ;
 
 impact_pragma:
 | IMPACT PRAGMA any_identifier full_lexpr SEMICOLON
     { if $3 = "expr" then IPexpr $4
-      else raise (Not_well_formed (loc(), "Unknown impact pragma")) }
+      else raise (Not_well_formed (loc $sloc, "Unknown impact pragma")) }
 | IMPACT PRAGMA any_identifier SEMICOLON
     { if $3 = "stmt" then IPstmt
-      else raise (Not_well_formed (loc(), "Unknown impact pragma")) }
+      else raise (Not_well_formed (loc $sloc, "Unknown impact pragma")) }
 ;
 
 /*** declarations and logical definitions ***/
 
 decl_list:
-| decl            { [loc_decl $1] }
-| decl decl_list  { (loc_decl $1) :: $2 }
+| decl            { [loc_decl $sloc $1] }
+| decl decl_list  { (loc_decl $loc($1) $1) :: $2 }
+;
 
 decl:
 | GLOBAL INVARIANT any_identifier COLON full_lexpr SEMICOLON
@@ -1608,7 +1616,7 @@ ext_decls:
 ;
 
 ext_decl_loc:
-| ext_decl { loc_ext $1 }
+| ext_decl { loc_ext $sloc $1 }
 ;
 
 volatile_opt:
@@ -1638,6 +1646,7 @@ type_annot:
 opt_semicolon:
 | /* epsilon */ { }
 | SEMICOLON { }
+;
 
 model_annot:
 | MODEL type_spec LBRACE full_parameter opt_semicolon RBRACE SEMICOLON
@@ -1718,7 +1727,7 @@ deprecated_logic_decl:
 /* OBSOLETE: logic function declaration */
 | LOGIC full_logic_rt_type poly_id opt_parameters SEMICOLON
     { let (id, labels, tvars) = $3 in
-      let source = fst (loc ()) in
+      let source = pos $symbolstartpos in
       exit_type_variables_scope ();
       obsolete  "logic declaration" ~source ~now:"an axiomatic block";
       LDlogic_reads (id, labels, tvars, $2, $4, None) }
@@ -1726,7 +1735,7 @@ deprecated_logic_decl:
 | PREDICATE poly_id opt_parameters SEMICOLON
     { let (id,labels,tvars) = $2 in
       exit_type_variables_scope ();
-      let source = fst (loc ()) in
+      let source = pos $symbolstartpos in
       obsolete "logic declaration" ~source ~now:"an axiomatic block";
       LDpredicate_reads (id, labels, tvars, $3, None) }
 /* OBSOLETE: type declaration */
@@ -1734,7 +1743,7 @@ deprecated_logic_decl:
     { let (id,tvars) = $2 in
       Logic_env.add_typename id;
       exit_type_variables_scope ();
-      let source = fst (loc ()) in
+      let source = pos $symbolstartpos in
       obsolete "logic type declaration" ~source ~now:"an axiomatic block";
       LDtype(id,tvars,None)
     }
@@ -1743,7 +1752,7 @@ deprecated_logic_decl:
     { let (id,_,_) = $2 in
       raise
 	(Not_well_formed
-	   (loc(),"Axiom " ^ id ^ " is declared outside of an axiomatic."))
+	   (loc $sloc,"Axiom " ^ id ^ " is declared outside of an axiomatic."))
     }
 ;
 
@@ -1781,7 +1790,7 @@ logic_decl:
 ;
 
 logic_decl_loc:
-| logic_decl { loc_decl $1 }
+| logic_decl { loc_decl $sloc $1 }
 ;
 
 
@@ -1838,15 +1847,15 @@ opt_label_1:
 | opt_label_list { match $1 with
 		     | [] -> None
 		     | l::[] -> Some l
-		     | _ -> raise (Not_well_formed (loc(),"Only one label is allowed")) }
+		     | _ -> raise (Not_well_formed (loc $sloc,"Only one label is allowed")) }
 ;
 
 opt_label_2:
 | opt_label_list { match $1 with
 		     | [] -> None
 		     | l1::l2::[] -> Some (l1,l2)
-		     | _::[] -> raise (Not_well_formed (loc(),"One label is missing"))
-		     | _ -> raise (Not_well_formed (loc(),"Only two labels are allowed")) }
+		     | _::[] -> raise (Not_well_formed (loc $sloc,"One label is missing"))
+		     | _ -> raise (Not_well_formed (loc $sloc,"Only two labels are allowed")) }
 ;
 
 opt_label_list:
@@ -1902,12 +1911,12 @@ bounded_var:
 | identifier { $1 }
 | is_acsl_typename /* Since TYPENAME cannot be accepted by lexpr rule */
     { raise
-	(Not_well_formed(loc (),
+	(Not_well_formed(loc $sloc,
 			 "Type names are not allowed as binding variable"))
     }
 | TYPENAME  /* Since TYPENAME cannot be accepted by lexpr rule */
     { raise
-	(Not_well_formed(loc (),
+	(Not_well_formed(loc $sloc,
 			 "Type names are not allowed as binding variable"))
     }
 ;
-- 
GitLab