- Try to do better pretty printing when array elements are individually
[bpt/coccinelle.git] / parsing_c / parser_c.mly
index f63cdba..0318137 100644 (file)
@@ -69,7 +69,7 @@ let addStorageD  = function
 let addInlineD  = function
   | ((true,ii), ({inlineD = (false,[])} as v)) -> { v with inlineD=(true,[ii])}
   | ((true,ii), ({inlineD = (true, ii2)} as v)) -> warning "duplicate inline" v
-  | _ -> raise Impossible
+  | _ -> raise (Impossible 86)
 
 
 let addTypeD     = function
@@ -98,8 +98,8 @@ let addTypeD     = function
   | ((Middle3 x,ii),      ({typeD = ((a,None,c),ii2)} as v))  ->
       {v with typeD = (a, Some x,c),ii++ii2}
 
-  | ((Right3 t,ii),       ({typeD = ((a,b,Some _),ii2)} as _v)) ->
-      raise (Semantic ("two or more data types", fake_pi))
+  | ((Right3 t,ii),       ({typeD = ((a,b,Some x),ii2)} as _v)) ->
+      raise (Semantic ((Printf.sprintf "two or more data types: t %s ii %s\ntypeD %s ii2 %s\n" (Dumper.dump t) (Dumper.dump ii) (Dumper.dump x) (Dumper.dump ii2)), fake_pi))
   | ((Right3 t,ii),       ({typeD = ((a,b,None),ii2)} as v))   ->
       {v with typeD = (a,b, Some t),ii++ii2}
 
@@ -231,7 +231,7 @@ let (fixOldCDecl: fullType -> fullType) = fun ty ->
           | BaseType Void ->
               ty
           | _ ->
-              pr2 ("SEMANTIC:parameter name omitted, but I continue");
+              pr2_once ("SEMANTIC:parameter name omitted, but I continue");
               ty
           )
 
@@ -240,7 +240,7 @@ let (fixOldCDecl: fullType -> fullType) = fun ty ->
             match param with
             | {p_namei = None} ->
               (* if majuscule, then certainly macro-parameter *)
-                pr2 ("SEMANTIC:parameter name omitted, but I continue");
+                pr2_once ("SEMANTIC:parameter name omitted, but I continue");
            | _ -> ()
           ));
           ty
@@ -400,6 +400,8 @@ let mk_string_wrap (s,info) = (s, [info])
 %token <(string * Ast_c.isWchar) * Ast_c.info>   TString
 
 %token <string * Ast_c.info> TIdent
+%token <string * Ast_c.info> TKRParam
+%token <string * Ast_c.info> Tconstructorname /* parsing_hack for c++ */
 /*(* appears mostly after some fix_xxx in parsing_hack *)*/
 %token <string * Ast_c.info> TypedefIdent
 
@@ -428,13 +430,14 @@ let mk_string_wrap (s,info) = (s, [info])
 
 %token <Ast_c.info>
        Tchar Tshort Tint Tdouble Tfloat Tlong Tunsigned Tsigned Tvoid
+       Tsize_t Tssize_t Tptrdiff_t
        Tauto Tregister Textern Tstatic
        Ttypedef
        Tconst Tvolatile
        Tstruct Tunion Tenum
        Tbreak Telse Tswitch Tcase Tcontinue Tfor Tdo Tif  Twhile Treturn
        Tgoto Tdefault
-       Tsizeof
+       Tsizeof Tnew Tdelete TOParCplusplusInit
 
 /*(* C99 *)*/
 %token <Ast_c.info>
@@ -502,8 +505,7 @@ let mk_string_wrap (s,info) = (s, [info])
 /*(* other         *)*/
 /*(*---------------*)*/
 
-
-%token <string * Ast_c.info> TUndef
+%token <Ast_c.info> TUndef
 
 %token <Ast_c.info> TCppDirectiveOther
 
@@ -613,7 +615,8 @@ let mk_string_wrap (s,info) = (s, [info])
 /*(*************************************************************************)*/
 /*(* no more used; now that use error recovery *)*/
 
-main:  translation_unit EOF     { $1 }
+main:
+ translation_unit EOF     { $1 }
 
 translation_unit:
  | external_declaration
