From 2360db37268c51fd7043ed899814d351d2aa203a Mon Sep 17 00:00:00 2001
From: Virgile Prevosto <virgile.prevosto@m4x.org>
Date: Wed, 15 Jan 2020 10:39:07 +0100
Subject: [PATCH] [lexer] make logic_lexer aware of __FC_FILENAME__

---
 src/kernel_internals/parsing/logic_lexer.mll | 159 +++++++++++--------
 tests/syntax/fc_filename.c                   |   2 +
 tests/syntax/oracle/fc_filename.res.oracle   |   5 +
 3 files changed, 98 insertions(+), 68 deletions(-)

diff --git a/src/kernel_internals/parsing/logic_lexer.mll b/src/kernel_internals/parsing/logic_lexer.mll
index e122cd7f80c..07071b3e13a 100644
--- a/src/kernel_internals/parsing/logic_lexer.mll
+++ b/src/kernel_internals/parsing/logic_lexer.mll
@@ -81,77 +81,95 @@
          if flag then Hashtbl.add c_kw i t
       )
       [
-        "allocates", ALLOCATES, false;
-        "assert", ASSERT, false;
-        "assigns", ASSIGNS, false;
-        "assumes", ASSUMES, false;
-        "at", EXT_AT, false;(* ACSL extension for external spec file *)
-        "axiom", AXIOM, false;
-        "axiomatic", AXIOMATIC, false;
-        "behavior", BEHAVIOR, false;
-        "behaviors", BEHAVIORS, false;
-        "_Bool", BOOL, true;
-        "breaks", BREAKS, false;
-	"case", CASE, true;
-        "char", CHAR, true;
-        "check", CHECK, false;
-        "complete", COMPLETE, false;
-        "const", CONST, true;
-        "continues", CONTINUES, false;
-        "contract", CONTRACT, false;(* ACSL extension for external spec file *)
-	"custom", CUSTOM, false; (* ACSL extension for custom annotations *)
-        "decreases", DECREASES, false;
-        "disjoint", DISJOINT, false;
-        "double", DOUBLE, true;
-        "else", ELSE, true;
-        "ensures", ENSURES, false ;
-        "enum", ENUM, true;
-        "exits", EXITS, false;
-        "frees", FREES, false;
-        "function", FUNCTION, false;(* ACSL extension for external spec file *)
-        "float", FLOAT, true;
-        "for", FOR, true;
-        "global",    GLOBAL, false;
-        "if", IF, true;
-	"impact", IMPACT, false;
-	"inductive", INDUCTIVE, false;
-	"include", INCLUDE, false;(* ACSL extension for external spec file *)
-        "int", INT, true;
-        "invariant", INVARIANT, false;
-        "label", LABEL, false;
-        "lemma", LEMMA, false;
-        "let", EXT_LET, false;(* ACSL extension for external spec file *)
-        "logic", LOGIC, false;
-        "long", LONG, true;
-        "loop", LOOP, false;
-        "model", MODEL, false;(* ACSL extension for model fields *)
-        "module", MODULE, false;(* ACSL extension for external spec file *)
-        "pragma", PRAGMA, false;
-        "predicate", PREDICATE, false;
-        "reads", READS, true; (* treated specifically in the parser to
-                                 avoid issue in volatile clause. *)
-        "requires", REQUIRES, false;
-        "returns", RETURNS, false;
-        "short", SHORT, true;
-        "signed", SIGNED, true;
-        "sizeof", SIZEOF, true;
-        "slice", SLICE, false;
-        "struct", STRUCT, true;
-        "terminates", TERMINATES, false;
-        "type", TYPE, false;
-        "union", UNION, true;
-        "unsigned", UNSIGNED, true;
-        "variant", VARIANT, false;
-        "void", VOID, true;
-        "volatile", VOLATILE, true;
-        "writes", WRITES, true; (* treated specifically in the parser to
-                                   avoid issue in volatile clause. *)
+        "allocates", (fun _ -> ALLOCATES), false;
+        "assert", (fun _ -> ASSERT), false;
+        "assigns", (fun _ -> ASSIGNS), false;
+        "assumes", (fun _ -> ASSUMES), false;
+        "at", (fun _ -> EXT_AT), false;
+        (* ACSL extension for external spec file *)
+        "axiom", (fun _ -> AXIOM), false;
+        "axiomatic", (fun _ -> AXIOMATIC), false;
+        "behavior", (fun _ -> BEHAVIOR), false;
+        "behaviors", (fun _ -> BEHAVIORS), false;
+        "_Bool", (fun _ -> BOOL), true;
+        "breaks", (fun _ -> BREAKS), false;
+        "case", (fun _ -> CASE), true;
+        "char", (fun _ -> CHAR), true;
+        "check", (fun _ -> CHECK), false;
+        "complete", (fun _ -> COMPLETE), false;
+        "const", (fun _ -> CONST), true;
+        "continues", (fun _ -> CONTINUES), false;
+        "contract", (fun _ -> CONTRACT), false;
+        (* ACSL extension for external spec file *)
+        "custom", (fun _ -> CUSTOM), false;
+        (* ACSL extension for custom annotations *)
+        "decreases", (fun _ -> DECREASES), false;
+        "disjoint", (fun _ -> DISJOINT), false;
+        "double", (fun _ -> DOUBLE), true;
+        "else", (fun _ -> ELSE), true;
+        "ensures", (fun _ -> ENSURES), false ;
+        "enum", (fun _ -> ENUM), true;
+        "exits", (fun _ -> EXITS), false;
+        "frees", (fun _ -> FREES), false;
+        "function", (fun _ -> FUNCTION), false;
+        (* ACSL extension for external spec file *)
+        "float", (fun _ -> FLOAT), true;
+        "for", (fun _ -> FOR), true;
+        "global", (fun _ -> GLOBAL), false;
+        "if", (fun _ -> IF), true;
+	"impact", (fun _ -> IMPACT), false;
+	"inductive", (fun _ -> INDUCTIVE), false;
+	"include", (fun _ -> INCLUDE), false;
+        (* ACSL extension for external spec file *)
+        "int", (fun _ -> INT), true;
+        "invariant", (fun _ -> INVARIANT), false;
+        "label", (fun _ -> LABEL), false;
+        "lemma", (fun _ -> LEMMA), false;
+        "let", (fun _ -> EXT_LET), false;
+        (* ACSL extension for external spec file *)
+        "logic", (fun _ -> LOGIC), false;
+        "long", (fun _ -> LONG), true;
+        "loop", (fun _ -> LOOP), false;
+        "model", (fun _ -> MODEL), false;
+        (* ACSL extension for model fields *)
+        "module", (fun _ -> MODULE), false;
+        (* ACSL extension for external spec file *)
+        "pragma", (fun _ -> PRAGMA), false;
+        "predicate", (fun _ -> PREDICATE), false;
+        "reads", (fun _ -> READS), true;
+        (* treated specifically in the parser to
+           avoid issue in volatile clause. *)
+        "requires", (fun _ -> REQUIRES), false;
+        "returns", (fun _ -> RETURNS), false;
+        "short", (fun _ -> SHORT), true;
+        "signed", (fun _ -> SIGNED), true;
+        "sizeof", (fun _ -> SIZEOF), true;
+        "slice", (fun _ -> SLICE), false;
+        "struct", (fun _ -> STRUCT), true;
+        "terminates", (fun _ -> TERMINATES), false;
+        "type", (fun _ -> TYPE), false;
+        "union", (fun _ -> UNION), true;
+        "unsigned", (fun _ -> UNSIGNED), true;
+        "variant", (fun _ -> VARIANT), false;
+        "void", (fun _ -> VOID), true;
+        "volatile", (fun _ -> VOLATILE), true;
+        "writes", (fun _ -> WRITES), true;
+        (* treated specifically in the parser to
+           avoid issue in volatile clause. *)
+        "__FC_FILENAME__",
+        (fun loc ->
+           let filename =
+             Filepath.(Normalized.to_pretty_string (fst loc).pos_path)
+           in
+           STRING_LITERAL (false,filename)),
+        true;
       ];
     List.iter (fun (x, y) -> Hashtbl.add type_kw x y)
       ["integer", INTEGER; "real", REAL; "boolean", BOOLEAN; ];
