Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / parsing_cocci / lexer_cocci.mll
index 878edc5..0125f0e 100644 (file)
@@ -1,25 +1,3 @@
-(*
-* Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
-* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
-* This file is part of Coccinelle.
-* 
-* Coccinelle is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, according to version 2 of the License.
-* 
-* Coccinelle is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-* 
-* You should have received a copy of the GNU General Public License
-* along with Coccinelle.  If not, see <http://www.gnu.org/licenses/>.
-* 
-* The authors reserve the right to distribute this or future versions of
-* Coccinelle under other licenses.
-*)
-
-
 {
 open Parser_cocci_menhir
 module D = Data
@@ -49,7 +27,7 @@ let get_current_line_type lexbuf =
   let preceeding_spaces =
     if !line_start < 0 then 0 else lex_start - !line_start in
   (*line_start := -1;*)
-  prev_plus := (c = D.PLUS);
+  prev_plus := (c = D.PLUS) or (c = D.PLUSPLUS);
   (c,l,ll,lex_start,preceeding_spaces,[],[],Ast0.NoMetaPos)
 let current_line_started = ref false
 let col_zero = ref true
@@ -87,6 +65,8 @@ let add_current_line_type x =
       current_line_type := (D.OPTMINUS,ln,lln)
   | (D.PLUS,(D.CONTEXT,ln,lln))   ->
       current_line_type := (D.PLUS,ln,lln)
+  | (D.PLUSPLUS,(D.CONTEXT,ln,lln))   ->
+      current_line_type := (D.PLUSPLUS,ln,lln)
   | (D.UNIQUE,(D.CONTEXT,ln,lln)) ->
       current_line_type := (D.UNIQUE,ln,lln)
   | (D.OPT,(D.CONTEXT,ln,lln))    ->
@@ -95,7 +75,7 @@ let add_current_line_type x =
 
 let check_minus_context_linetype s =
   match !current_line_type with
-    (D.PLUS,_,_) -> lexerr "invalid in a + context: " s
+    (D.PLUS,_,_) | (D.PLUSPLUS,_,_) -> lexerr "invalid in a + context: " s
   | _ -> ()
 
 let check_context_linetype s =
@@ -105,17 +85,18 @@ let check_context_linetype s =
 
 let check_plus_linetype s =
   match !current_line_type with
-    (D.PLUS,_,_) -> ()
+    (D.PLUS,_,_) | (D.PLUSPLUS,_,_) -> ()
   | _ -> lexerr "invalid in a non + context: " s
 
 let check_arity_context_linetype s =
   match !current_line_type with
-    (D.CONTEXT,_,_) | (D.PLUS,_,_) | (D.UNIQUE,_,_) | (D.OPT,_,_) -> ()
+    (D.CONTEXT,_,_) | (D.PLUS,_,_) | (D.PLUSPLUS,_,_)
+  | (D.UNIQUE,_,_) | (D.OPT,_,_) -> ()
   | _ -> lexerr "invalid in a nonempty context: " s
 
 let process_include start finish str =
   (match !current_line_type with
-    (D.PLUS,_,_) ->
+    (D.PLUS,_,_) | (D.PLUSPLUS,_,_) ->
       (try
        let _ = Str.search_forward (Str.regexp "\\.\\.\\.") str start in
        lexerr "... not allowed in + include" ""
@@ -130,15 +111,20 @@ let pm = ref UNKNOWN
 
 let patch_or_match = function
     PATCH ->
-      (match !pm with
-       MATCH -> lexerr "- or + not allowed in the first column for a match" ""
-      |        PATCH -> ()
-      |        UNKNOWN -> Flag.sgrep_mode2 := false; pm := PATCH)
+      if not !D.ignore_patch_or_match
+      then
+       (match !pm with
+         MATCH ->
+           lexerr "- or + not allowed in the first column for a match" ""
+       | PATCH -> ()
+       | UNKNOWN -> Flag.sgrep_mode2 := false; pm := PATCH)
   | MATCH ->
-      (match !pm with
-       PATCH -> lexerr "* not allowed in the first column for a patch" ""
-      |        MATCH -> ()
-      |        UNKNOWN -> Flag.sgrep_mode2 := true; pm := MATCH)
+      if not !D.ignore_patch_or_match
+      then
+       (match !pm with
+         PATCH -> lexerr "* not allowed in the first column for a patch" ""
+       | MATCH -> ()
+       | UNKNOWN -> Flag.sgrep_mode2 := true; pm := MATCH)
   | _ -> failwith "unexpected argument"
 
 (* ---------------------------------------------------------------------- *)
@@ -179,7 +165,7 @@ let id_tokens lexbuf =
   let s = tok lexbuf in
   let linetype = get_current_line_type lexbuf in
   let in_rule_name = !Data.in_rule_name in
-  let in_meta = !Data.in_meta in
+  let in_meta = !Data.in_meta && not !Data.saw_struct in
   let in_iso = !Data.in_iso in
   let in_prolog = !Data.in_prolog in
   match s with
@@ -216,15 +202,16 @@ let id_tokens lexbuf =
   | "words" when in_meta ->      check_context_linetype s; TWords
 
   | "using" when in_rule_name || in_prolog ->  check_context_linetype s; TUsing
+  | "virtual" when in_prolog ->  check_context_linetype s; TVirtual
   | "disable" when in_rule_name ->  check_context_linetype s; TDisable
   | "extends" when in_rule_name -> check_context_linetype s; TExtends
   | "depends" when in_rule_name -> check_context_linetype s; TDepends
   | "on" when in_rule_name      -> check_context_linetype s; TOn
   | "ever" when in_rule_name    -> check_context_linetype s; TEver
   | "never" when in_rule_name   -> check_context_linetype s; TNever
+  (* exists and forall for when are reparsed in parse_cocci.ml *)
   | "exists" when in_rule_name  -> check_context_linetype s; TExists
   | "forall" when in_rule_name  -> check_context_linetype s; TForall
-  | "reverse" when in_rule_name -> check_context_linetype s; TReverse
   | "script" when in_rule_name  -> check_context_linetype s; TScript
   | "initialize" when in_rule_name -> check_context_linetype s; TInitialize
   | "finalize" when in_rule_name   -> check_context_linetype s; TFinalize
@@ -236,9 +223,11 @@ let id_tokens lexbuf =
   | "float" ->      Tfloat    linetype
   | "long" ->       Tlong     linetype
   | "void" ->       Tvoid     linetype
-  | "struct" ->     Tstruct   linetype
-  | "union" ->      Tunion    linetype
-  | "enum" ->       Tenum     linetype
+  (* in_meta is only for the first keyword; drop it now to allow any type
+     name *)
+  | "struct" ->     Data.saw_struct := true; Tstruct   linetype
+  | "union" ->      Data.saw_struct := true; Tunion    linetype
+  | "enum" ->       Data.saw_struct := true; Tenum     linetype
   | "unsigned" ->   Tunsigned linetype
   | "signed" ->     Tsigned   linetype
 
@@ -291,6 +280,7 @@ let init _ =
   Data.in_rule_name := false;
   Data.in_meta := false;
   Data.in_prolog := false;
+  Data.saw_struct := false;
   Data.inheritable_positions := [];
   Hashtbl.clear all_metavariables;
   Hashtbl.clear Data.all_metadecls;
@@ -306,7 +296,7 @@ let init _ =
       Hashtbl.replace metavariables (get_name name) fn);
   Data.add_fresh_id_meta :=
     (fun name ->
-      let fn clt = TMetaId(name,[],Ast0.Impure,clt) in
+      let fn clt = TMetaId(name,Ast.IdNoConstraint,Ast0.Impure,clt) in
       Hashtbl.replace metavariables (get_name name) fn);
   Data.add_type_meta :=
     (fun name pure ->
@@ -445,6 +435,8 @@ rule token = parse
           then (start_line true; TArob)
           else (check_minus_context_linetype "@"; TPArob) }
 
+  | "~="  { start_line true; TTildeEq (get_current_line_type lexbuf) }
+  | "!~=" { start_line true; TTildeExclEq (get_current_line_type lexbuf) }
   | "WHEN" | "when"
       { start_line true; check_minus_context_linetype (tok lexbuf);
        TWhen (get_current_line_type lexbuf) }
@@ -550,7 +542,12 @@ rule token = parse
                     TDmOp (Ast.Mod,get_current_line_type lexbuf) }
   | '~'            { start_line true;  TTilde (get_current_line_type lexbuf) }
 
-  | "++"           { start_line true;  TInc (get_current_line_type lexbuf) }
+  | "++"           { pass_zero();
+                    if !current_line_started
+                    then
+                      (start_line true; TInc (get_current_line_type lexbuf))
+                    else (patch_or_match PATCH;
+                          add_current_line_type D.PLUSPLUS; token lexbuf) }
   | "--"           { start_line true;  TDec (get_current_line_type lexbuf) }
 
   | "="            { start_line true; TEq (get_current_line_type lexbuf) }
@@ -571,8 +568,8 @@ rule token = parse
 
   | ":"            { start_line true; TDotDot (get_current_line_type lexbuf) }
 
-  | "=="           { start_line true; TEqEq   (get_current_line_type lexbuf) }
-  | "!="           { start_line true; TNotEq  (get_current_line_type lexbuf) }
+  | "=="           { start_line true; TEqEq    (get_current_line_type lexbuf) }
+  | "!="           { start_line true; TNotEq   (get_current_line_type lexbuf) }
   | ">="           { start_line true;
                     TLogOp(Ast.SupEq,get_current_line_type lexbuf) }
   | "<="           { start_line true;
@@ -593,6 +590,7 @@ rule token = parse
   | "&"            { start_line true; TAnd    (get_current_line_type lexbuf) }
   | "^"            { start_line true; TXor(get_current_line_type lexbuf) }
 
+  | "##"            { start_line true; TCppConcatOp }
   | (( ("#" [' ' '\t']*  "define" [' ' '\t']+)) as def)
     ( (letter (letter |digit)*) as ident)
       { start_line true;
@@ -737,7 +735,7 @@ and comment = parse
   (* noteopti: *)
   | [^ '*'] { start_line true; let s = tok lexbuf in s ^ comment lexbuf }
   | [ '*']   { start_line true; let s = tok lexbuf in s ^ comment lexbuf }
-  | _  
+  | _
       { start_line true; let s = tok lexbuf in
         Common.pr2 ("LEXER: unrecognised symbol in comment:"^s);
         s ^ comment lexbuf