@@ -661,7 +664,7 @@ ident_extra_cpp:
      {
        CppConcatenatedName (
          match $3 with
-         | [] -> raise Impossible
+         | [] -> raise (Impossible 87)
          | (x,concatnull)::xs ->
              assert(null concatnull);
              (mk_string_wrap $1, [])::(x,[$2])::xs
@@ -735,6 +738,39 @@ unary_expr:
  | unary_op cast_expr              { mk_e(Unary ($2, fst $1)) [snd $1] }
  | Tsizeof unary_expr              { mk_e(SizeOfExpr ($2))    [$1] }
  | Tsizeof topar2 type_name tcpar2 { mk_e(SizeOfType ($3))    [$1;$2;$4] }
+ | Tnew new_argument               { mk_e(New $2)             [$1] }
+ | Tdelete cast_expr               { mk_e(Delete $2)          [$1] }
+
+new_argument:
+ | TIdent TOPar argument_list_ne TCPar
+     { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
+       Left (mk_e(FunCall (fn, $3)) [$2;$4]) }
+ | TIdent TOPar TCPar
+     { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
+       Left(mk_e(FunCall (fn, [])) [$2;$3]) }
+ | TypedefIdent TOPar argument_list_ne TCPar
+     { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
+       Left (mk_e(FunCall (fn, $3)) [$2;$4]) }
+ | TypedefIdent TOPar TCPar
+     { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
+       Left (mk_e(FunCall (fn, [])) [$2;$3]) }
+ | type_spec
+     { let ty = addTypeD ($1,nullDecl) in
+       let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam ty in
+       Right (ArgType { p_namei = None; p_type = returnType;
+                       p_register = hasreg, iihasreg;
+                     } )
+     }
+ | new_argument TOCro expr TCCro
+     {
+       match $1 with
+        Left(e) -> Left(mk_e(ArrayAccess (e, $3)) [$2;$4])
+       | Right(ArgType(ty)) -> (* lots of hacks to make the right type *)
+          let fty = mk_ty (Array (Some $3, ty.Ast_c.p_type)) [$2;$4] in
+          let pty = { ty with p_type = fty } in
+          Right(ArgType pty)
+       | _ -> raise (Impossible 88)
+     } 
 
 unary_op:
  | TAnd   { GetRef,     $1 }
@@ -748,8 +784,6 @@ unary_op:
     *)*/
  | TAndLog { GetRefLabel, $1 }
 
-
-
 postfix_expr:
  | primary_expr               { $1 }
  | postfix_expr TOCro expr TCCro
@@ -764,9 +798,10 @@ postfix_expr:
 
  /*(* gccext: also called compound literals *)*/
  | topar2 type_name tcpar2 TOBrace TCBrace
-     { mk_e(Constructor ($2, [])) [$1;$3;$4;$5] }
+     { mk_e(Constructor ($2, (InitList [], [$4;$5]))) [$1;$3] }
  | topar2 type_name tcpar2 TOBrace initialize_list gcc_comma_opt TCBrace
-     { mk_e(Constructor ($2, List.rev $5)) ([$1;$3;$4;$7] ++ $6) }
+     { mk_e(Constructor ($2, (InitList (List.rev $5),[$4;$7]++$6))) [$1;$3] }
+
 
 primary_expr:
  | identifier_cpp  { mk_e(Ident  ($1)) [] }
@@ -863,11 +898,16 @@ statement2:
    * a Case  (1, (Case (2, i++)))  :(
    *)*/
 labeled:
- | ident_cpp        TDotDot statement   { Label ($1, $3),  [$2] }
- | Tcase const_expr TDotDot statement   { Case ($2, $4),       [$1; $3] }
- | Tcase const_expr TEllipsis const_expr TDotDot statement
+ | ident_cpp        TDotDot sw_stat_or_decl   { Label ($1, $3),  [$2] }
+ | Tcase const_expr TDotDot sw_stat_or_decl   { Case ($2, $4),       [$1; $3] }
+ | Tcase const_expr TEllipsis const_expr TDotDot sw_stat_or_decl
      { CaseRange ($2, $4, $6), [$1;$3;$5] } /*(* gccext: allow range *)*/
- | Tdefault         TDotDot statement   { Default $3,             [$1; $2] }
+ | Tdefault    TDotDot sw_stat_or_decl   { Default $3,             [$1; $2] }
+
+sw_stat_or_decl:
+ | decl      { mk_st (Decl ($1 Ast_c.LocalDecl)) Ast_c.noii }
+ | statement { $1 }
+
 
 end_labeled:
  /*(* gccext:  allow toto: }
@@ -924,9 +964,6 @@ stat_or_decl:
      { IfdefStmt $1 }
 
 
-
-
-
 expr_statement:
  | TPtVirg      { None,    [$1] }
  | expr TPtVirg { Some $1, [$2] }
@@ -945,15 +982,14 @@ iteration:
  | Tdo statement Twhile TOPar expr TCPar TPtVirg
      { DoWhile ($2,$5),              [$1;$3;$4;$6;$7] }
  | Tfor TOPar expr_statement expr_statement TCPar statement
-     { For ($3,$4,(None, []),$6),    [$1;$2;$5]}
+     { For (ForExp $3,$4,(None, []),$6),    [$1;$2;$5]}
  | Tfor TOPar expr_statement expr_statement expr TCPar statement
-     { For ($3,$4,(Some $5, []),$7), [$1;$2;$6] }
+     { For (ForExp $3,$4,(Some $5, []),$7), [$1;$2;$6] }
  /*(* c++ext: for(int i = 0; i < n; i++)*)*/
- | Tfor TOPar decl expr_statement expr_opt TCPar statement
-     {
-       (* pr2 "DECL in for"; *)
-       MacroIteration ("toto", [], $7),[$1;$2;$6] (* TODOfake ast, TODO need decl2 ? *)
-     }
+ | Tfor TOPar decl expr_statement TCPar statement
+     { For (ForDecl ($3 Ast_c.LocalDecl),$4,(None, []),$6),    [$1;$2;$5]}
+ | Tfor TOPar decl expr_statement expr TCPar statement
+     { For (ForDecl ($3 Ast_c.LocalDecl),$4,(Some $5, []),$7), [$1;$2;$6] }
  /*(* cppext: *)*/
  | TMacroIterator TOPar argument_list_ne TCPar statement
      { MacroIteration (fst $1, $3, $5), [snd $1;$2;$4] }
@@ -1012,6 +1048,9 @@ type_spec2:
  | Tint                 { Right3 (BaseType (IntType (Si (Signed,CInt)))), [$1]}
  | Tfloat               { Right3 (BaseType (FloatType CFloat)),  [$1]}
  | Tdouble              { Right3 (BaseType (FloatType CDouble)), [$1] }
+ | Tsize_t              { Right3 (BaseType SizeType),            [$1] }
+ | Tssize_t             { Right3 (BaseType SSizeType),           [$1] }
+ | Tptrdiff_t           { Right3 (BaseType PtrDiffType),         [$1] }
  | Tshort               { Middle3 Short,  [$1]}
  | Tlong                { Middle3 Long,   [$1]}
  | Tsigned              { Left3 Signed,   [$1]}
@@ -1091,13 +1130,22 @@ declarator:
 
 /*(* so must do  int * const p; if the pointer is constant, not the pointee *)*/
 pointer:
- | TMul                   { fun x -> mk_ty (Pointer x) [$1] }
- | TMul pointer           { fun x -> mk_ty (Pointer ($2 x)) [$1] }
- | TMul type_qualif_list
+ | tmul                   { fun x -> mk_ty (Pointer x) [$1] }
+ | tmul pointer           { fun x -> mk_ty (Pointer ($2 x)) [$1] }
+ | tmul type_qualif_list
      { fun x -> ($2.qualifD, mk_tybis (Pointer x) [$1])}
- | TMul type_qualif_list pointer
+ | tmul type_qualif_list pointer
      { fun x -> ($2.qualifD, mk_tybis (Pointer ($3 x)) [$1]) }
 
+tmul:
+   TMul { $1 }
+ | TAnd
+     { if !Flag.c_plus_plus
+     then $1
+     else
+       let i = Ast_c.parse_info_of_info $1 in
+       raise (Semantic("& not allowed in C types, try -c++ option", i)) }
+
 
 direct_d:
  | identifier_cpp
@@ -1171,6 +1219,14 @@ parameter_type_list:
 
 
 parameter_decl2:
+   TKRParam {
+     let name = RegularName (mk_string_wrap $1) in
+     LP.add_ident (str_of_name name);
+     { p_namei = Some name;
+       p_type = mk_ty NoType [];
+       p_register = (false, []);
+     }
+   }
  | decl_spec declaratorp
      { let ((returnType,hasreg),iihasreg) = fixDeclSpecForParam $1 in
        let (name, ftyp) = $2 in
@@ -1279,14 +1335,9 @@ decl2:
        DeclList (
          ($2 +> List.map (fun ((((name,f),attrs), ini), iivirg) ->
            let s = str_of_name name in
-           let iniopt =
-             match ini with
-             | None -> None
-             | Some (ini, iini) -> Some (iini, ini)
-           in
           if fst (unwrap storage) =*= StoTypedef
           then LP.add_typedef s;
-           {v_namei = Some (name, iniopt);
+           {v_namei = Some (name, ini);
             v_type = f returnType;
             v_storage = unwrap storage;
             v_local = local;
@@ -1301,13 +1352,26 @@ decl2:
 
  | TMacroDecl TOPar argument_list TCPar TPtVirg
      { function _ ->
-       MacroDecl ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]) }
+       MacroDecl ((fst $1, $3, true), [snd $1;$2;$4;$5;fakeInfo()]) }
  | Tstatic TMacroDecl TOPar argument_list TCPar TPtVirg
      { function _ ->
-       MacroDecl ((fst $2, $4), [snd $2;$3;$5;$6;fakeInfo();$1]) }
+       MacroDecl ((fst $2, $4, true), [snd $2;$3;$5;$6;fakeInfo();$1]) }
  | Tstatic TMacroDeclConst TMacroDecl TOPar argument_list TCPar TPtVirg
      { function _ ->
-       MacroDecl ((fst $3, $5), [snd $3;$4;$6;$7;fakeInfo();$1;$2])}
+       MacroDecl ((fst $3, $5, true), [snd $3;$4;$6;$7;fakeInfo();$1;$2])}
+
+
+ | TMacroDecl TOPar argument_list TCPar teq initialize TPtVirg
+     { function _ ->
+       MacroDeclInit ((fst $1, $3, $6), [snd $1;$2;$4;$5;$7;fakeInfo()]) }
+ | Tstatic TMacroDecl TOPar argument_list TCPar teq initialize TPtVirg
+     { function _ ->
+       MacroDeclInit ((fst $2, $4, $7),[snd $2;$3;$5;$6;$8;fakeInfo();$1]) }
+ | Tstatic TMacroDeclConst TMacroDecl TOPar argument_list TCPar
+     teq initialize TPtVirg
+     { function _ ->
+       MacroDeclInit
+        ((fst $3, $5, $8), [snd $3;$4;$6;$7;$9;fakeInfo();$1;$2])}
 
 
 /*(*-----------------------------------------------------------------------*)*/
@@ -1351,9 +1415,11 @@ decl_spec: decl_spec2    { dt "declspec" (); $1  }
 /*(* declarators (right part of type and variable) *)*/
 /*(*-----------------------------------------------------------------------*)*/
 init_declarator2:
- | declaratori                  { ($1, None) }
- | declaratori teq initialize   { ($1, Some ($3, $2)) }
-
+ | declaratori                  { ($1, NoInit) }
+ | declaratori teq initialize   { ($1, ValInit($2, $3)) }
+ /* C++ only */
+ | declaratori TOParCplusplusInit argument_list TCPar
+     { ($1, ConstrInit($3,[$2;$4])) }
 
 
 /*(*----------------------------*)*/
@@ -1506,7 +1572,7 @@ field_declaration:
           *)
      }
 
