Release coccinelle-0.2.5-rc2
[bpt/coccinelle.git] / parsing_cocci / parser_cocci_menhir.mly
index 01a67f6..f0b6832 100644 (file)
@@ -82,7 +82,7 @@ module P = Parse_aux
 
 %token <string>  TPathIsoFile
 %token <string * Data.clt> TIncludeL TIncludeNL
-%token <Data.clt * token> TDefine
+%token <Data.clt * token> TDefine TUndef
 %token <Data.clt * token * int * int> TDefineParam
 %token <string * Data.clt> TMinusFile TPlusFile
 
@@ -264,6 +264,8 @@ incl:
 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
 | TVirtual comma_list(pure_ident)
     { let names = List.map P.id2name $2 in
+      Iteration.parsed_virtual_rules :=
+       Common.union_set names !Iteration.parsed_virtual_rules;
       (* ensure that the names of virtual and real rules don't overlap *)
       List.iter
       (function name -> Hashtbl.add Data.all_metadecls name [])
@@ -408,6 +410,9 @@ list_len:
         let vl = List.assoc name virtual_env in
         !Data.add_virt_id_meta_found name vl; []
        with Not_found ->
+        Iteration.parsed_virtual_identifiers :=
+          Common.union_set [name]
+            !Iteration.parsed_virtual_identifiers;
         let name = ("virtual",name) in
         let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
         !Data.add_virt_id_meta_not_found name pure; tok in
@@ -758,6 +763,20 @@ includes:
                            P.clt2mcode
                              (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
                              (P.drop_bef clt))) }
+| TUndef TLineEnd
+    { let (clt,ident) = $1 in
+      Ast0.wrap
+      (Ast0.Undef
+        (P.clt2mcode "#undef" clt,
+         (match ident with
+           TMetaId((nm,constraints,pure,clt)) ->
+             Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
+         | TIdent(nm_pure) ->
+             Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
+         | _ ->
+             raise
+               (Semantic_cocci.Semantic
+                  "unexpected name for a #define")))) }
 | d=defineop TLineEnd
     { d (Ast0.wrap(Ast0.DOTS([]))) }
 | d=defineop t=ctype TLineEnd
@@ -1259,11 +1278,13 @@ decl_statement_expr:
 
 /*****************************************************************************/
 
-/* The following cannot contain <... ...> at the top level.  This can only
-be allowed as an expression when the expression is delimited on both sides
-by expression-specific markers.  In that case, the rule eexpr is used, which
+/* expr cannot contain <... ...> at the top level.  This can only
+be allowed as an expression when the expression is delimited on the left
+by an expression-specific marker.  In that case, the rule eexpr is used, which
 allows <... ...> anywhere.  Hopefully, this will not be too much of a problem
-in practice. */
+in practice.
+dot_expressions is the most permissive.  all three kinds of expressions use
+this once an expression_specific token has been seen */
 expr:  basic_expr(expr,invalid) { $1 }
 /* allows ... and nests */
 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
@@ -1320,41 +1341,74 @@ assign_expr_bis:
 
 cond_expr(r,pe):
     arith_expr(r,pe)                         { $1 }
-  | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
+  | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=eexpr/*see parser_c*/
       { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
                                 P.clt2mcode ":" dd, r)) }
 
 arith_expr(r,pe):
     cast_expr(r,pe)                         { $1 }
-  | arith_expr(r,pe) TMul    arith_expr(r,pe)
+  | arith_expr(r,pe) TMul    arith_expr_bis
       { P.arith_op Ast.Mul $1 $2 $3 }