-    (fun s ->
+    (fun s loc ->
       try
-        Hashtbl.find (if Logic_utils.is_kw_c_mode () then c_kw else all_kw) s
+        (Hashtbl.find (if Logic_utils.is_kw_c_mode () then c_kw else all_kw) s)
+        loc
       with Not_found ->
         let res =
           if not (Logic_utils.is_kw_c_mode ()) then begin
@@ -292,7 +310,12 @@ rule token = parse
          }
 
   | '\\' rL (rL | rD)* { bs_identifier lexbuf }
-  | rL (rL | rD)*       { let s = lexeme lexbuf in identifier s }
+  | rL (rL | rD)*       {
+      let loc = Lexing.(lexeme_start_p lexbuf, lexeme_end_p lexbuf) in
+      let cabsloc = Cil_datatype.Location.of_lexing_loc loc in
+      let s = lexeme lexbuf in
+      identifier s cabsloc
+    }
 
   | '0'['x''X'] rH+ rIS?    { CONSTANT (IntConstant (lexeme lexbuf)) }
   | '0'['b''B'] rB+ rIS?    { CONSTANT (IntConstant (lexeme lexbuf)) }
diff --git a/tests/syntax/fc_filename.c b/tests/syntax/fc_filename.c
index 592f11f97c4..428237cc331 100644
--- a/tests/syntax/fc_filename.c
+++ b/tests/syntax/fc_filename.c
@@ -3,3 +3,5 @@ const char* test = "string concatenation test: " __FC_FILENAME__ ". end test";
 int f() {
   return test[2] == 'r';
 }
+
+/*@ lemma test: "string cst in ACSL: " __FC_FILENAME__ ".end test"[3] == 'i'; */
diff --git a/tests/syntax/oracle/fc_filename.res.oracle b/tests/syntax/oracle/fc_filename.res.oracle
index 32ef5735731..1d842ed812f 100644
--- a/tests/syntax/oracle/fc_filename.res.oracle
+++ b/tests/syntax/oracle/fc_filename.res.oracle
@@ -9,4 +9,9 @@ int f(void)
   return __retres;
 }
 
+/*@
+lemma test{L}:
+  *("string cst in ACSL: tests/syntax/fc_filename.c.end test" + 3) ≡ 'i';
+
+*/
 
-- 
GitLab