- |  spec_qualif_list TPtVirg
+ | spec_qualif_list TPtVirg
      {
        (* gccext: allow empty elements if it is a structdef or enumdef *)
        let (returnType,storage) = fixDeclSpecForDecl $1 in
@@ -1557,9 +1623,9 @@ struct_decl_list_gcc:
 /*(* enum *)*/
 /*(*************************************************************************)*/
 enum_spec:
- | Tenum        tobrace_enum enumerator_list gcc_comma_opt tcbrace_enum
+ | Tenum        tobrace_enum enumerator_list gcc_comma_opt_struct tcbrace_enum
      { Enum (None,    $3),           [$1;$2;$5] ++ $4 }
- | Tenum ident  tobrace_enum enumerator_list gcc_comma_opt tcbrace_enum
+ | Tenum ident  tobrace_enum enumerator_list gcc_comma_opt_struct tcbrace_enum
      { Enum (Some (fst $2), $4),     [$1; snd $2; $3;$6] ++ $5 }
  | Tenum ident
      { EnumName (fst $2),       [$1; snd $2] }
@@ -1612,6 +1678,23 @@ start_fun2: decl_spec declaratorfd
        let (id, attrs) = $2 in
        (fst id, fixOldCDecl ((snd id) returnType) , storage, attrs)
      }