-  | arith_expr(r,pe) TDmOp    arith_expr(r,pe)
+  | arith_expr(r,pe) TDmOp    arith_expr_bis
       { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
-  | arith_expr(r,pe) TPlus   arith_expr(r,pe)
+  | arith_expr(r,pe) TPlus   arith_expr_bis
       { P.arith_op Ast.Plus $1 $2 $3 }
-  | arith_expr(r,pe) TMinus  arith_expr(r,pe)
+  | arith_expr(r,pe) TMinus  arith_expr_bis
       { P.arith_op Ast.Minus $1 $2 $3 }
-  | arith_expr(r,pe) TShLOp    arith_expr(r,pe)
+  | arith_expr(r,pe) TShLOp    arith_expr_bis
       { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
-  | arith_expr(r,pe) TShROp    arith_expr(r,pe)
+  | arith_expr(r,pe) TShROp    arith_expr_bis
       { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
-  | arith_expr(r,pe) TLogOp    arith_expr(r,pe)
+  | arith_expr(r,pe) TLogOp    arith_expr_bis
       { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
-  | arith_expr(r,pe) TEqEq   arith_expr(r,pe)
+  | arith_expr(r,pe) TEqEq   arith_expr_bis
       { P.logic_op Ast.Eq $1 $2 $3 }
-  | arith_expr(r,pe) TNotEq  arith_expr(r,pe)
+  | arith_expr(r,pe) TNotEq  arith_expr_bis
       { P.logic_op Ast.NotEq $1 $2 $3 }
-  | arith_expr(r,pe) TAnd    arith_expr(r,pe)
+  | arith_expr(r,pe) TAnd    arith_expr_bis
       { P.arith_op Ast.And $1 $2 $3 }
-  | arith_expr(r,pe) TOr     arith_expr(r,pe)
+  | arith_expr(r,pe) TOr     arith_expr_bis
       { P.arith_op Ast.Or $1 $2 $3 }
-  | arith_expr(r,pe) TXor    arith_expr(r,pe)
+  | arith_expr(r,pe) TXor    arith_expr_bis
       { P.arith_op Ast.Xor $1 $2 $3 }
-  | arith_expr(r,pe) TAndLog arith_expr(r,pe)
+  | arith_expr(r,pe) TAndLog arith_expr_bis
       { P.logic_op Ast.AndLog $1 $2 $3 }
-  | arith_expr(r,pe) TOrLog  arith_expr(r,pe)
+  | arith_expr(r,pe) TOrLog  arith_expr_bis
       { P.logic_op Ast.OrLog $1 $2 $3 }
 
+// allows dots now that an expression-specific token has been seen
+// need an extra rule because of recursion restrictions
+arith_expr_bis:
+    cast_expr(eexpr,dot_expressions)                         { $1 }
+  | arith_expr_bis TMul    arith_expr_bis
+      { P.arith_op Ast.Mul $1 $2 $3 }
+  | arith_expr_bis TDmOp    arith_expr_bis
+      { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+  | arith_expr_bis TPlus   arith_expr_bis
+      { P.arith_op Ast.Plus $1 $2 $3 }
+  | arith_expr_bis TMinus  arith_expr_bis
+      { P.arith_op Ast.Minus $1 $2 $3 }
+  | arith_expr_bis TShLOp    arith_expr_bis
+      { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+  | arith_expr_bis TShROp    arith_expr_bis
+      { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+  | arith_expr_bis TLogOp    arith_expr_bis
+      { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
+  | arith_expr_bis TEqEq   arith_expr_bis
+      { P.logic_op Ast.Eq $1 $2 $3 }
+  | arith_expr_bis TNotEq  arith_expr_bis
+      { P.logic_op Ast.NotEq $1 $2 $3 }
+  | arith_expr_bis TAnd    arith_expr_bis
+      { P.arith_op Ast.And $1 $2 $3 }
+  | arith_expr_bis TOr     arith_expr_bis
+      { P.arith_op Ast.Or $1 $2 $3 }
+  | arith_expr_bis TXor    arith_expr_bis
+      { P.arith_op Ast.Xor $1 $2 $3 }
+  | arith_expr_bis TAndLog arith_expr_bis
+      { P.logic_op Ast.AndLog $1 $2 $3 }
+// no OrLog because it is left associative and this is for
+// a right argument, not sure why not the same problem for AndLog
+
 cast_expr(r,pe):
     unary_expr(r,pe)                      { $1 }
   | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
@@ -1363,16 +1417,35 @@ cast_expr(r,pe):
 
 unary_expr(r,pe):
     postfix_expr(r,pe)                   { $1 }
-  | TInc unary_expr(r,pe)
+  | TInc unary_expr_bis
       { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
-  | TDec unary_expr(r,pe)
+  | TDec unary_expr_bis
       { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
   | unary_op cast_expr(r,pe)
       { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
-  | TBang unary_expr(r,pe)
+  | TBang unary_expr_bis
+      { let mcode = P.clt2mcode Ast.Not $1 in
+      Ast0.wrap(Ast0.Unary($2, mcode)) }
+  | TSizeof unary_expr_bis
+      { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
+  | s=TSizeof lp=TOPar t=ctype rp=TCPar
+      { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
+                                   P.clt2mcode "(" lp,t,
+                                   P.clt2mcode ")" rp)) }
+
+// version that allows dots
+unary_expr_bis:
+    postfix_expr(eexpr,dot_expressions)                   { $1 }
+  | TInc unary_expr_bis
+      { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
+  | TDec unary_expr_bis
+      { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
+  | unary_op cast_expr(eexpr,dot_expressions)
+      { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
+  | TBang unary_expr_bis
       { let mcode = P.clt2mcode Ast.Not $1 in
       Ast0.wrap(Ast0.Unary($2, mcode)) }
-  | TSizeof unary_expr(r,pe)
+  | TSizeof unary_expr_bis
       { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
   | s=TSizeof lp=TOPar t=ctype rp=TCPar
       { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
@@ -1532,7 +1605,14 @@ pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
          None -> (i, Ast.IdNoConstraint)
        | Some constraint_ -> (i,constraint_))
     }
-| TVirtual TDot pure_ident { Common.Right (P.id2name $3) }
+| TVirtual TDot pure_ident
+    {
+     let nm = P.id2name $3 in
+     Iteration.parsed_virtual_identifiers :=
+       Common.union_set [nm]
+        !Iteration.parsed_virtual_identifiers;
+     Common.Right nm
+    }
 
 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
        i=pure_ident_or_meta_ident c=option(constraint_type)
@@ -2106,6 +2186,9 @@ script_name_decl:
         (($2, nm), mv) }
   | TShLOp TVirtual TDot cocci=pure_ident
       { let nm = P.id2name cocci in
+        Iteration.parsed_virtual_identifiers :=
+          Common.union_set [nm]
+            !Iteration.parsed_virtual_identifiers;
         let name = ("virtual", nm) in
         let mv = Ast.MetaIdDecl(Ast.NONE,name) in
         (name,mv) }