+   | ctor_dtor { $1 }
+
+ctor_dtor:
+ | Tconstructorname topar tcpar {
+     let id = RegularName (mk_string_wrap $1) in
+     let ret = mk_ty NoType [] in
+     let ty = mk_ty (FunctionType (ret, (([], (false, []))))) [$2;$3] in
+     let storage = ((NoSto,false),[]) in
+     let attrs = [] in
+     (id, ty, storage, attrs) }
+ | Tconstructorname topar parameter_type_list tcpar {
+     let id = RegularName (mk_string_wrap $1) in
+     let ret = mk_ty NoType [] in
+     let ty = mk_ty (FunctionType (ret, $3)) [$2;$4] in
+     let storage = ((NoSto,false),[]) in
+     let attrs = [] in
+     (id, ty, storage, attrs) }
 
 /*(*----------------------------*)*/
 /*(* workarounds *)*/
@@ -1669,11 +1752,12 @@ cpp_directive:
   *)*/
  | TDefine TIdentDefine TOParDefine param_define_list TCPar define_val TDefEOL
      { Define
-         ((fst $2, [$1; snd $2;$7]),
+         ((fst $2, [$1; snd $2; $7]),
            (DefineFunc ($4, [$3;$5]), $6))
      }
 
- | TUndef             { Undef (fst $1, [snd $1]) }
+ | TUndef TIdentDefine TDefEOL
+     { Define((fst $2, [$1; snd $2; $3]), (Undef,DefineEmpty)) }
  | TCppDirectiveOther { PragmaAndCo ([$1]) }
 
 
@@ -1705,18 +1789,23 @@ define_val:
        DefineType typ
      }
 
-/* can be in conflict with decl_spec, maybe change fixDeclSpecForMacro
+/*(* can be in conflict with decl_spec, maybe change fixDeclSpecForMacro
  * to also allow storage ?
  | storage_class_spec { DefineTodo }
  | Tinline { DefineTodo }
-*/
+*)*/
 
- /*(* a few special cases *)*/
- | stat_or_decl stat_or_decl_list { DefineTodo }
-/*
+ | stat_or_decl stat_or_decl_list 
+     { DefineMulti
+        (List.map
+           (function
+               StmtElem e -> e
+             | _ -> failwith "unexpected statement for DefineMulti")
+           ($1 :: $2)) }
+/*(*
  | statement statement { DefineTodo }
  | decl function_definition { DefineTodo }
-*/
+*)*/
 
 
 
@@ -1791,13 +1880,13 @@ cpp_other:
     *)*/
  | identifier TOPar argument_list TCPar TPtVirg
      {
-       Declaration (MacroDecl ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]))
+       Declaration(MacroDecl((fst $1, $3, true), [snd $1;$2;$4;$5;fakeInfo()]))
        (* old: MacroTop (fst $1, $3,    [snd $1;$2;$4;$5])  *)
      }
 
  /*(* TCParEOL to fix the end-of-stream bug of ocamlyacc *)*/
  | identifier TOPar argument_list TCParEOL
-     { MacroTop (fst $1, $3,    [snd $1;$2;$4;fakeInfo()]) }
+     { Declaration (MacroDecl ((fst $1, $3, false), [snd $1;$2;$4;fakeInfo()])) }
 
   /*(* ex: EXPORT_NO_SYMBOLS; *)*/
  | identifier TPtVirg { EmptyDef [snd $1;$2] }
@@ -1814,7 +1903,7 @@ external_declaration:
 
 
 celem:
- | external_declaration                         { $1 }
  | external_declaration                         { $1 }
 
  /*(* cppext: *)*/
  | cpp_directive
@@ -2016,7 +2105,3 @@ opt_ptvirg:
 *)*/
 
 
-expr_opt:
- | expr            { Some $1 }
- | /*(* empty *)*/ { None }
-