2 (* Copyright (C) 2002, 2006, 2007, 2008 Yoann Padioleau
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License (GPL)
6 * version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * file license.txt for more details.
17 module LP = Lexer_parser
18 open Lexer_parser (* for the fields *)
20 open Semantic_c (* Semantic exn *)
22 module Stat = Parsing_stat
24 (*****************************************************************************)
26 (*****************************************************************************)
28 if !Flag_parsing_c.verbose_parsing
29 then Common.warning ("PARSING: " ^ s) v
34 if !Flag_parsing_c.verbose_parsing
37 (*****************************************************************************)
38 (* Parse helpers functions *)
39 (*****************************************************************************)
41 (*-------------------------------------------------------------------------- *)
43 (*-------------------------------------------------------------------------- *)
45 type shortLong = Short | Long | LongLong
48 storageD: storagebis wrap;
49 typeD: ((sign option) * (shortLong option) * (typeCbis option)) wrap;
50 qualifD: typeQualifierbis wrap;
52 (* note: have a full_info: parse_info list; to remember ordering
53 * between storage, qualifier, type ? well this info is already in
54 * the Ast_c.info, just have to sort them to get good order *)
59 typeD = (None, None, None), [];
63 let fake_pi = Common.fake_parse_info
65 let addStorageD = function
66 | ((x,ii), ({storageD = (NoSto,[])} as v)) -> { v with storageD = (x, [ii]) }
67 | ((x,ii), ({storageD = (y, ii2)} as v)) ->
68 if x = y then warning "duplicate storage classes" v
69 else raise (Semantic ("multiple storage classes", fake_pi))
71 let addInlineD = function
72 | ((true,ii), ({inlineD = (false,[])} as v)) -> { v with inlineD=(true,[ii])}
73 | ((true,ii), ({inlineD = (true, ii2)} as v)) -> warning "duplicate inline" v
74 | _ -> raise Impossible
77 let addTypeD = function
78 | ((Left3 Signed,ii) ,({typeD = ((Some Signed, b,c),ii2)} as v)) ->
79 warning "duplicate 'signed'" v
80 | ((Left3 UnSigned,ii) ,({typeD = ((Some UnSigned,b,c),ii2)} as v)) ->
81 warning "duplicate 'unsigned'" v
82 | ((Left3 _,ii), ({typeD = ((Some _,b,c),ii2)} as _v)) ->
83 raise (Semantic ("both signed and unsigned specified", fake_pi))
84 | ((Left3 x,ii), ({typeD = ((None,b,c),ii2)} as v)) ->
85 {v with typeD = (Some x,b,c),ii ++ ii2}
87 | ((Middle3 Short,ii), ({typeD = ((a,Some Short,c),ii2)} as v)) ->
88 warning "duplicate 'short'" v
91 (* gccext: long long allowed *)
92 | ((Middle3 Long,ii), ({typeD = ((a,Some Long ,c),ii2)} as v)) ->
93 { v with typeD = (a, Some LongLong, c),ii++ii2 }
94 | ((Middle3 Long,ii), ({typeD = ((a,Some LongLong ,c),ii2)} as v)) ->
95 warning "triplicate 'long'" v
98 | ((Middle3 _,ii), ({typeD = ((a,Some _,c),ii2)} as _v)) ->
99 raise (Semantic ("both long and short specified", fake_pi))
100 | ((Middle3 x,ii), ({typeD = ((a,None,c),ii2)} as v)) ->
101 {v with typeD = (a, Some x,c),ii++ii2}
103 | ((Right3 t,ii), ({typeD = ((a,b,Some _),ii2)} as _v)) ->
104 raise (Semantic ("two or more data types", fake_pi))
105 | ((Right3 t,ii), ({typeD = ((a,b,None),ii2)} as v)) ->
106 {v with typeD = (a,b, Some t),ii++ii2}
109 let addQualif = function
110 | ({const=true}, ({const=true} as x)) -> warning "duplicate 'const'" x
111 | ({volatile=true},({volatile=true} as x))-> warning "duplicate 'volatile'" x
112 | ({const=true}, v) -> {v with const=true}
113 | ({volatile=true}, v) -> {v with volatile=true}
114 | _ -> internal_error "there is no noconst or novolatile keyword"
116 let addQualifD ((qu,ii), ({qualifD = (v,ii2)} as x)) =
117 { x with qualifD = (addQualif (qu, v),ii::ii2) }
120 (*-------------------------------------------------------------------------- *)
121 (* Declaration/Function related *)
122 (*-------------------------------------------------------------------------- *)
125 (* stdC: type section, basic integer types (and ritchie)
126 * To understand the code, just look at the result (right part of the PM)
129 let (fixDeclSpecForDecl: decl -> (fullType * (storage wrap))) = function
130 {storageD = (st,iist);
133 inlineD = (inline,iinl);
138 | (None,None,None) -> warning "type defaults to 'int'" (defaultInt, [])
139 | (None, None, Some t) -> (t, iit)
141 | (Some sign, None, (None| Some (BaseType (IntType (Si (_,CInt)))))) ->
142 BaseType(IntType (Si (sign, CInt))), iit
143 | ((None|Some Signed),Some x,(None|Some(BaseType(IntType (Si (_,CInt)))))) ->
144 BaseType(IntType (Si (Signed, [Short,CShort; Long, CLong; LongLong, CLongLong] +> List.assoc x))), iit
145 | (Some UnSigned, Some x, (None| Some (BaseType (IntType (Si (_,CInt))))))->
146 BaseType(IntType (Si (UnSigned, [Short,CShort; Long, CLong; LongLong, CLongLong] +> List.assoc x))), iit
147 | (Some sign, None, (Some (BaseType (IntType CChar)))) -> BaseType(IntType (Si (sign, CChar2))), iit
148 | (None, Some Long,(Some(BaseType(FloatType CDouble)))) -> BaseType (FloatType (CLongDouble)), iit
150 | (Some _,_, Some _) ->
152 raise (Semantic ("signed, unsigned valid only for char and int", fake_pi))
153 | (_,Some _,(Some(BaseType(FloatType (CFloat|CLongDouble))))) ->
154 raise (Semantic ("long or short specified with floatint type", fake_pi))
155 | (_,Some Short,(Some(BaseType(FloatType CDouble)))) ->
156 raise (Semantic ("the only valid combination is long double", fake_pi))
158 | (_, Some _, Some _) ->
160 raise (Semantic ("long, short valid only for int or float", fake_pi))
162 (* if do short uint i, then gcc say parse error, strange ? it is
163 * not a parse error, it is just that we dont allow with typedef
164 * either short/long or signed/unsigned. In fact, with
165 * parse_typedef_fix2 (with et() and dt()) now I say too parse
166 * error so this code is executed only when do short struct
167 * {....} and never with a typedef cos now we parse short uint i
168 * as short ident ident => parse error (cos after first short i
169 * pass in dt() mode) *)
171 ,((st, inline),iist++iinl)
174 let fixDeclSpecForParam = function ({storageD = (st,iist)} as r) ->
175 let ((qu,ty) as v,_st) = fixDeclSpecForDecl r in
177 | (Sto Register) -> (v, true), iist
178 | NoSto -> (v, false), iist
181 (Semantic ("storage class specified for parameter of function",
184 let fixDeclSpecForFuncDef x =
185 let (returnType,storage) = fixDeclSpecForDecl x in
186 (match fst (unwrap storage) with
188 raise (Semantic ("function definition declared 'typedef'", fake_pi))
189 | x -> (returnType, storage)
192 (* parameter: (this is the context where we give parameter only when
193 * in func DEFINITION not in funct DECLARATION) We must have a name.
194 * This function ensure that we give only parameterTypeDecl with well
195 * formed Classic constructor todo?: do we accept other declaration
196 * in ? so I must add them to the compound of the deffunc. I dont
197 * have to handle typedef pb here cos C forbid to do VF f { ... }
198 * with VF a typedef of func cos here we dont see the name of the
199 * argument (in the typedef)
201 let (fixOldCDecl: fullType -> fullType) = fun ty ->
203 | ((FunctionType (fullt, (params, (b, iib)))),iifunc) ->
205 (* stdC: If the prototype declaration declares a parameter for a
206 * function that you are defining (it is part of a function
207 * definition), then you must write a name within the declarator.
208 * Otherwise, you can omit the name. *)
210 | [((reg, None, ((_qua, (BaseType Void,_)))),_), _] ->
213 (params +> List.iter (function
214 | (((b, None, _), ii1),ii2) ->
215 (* if majuscule, then certainly macro-parameter *)
216 pr2 ("SEMANTIC:parameter name omitted, but I continue");
221 (* todo? can we declare prototype in the decl or structdef,
222 ... => length <> but good kan meme *)
224 (* gcc say parse error but dont see why *)
225 raise (Semantic ("seems this is not a function", fake_pi))
228 let fixFunc = function
231 (nQ, (FunctionType (fullt, (params,bool)),iifunc)),
238 let iistart = Ast_c.fakeInfo () in
239 assert (nQ =*= nullQualif);
241 | [((reg, None, ((_qua, (BaseType Void,_)))),_), _] -> ()
243 params +> List.iter (function
244 | (((bool, Some s, fullt), _), _) -> ()
246 (* failwith "internal errror: fixOldCDecl not good" *)
248 (* it must be nullQualif,cos parser construct only this*)
250 f_type = (fullt, (params, bool));
255 ([iis]++iifunc++iicp++[iistart]++iist)
259 ("you are trying to do a function definition but you dont give " ^
260 "any parameter", fake_pi))
263 (*-------------------------------------------------------------------------- *)
264 (* parse_typedef_fix2 *)
265 (*-------------------------------------------------------------------------- *)
268 if !Flag_parsing_c.debug_etdt then pr2 ("<" ^ s);
269 LP.disable_typedef ()
272 if !Flag_parsing_c.debug_etdt then pr2 (">" ^ s);
276 let fix_add_params_ident = function
277 | ((s, (nQ, (FunctionType (fullt, (params, bool)),_)), st, _attrs)) ->
280 | [((reg, None, ((_qua, (BaseType Void,_)))),_), _] -> ()
282 params +> List.iter (function
283 | (((bool, Some s, fullt), _), _) ->
287 (* failwith "internal errror: fixOldCDecl not good" *)
291 (*-------------------------------------------------------------------------- *)
293 (*-------------------------------------------------------------------------- *)
295 let mk_e e ii = ((e, Ast_c.noType()), ii)
299 /*(*****************************************************************************)*/
301 /*(*************************************************************************)*/
305 * Some tokens are not even used in this file because they are filtered
306 * in some intermediate phase. But they still must be declared because
307 * ocamllex may generate them, or some intermediate phase may also
308 * generate them (like some functions in parsing_hacks.ml)
312 %token <Ast_c.info> TUnknown /*(* unrecognized token *)*/
314 /*(* coupling: Token_helpers.is_real_comment *)*/
315 %token <Ast_c.info> TCommentSpace TCommentNewline TComment
317 /*(*-----------------------------------------*)*/
318 /*(* the normal tokens *)*/
319 /*(*-----------------------------------------*)*/
321 %token <string * Ast_c.info> TInt
322 %token <(string * Ast_c.floatType) * Ast_c.info> TFloat
323 %token <(string * Ast_c.isWchar) * Ast_c.info> TChar
324 %token <(string * Ast_c.isWchar) * Ast_c.info> TString
326 %token <string * Ast_c.info> TIdent
327 /*(* appears mostly after some fix_xxx in parsing_hack *)*/
328 %token <string * Ast_c.info> TypedefIdent
332 (* Some tokens like TOPar and TCPar are used as synchronisation stuff,
333 * in parsing_hack.ml. So if define special tokens like TOParDefine and
334 * TCParEOL, then take care to also modify in Token_helpers.
338 %token <Ast_c.info> TOPar TCPar TOBrace TCBrace TOCro TCCro
339 %token <Ast_c.info> TDot TComma TPtrOp
340 %token <Ast_c.info> TInc TDec
341 %token <Ast_c.assignOp * Ast_c.info> TAssign
342 %token <Ast_c.info> TEq
343 %token <Ast_c.info> TWhy TTilde TBang
344 %token <Ast_c.info> TEllipsis
345 %token <Ast_c.info> TDotDot
347 %token <Ast_c.info> TPtVirg
349 TOrLog TAndLog TOr TXor TAnd TEqEq TNotEq TInf TSup TInfEq TSupEq
351 TPlus TMinus TMul TDiv TMod
354 Tchar Tshort Tint Tdouble Tfloat Tlong Tunsigned Tsigned Tvoid
355 Tauto Tregister Textern Tstatic
359 Tbreak Telse Tswitch Tcase Tcontinue Tfor Tdo Tif Twhile Treturn
367 /*(*-----------------------------------------*)*/
368 /*(* gccext: extra tokens *)*/
369 /*(*-----------------------------------------*)*/
370 %token <Ast_c.info> Tasm
371 %token <Ast_c.info> Tattribute
372 %token <Ast_c.info> Tinline
373 %token <Ast_c.info> Ttypeof
375 /*(*-----------------------------------------*)*/
376 /*(* cppext: extra tokens *)*/
377 /*(*-----------------------------------------*)*/
378 /*(* coupling with Token_helpers.is_cpp_token *)*/
381 /*(*---------------*)*/
383 /*(*---------------*)*/
385 %token <Ast_c.info> TDefine
386 %token <(string * Ast_c.info)> TDefParamVariadic
388 /*(* disappear after fix_tokens_define *)*/
389 %token <Ast_c.info> TCppEscapedNewline
391 /*(* appear after fix_tokens_define *)*/
392 %token <Ast_c.info> TOParDefine
393 %token <Ast_c.info> TOBraceDefineInit
395 %token <(string * Ast_c.info)> TIdentDefine /*(* same *)*/
396 %token <Ast_c.info> TDefEOL /*(* same *)*/
399 /*(*---------------*)*/
401 /*(*---------------*)*/
404 /*(* used only in lexer_c, then transformed in comment or splitted in tokens *)*/
405 %token <(string * string * bool ref * Ast_c.info)> TInclude
407 /*(* tokens coming from above, generated in parse_c from TInclude, etc *)*/
408 %token <(Ast_c.info * bool ref)> TIncludeStart
409 %token <(string * Ast_c.info)> TIncludeFilename
412 /*(*---------------*)*/
414 /*(*---------------*)*/
416 /*(* coupling: Token_helpers.is_cpp_instruction *)*/
417 %token <((int * int) option ref * Ast_c.info)>
418 TIfdef TIfdefelse TIfdefelif TEndif
419 %token <(bool * (int * int) option ref * Ast_c.info)>
420 TIfdefBool TIfdefMisc TIfdefVersion
422 /*(*---------------*)*/
424 /*(*---------------*)*/
427 %token <string * Ast_c.info> TUndef
429 %token <Ast_c.info> TCppDirectiveOther
431 /*(*---------------*)*/
433 /*(*---------------*)*/
435 /*(* appear after fix_tokens_cpp, cf also parsing_hacks#hint *)*/
437 %token <(string * Ast_c.info)> TMacroAttr
438 %token <(string * Ast_c.info)> TMacroStmt
439 /*(* no need value for the moment *)*/
440 %token <(string * Ast_c.info)> TMacroString
441 %token <(string * Ast_c.info)> TMacroDecl
442 %token <Ast_c.info> TMacroDeclConst
443 %token <(string * Ast_c.info)> TMacroStructDecl
444 %token <(string * Ast_c.info)> TMacroIterator
445 /*(* %token <(string * Ast_c.info)> TMacroTop *)*/
447 %token <(string * Ast_c.info)> TMacroAttrStorage
450 /*(*---------------*)*/
452 /*(*---------------*)*/
454 /*(* appear after parsing_hack *)*/
455 %token <Ast_c.info> TCParEOL
457 %token <Ast_c.info> TAction
460 %token <Ast_c.info> TCommentMisc
461 %token <(Ast_c.cppcommentkind * Ast_c.info)> TCommentCpp
464 /*(*-----------------------------------------*)*/
465 %token <Ast_c.info> EOF
467 /*(*-----------------------------------------*)*/
469 /*(* must be at the top so that it has the lowest priority *)*/
480 %left TInf TSup TInfEq TSupEq
485 /*(*************************************************************************)*/
486 /*(* Rules type declaration *)*/
487 /*(*************************************************************************)*/
489 %start main celem statement expr type_name
490 %type <Ast_c.program> main
491 %type <Ast_c.toplevel> celem
493 %type <Ast_c.statement> statement
494 %type <Ast_c.expression> expr
495 %type <Ast_c.fullType> type_name
498 /*(*************************************************************************)*/
501 * toplevel (obsolete)
507 * - left part (type_spec, qualif),
508 * - right part (declarator, abstract declarator)
509 * - aux part (parameters)
510 * declaration, storage, initializers
516 * generic workarounds (obrace, cbrace for context setting)
520 /*(*************************************************************************)*/
522 /*(*************************************************************************)*/
524 /*(*************************************************************************)*/
525 /*(* no more used; now that use error recovery *)*/
527 main: translation_unit EOF { $1 }
530 | external_declaration
531 { !LP._lexer_hint.context_stack <- [LP.InTopLevel]; [$1] }
532 | translation_unit external_declaration
533 { !LP._lexer_hint.context_stack <- [LP.InTopLevel]; $1 ++ [$2] }
537 /*(*************************************************************************)*/
539 /*(*************************************************************************)*/
541 /*(* Why this ? Why not s/ident/TIdent ? cos there is multiple namespaces in C,
542 * so a label can have the same name that a typedef, same for field and tags
543 * hence sometimes the use of ident instead of TIdent.
547 | TypedefIdent { $1 }
553 /*(*************************************************************************)*/
555 /*(*************************************************************************)*/
559 | expr TComma assign_expr { mk_e (Sequence ($1,$3)) [$2] }
561 /*(* bugfix: in C grammar they put unary_expr, but in fact it must be
562 * cast_expr, otherwise (int * ) xxx = &yy; is not allowed
566 | cast_expr TAssign assign_expr { mk_e(Assignment ($1,fst $2,$3)) [snd $2]}
567 | cast_expr TEq assign_expr { mk_e(Assignment ($1,SimpleAssign,$3)) [$2]}
569 /*(* gccext: allow optional then part hence gcc_opt_expr
570 * bugfix: in C grammar they put TDotDot cond_expr, but in fact it must be
571 * assign_expr, otherwise pnp ? x : x = 0x388 is not allowed
576 | arith_expr TWhy gcc_opt_expr TDotDot assign_expr
577 { mk_e (CondExpr ($1,$3,$5)) [$2;$4] }
582 | arith_expr TMul arith_expr { mk_e(Binary ($1, Arith Mul, $3)) [$2] }
583 | arith_expr TDiv arith_expr { mk_e(Binary ($1, Arith Div, $3)) [$2] }
584 | arith_expr TMod arith_expr { mk_e(Binary ($1, Arith Mod, $3)) [$2] }
585 | arith_expr TPlus arith_expr { mk_e(Binary ($1, Arith Plus, $3)) [$2] }
586 | arith_expr TMinus arith_expr { mk_e(Binary ($1, Arith Minus, $3)) [$2] }
587 | arith_expr TShl arith_expr { mk_e(Binary ($1, Arith DecLeft, $3)) [$2] }
588 | arith_expr TShr arith_expr { mk_e(Binary ($1, Arith DecRight, $3)) [$2] }
589 | arith_expr TInf arith_expr { mk_e(Binary ($1, Logical Inf, $3)) [$2] }
590 | arith_expr TSup arith_expr { mk_e(Binary ($1, Logical Sup, $3)) [$2] }
591 | arith_expr TInfEq arith_expr { mk_e(Binary ($1, Logical InfEq, $3)) [$2] }
592 | arith_expr TSupEq arith_expr { mk_e(Binary ($1, Logical SupEq, $3)) [$2] }
593 | arith_expr TEqEq arith_expr { mk_e(Binary ($1, Logical Eq, $3)) [$2] }
594 | arith_expr TNotEq arith_expr { mk_e(Binary ($1, Logical NotEq, $3)) [$2] }
595 | arith_expr TAnd arith_expr { mk_e(Binary ($1, Arith And, $3)) [$2] }
596 | arith_expr TOr arith_expr { mk_e(Binary ($1, Arith Or, $3)) [$2] }
597 | arith_expr TXor arith_expr { mk_e(Binary ($1, Arith Xor, $3)) [$2] }
598 | arith_expr TAndLog arith_expr { mk_e(Binary ($1, Logical AndLog, $3)) [$2] }
599 | arith_expr TOrLog arith_expr { mk_e(Binary ($1, Logical OrLog, $3)) [$2] }
603 | topar2 type_name tcpar2 cast_expr { mk_e(Cast ($2, $4)) [$1;$3] }
606 | postfix_expr { $1 }
607 | TInc unary_expr { mk_e(Infix ($2, Inc)) [$1] }
608 | TDec unary_expr { mk_e(Infix ($2, Dec)) [$1] }
609 | unary_op cast_expr { mk_e(Unary ($2, fst $1)) [snd $1] }
610 | Tsizeof unary_expr { mk_e(SizeOfExpr ($2)) [$1] }
611 | Tsizeof topar2 type_name tcpar2 { mk_e(SizeOfType ($3)) [$1;$2;$4] }
614 | TAnd { GetRef, $1 }
616 | TPlus { UnPlus, $1 }
617 | TMinus { UnMinus, $1 }
618 | TTilde { Tilde, $1 }
620 /*(* gccext: have that a lot in old kernel to get address of local label.
621 * cf gcc manual "local labels as values".
623 | TAndLog { GetRefLabel, $1 }
628 | primary_expr { $1 }
629 | postfix_expr TOCro expr TCCro
630 { mk_e(ArrayAccess ($1, $3)) [$2;$4] }
631 | postfix_expr TOPar argument_list_ne TCPar
632 { mk_e(FunCall ($1, $3)) [$2;$4] }
633 | postfix_expr TOPar TCPar { mk_e(FunCall ($1, [])) [$2;$3] }
634 | postfix_expr TDot ident { mk_e(RecordAccess ($1,fst $3)) [$2;snd $3] }
635 | postfix_expr TPtrOp ident { mk_e(RecordPtAccess ($1,fst $3)) [$2;snd $3] }
636 | postfix_expr TInc { mk_e(Postfix ($1, Inc)) [$2] }
637 | postfix_expr TDec { mk_e(Postfix ($1, Dec)) [$2] }
639 /*(* gccext: also called compound literals *)*/
640 | topar2 type_name tcpar2 TOBrace TCBrace
641 { mk_e(Constructor ($2, [])) [$1;$3;$4;$5] }
642 | topar2 type_name tcpar2 TOBrace initialize_list gcc_comma_opt TCBrace
643 { mk_e(Constructor ($2, List.rev $5)) ([$1;$3;$4;$7] ++ $6) }
646 | identifier { mk_e(Ident (fst $1)) [snd $1] }
647 | TInt { mk_e(Constant (Int (fst $1))) [snd $1] }
648 | TFloat { mk_e(Constant (Float (fst $1))) [snd $1] }
649 | TString { mk_e(Constant (String (fst $1))) [snd $1] }
650 | TChar { mk_e(Constant (Char (fst $1))) [snd $1] }
651 | TOPar expr TCPar { mk_e(ParenExpr ($2)) [$1;$3] } /*(* forunparser: *)*/
653 /*(* gccext: cppext: TODO better ast ? *)*/
654 | TMacroString { mk_e(Constant (MultiString)) [snd $1] }
655 | string_elem string_list { mk_e(Constant (MultiString)) ($1 ++ $2) }
657 /*(* gccext: allow statement as expressions via ({ statement }) *)*/
658 | TOPar compound TCPar { mk_e(StatementExpr ($2)) [$1;$3] }
662 /*(*----------------------------*)*/
664 /*(*----------------------------*)*/
667 /*(* to avoid conflicts have to introduce a _not_empty (ne) version *)*/
669 | assign_expr { Left $1 }
670 | parameter_decl { Right (ArgType $1) }
671 | action_higherordermacro_ne { Right (ArgAction $1) }
675 | assign_expr { Left $1 }
676 | parameter_decl { Right (ArgType $1) }
677 /*(* had conflicts before, but julia fixed them *)*/
678 | action_higherordermacro { Right (ArgAction $1) }
680 action_higherordermacro_ne:
683 then ActMisc [Ast_c.fakeInfo()]
688 action_higherordermacro:
691 then ActMisc [Ast_c.fakeInfo()]
696 /*(*----------------------------*)*/
697 /*(* workarounds *)*/
698 /*(*----------------------------*)*/
700 /*(* would like evalInt $1 but require too much info *)*/
701 const_expr: cond_expr { $1 }
704 topar2: TOPar { et "topar2" (); $1 }
705 tcpar2: TCPar { et "tcpar2" (); $1 (*TODO? et ? sure ? c pas dt plutot ? *) }
709 /*(*************************************************************************)*/
711 /*(*************************************************************************)*/
714 | labeled { Labeled (fst $1), snd $1 }
715 | compound { Compound (fst $1), snd $1 }
716 | expr_statement { ExprStatement(fst $1), snd $1 }
717 | selection { Selection (fst $1), snd $1 ++ [fakeInfo()] }
718 | iteration { Iteration (fst $1), snd $1 ++ [fakeInfo()] }
719 | jump TPtVirg { Jump (fst $1), snd $1 ++ [$2] }
722 | Tasm TOPar asmbody TCPar TPtVirg { Asm $3, [$1;$2;$4;$5] }
723 | Tasm Tvolatile TOPar asmbody TCPar TPtVirg { Asm $4, [$1;$2;$3;$5;$6] }
726 | TMacroStmt { MacroStmt, [snd $1] }
731 /*(* note that case 1: case 2: i++; would be correctly parsed, but with
732 * a Case (1, (Case (2, i++))) :(
735 | ident TDotDot statement { Label (fst $1, $3), [snd $1; $2] }
736 | Tcase const_expr TDotDot statement { Case ($2, $4), [$1; $3] }
737 | Tcase const_expr TEllipsis const_expr TDotDot statement
738 { CaseRange ($2, $4, $6), [$1;$3;$5] } /*(* gccext: allow range *)*/
739 | Tdefault TDotDot statement { Default $3, [$1; $2] }
742 /*(* gccext: allow toto: }
743 * was generating each 30 shift/Reduce conflicts,
744 * mais ca va, ca fait ce qu'il faut.
745 * update: julia fixed the problem by introducing end_labeled
746 * and modifying below stat_or_decl_list
749 { Label (fst $1, (ExprStatement None, [])), [snd $1; $2] }
750 | Tcase const_expr TDotDot { Case ($2, (ExprStatement None, [])), [$1;$3] }
751 | Tdefault TDotDot { Default (ExprStatement None, []), [$1; $2] }
757 compound: tobrace compound2 tcbrace { $2, [$1; $3] }
761 (* cppext: because of cpp, some stuff looks like declaration but are in
762 * fact statement but too hard to figure out, and if parse them as
763 * expression, then we force to have first decls and then exprs, then
764 * will have a parse error. So easier to let mix decl/statement.
765 * Moreover it helps to not make such a difference between decl and
766 * statement for further coccinelle phases to factorize code.
770 | stat_or_decl_list { $1 }
774 | stat_or_decl { [$1] }
775 /*(* gccext: to avoid conflicts, cf end_labeled above *)*/
776 | end_labeled { [StmtElem (Labeled (fst $1), snd $1)] }
777 /*(* old: conflicts | stat_or_decl_list stat_or_decl { $1 ++ [$2] } *)*/
778 | stat_or_decl stat_or_decl_list { $1 :: $2 }
781 | decl { StmtElem (Decl ($1 Ast_c.LocalDecl), []) }
782 | statement { StmtElem $1 }
785 | function_definition { StmtElem (NestedFunc $1, []) }
789 { CppDirectiveStmt $1 }
790 | cpp_ifdef_directive/*(* stat_or_decl_list ...*)*/
798 | TPtVirg { None, [$1] }
799 | expr TPtVirg { Some $1, [$2] }
802 | Tif TOPar expr TCPar statement %prec SHIFTHERE
803 { If ($3, $5, (ExprStatement None, [])), [$1;$2;$4] }
804 | Tif TOPar expr TCPar statement Telse statement
805 { If ($3, $5, $7), [$1;$2;$4;$6] }
806 | Tswitch TOPar expr TCPar statement
807 { Switch ($3,$5), [$1;$2;$4] }
810 | Twhile TOPar expr TCPar statement
811 { While ($3,$5), [$1;$2;$4] }
812 | Tdo statement Twhile TOPar expr TCPar TPtVirg
813 { DoWhile ($2,$5), [$1;$3;$4;$6;$7] }
814 | Tfor TOPar expr_statement expr_statement TCPar statement
815 { For ($3,$4,(None, []),$6), [$1;$2;$5]}
816 | Tfor TOPar expr_statement expr_statement expr TCPar statement
817 { For ($3,$4,(Some $5, []),$7), [$1;$2;$6] }
818 /*(* c++ext: for(int i = 0; i < n; i++)*)*/
819 | Tfor TOPar decl expr_statement expr_opt TCPar statement
821 (* pr2 "DECL in for"; *)
822 MacroIteration ("toto", [], $7),[] (* TODOfake ast, TODO need decl2 ? *)
825 | TMacroIterator TOPar argument_list_ne TCPar statement
826 { MacroIteration (fst $1, $3, $5), [snd $1;$2;$4] }
827 | TMacroIterator TOPar TCPar statement
828 { MacroIteration (fst $1, [], $4), [snd $1;$2;$3] }
830 /*(* the ';' in the caller grammar rule will be appended to the infos *)*/
832 | Tgoto ident { Goto (fst $2), [$1;snd $2] }
833 | Tcontinue { Continue, [$1] }
834 | Tbreak { Break, [$1] }
835 | Treturn { Return, [$1] }
836 | Treturn expr { ReturnExpr $2, [$1] }
837 | Tgoto TMul expr { GotoComputed $3, [$1;$2] }
841 /*(*----------------------------*)*/
843 /*(*----------------------------*)*/
845 | TString { [snd $1] }
846 /*(* cppext: ex= printk (KERN_INFO "xxx" UTS_RELEASE) *)*/
847 | TMacroString { [snd $1] }
851 | string_list colon_asm_list { $1, $2 }
852 | string_list { $1, [] } /*(* in old kernel *)*/
855 colon_asm: TDotDot colon_option_list { Colon $2, [$1] }
858 | TString { ColonMisc, [snd $1] }
859 | TString TOPar asm_expr TCPar { ColonExpr $3, [snd $1; $2;$4] }
860 /*(* cppext: certainly a macro *)*/
861 | TOCro identifier TCCro TString TOPar asm_expr TCPar
862 { ColonExpr $6, [$1;snd $2;$3;snd $4; $5; $7 ] }
863 | identifier { ColonMisc, [snd $1] }
864 | /*(* empty *)*/ { ColonMisc, [] }
866 asm_expr: assign_expr { $1 }
868 /*(*************************************************************************)*/
870 /*(*************************************************************************)*/
873 /*(*-----------------------------------------------------------------------*)*/
874 /*(* Type spec, left part of a type *)*/
875 /*(*-----------------------------------------------------------------------*)*/
877 | Tvoid { Right3 (BaseType Void), [$1] }
878 | Tchar { Right3 (BaseType (IntType CChar)), [$1]}
879 | Tint { Right3 (BaseType (IntType (Si (Signed,CInt)))), [$1]}
880 | Tfloat { Right3 (BaseType (FloatType CFloat)), [$1]}
881 | Tdouble { Right3 (BaseType (FloatType CDouble)), [$1] }
882 | Tshort { Middle3 Short, [$1]}
883 | Tlong { Middle3 Long, [$1]}
884 | Tsigned { Left3 Signed, [$1]}
885 | Tunsigned { Left3 UnSigned, [$1]}
886 | struct_or_union_spec { Right3 (fst $1), snd $1 }
887 | enum_spec { Right3 (fst $1), snd $1 }
890 (* parse_typedef_fix1: cant put: TIdent {} cos it make the grammar
891 * ambiguous, generates lots of conflicts => we must
892 * use some tricks: we make the lexer and parser cooperate, cf lexerParser.ml.
894 * parse_typedef_fix2: this is not enough, and you must use
895 * parse_typedef_fix2 to fully manage typedef problems in grammar.
897 * parse_typedef_fix3:
899 * parse_typedef_fix4: try also to do now some consistency checking in
902 | TypedefIdent { Right3 (TypeName (fst $1,Ast_c.noTypedefDef())), [snd $1]}
904 | Ttypeof TOPar assign_expr TCPar { Right3 (TypeOfExpr ($3)), [$1;$2;$4] }
905 | Ttypeof TOPar type_name TCPar { Right3 (TypeOfType ($3)), [$1;$2;$4] }
907 /*(*----------------------------*)*/
908 /*(* workarounds *)*/
909 /*(*----------------------------*)*/
911 type_spec: type_spec2 { dt "type" (); $1 }
913 /*(*-----------------------------------------------------------------------*)*/
915 /*(*-----------------------------------------------------------------------*)*/
918 | Tconst { {const=true ; volatile=false}, $1 }
919 | Tvolatile { {const=false ; volatile=true}, $1 }
921 | Trestrict { (* TODO *) {const=false ; volatile=false}, $1 }
924 /*(*-----------------------------------------------------------------------*)*/
925 /*(* gccext: attributes *)*/
926 /*(*-----------------------------------------------------------------------*)*/
929 | Tattribute TOPar /*stuff*/ TCPar { raise Todo }
931 | TMacroAttr { Attribute (fst $1), [snd $1] }
935 | TMacroAttrStorage { $1 }
939 | TMacroAttr { {const=false ; volatile=false}, snd $1 (*TODO*) }
941 /*(*-----------------------------------------------------------------------*)*/
942 /*(* Declarator, right part of a type + second part of decl (the ident) *)*/
943 /*(*-----------------------------------------------------------------------*)*/
946 (* declarator return a couple:
947 * (name, partial type (a function to be applied to return type))
949 * when int* f(int) we must return Func(Pointer int,int) and not
950 * Pointer (Func(int,int)
954 | pointer direct_d { (fst $2, fun x -> x +> $1 +> (snd $2) ) }
957 /*(* so must do int * const p; if the pointer is constant, not the pointee *)*/
959 | TMul { fun x ->(nQ, (Pointer x, [$1]))}
960 | TMul type_qualif_list { fun x ->($2.qualifD, (Pointer x, [$1]))}
961 | TMul pointer { fun x ->(nQ, (Pointer ($2 x),[$1]))}
962 | TMul type_qualif_list pointer { fun x ->($2.qualifD, (Pointer ($3 x),[$1]))}
968 | TOPar declarator TCPar /*(* forunparser: old: $2 *)*/
969 { (fst $2, fun x -> (nQ, (ParenType ((snd $2) x), [$1;$3]))) }
970 | direct_d tocro tccro
971 { (fst $1,fun x->(snd $1) (nQ,(Array (None,x), [$2;$3]))) }
972 | direct_d tocro const_expr tccro
973 { (fst $1,fun x->(snd $1) (nQ,(Array (Some $3,x), [$2;$4])))}
974 | direct_d topar tcpar
977 (nQ,(FunctionType (x,(([],(false, [])))),[$2;$3])))
979 | direct_d topar parameter_type_list tcpar
980 { (fst $1,fun x->(snd $1) (nQ,(FunctionType (x, $3), [$2;$4]))) }
983 /*(*----------------------------*)*/
984 /*(* workarounds *)*/
985 /*(*----------------------------*)*/
987 tocro: TOCro { et "tocro" ();$1 }
988 tccro: TCCro { dt "tccro" ();$1 }
990 /*(*-----------------------------------------------------------------------*)*/
993 | direct_abstract_declarator { $1 }
994 | pointer direct_abstract_declarator { fun x -> x +> $2 +> $1 }
996 direct_abstract_declarator:
997 | TOPar abstract_declarator TCPar /*(* forunparser: old: $2 *)*/
998 { (fun x -> (nQ, (ParenType ($2 x), [$1;$3]))) }
1001 { fun x -> (nQ, (Array (None, x), [$1;$2]))}
1002 | TOCro const_expr TCCro
1003 { fun x -> (nQ, (Array (Some $2, x), [$1;$3]))}
1004 | direct_abstract_declarator TOCro TCCro
1005 { fun x ->$1 (nQ, (Array (None, x), [$2;$3])) }
1006 | direct_abstract_declarator TOCro const_expr TCCro
1007 { fun x ->$1 (nQ, (Array (Some $3,x), [$2;$4])) }
1009 { fun x -> (nQ, (FunctionType (x, ([], (false, []))), [$1;$2])) }
1010 | TOPar parameter_type_list TCPar
1011 { fun x -> (nQ, (FunctionType (x, $2), [$1;$3]))}
1012 | direct_abstract_declarator TOPar TCPar
1013 { fun x ->$1 (nQ, (FunctionType (x, (([], (false, [])))),[$2;$3])) }
1014 | direct_abstract_declarator TOPar parameter_type_list TCPar
1015 { fun x -> $1 (nQ, (FunctionType (x, $3), [$2;$4])) }
1017 /*(*-----------------------------------------------------------------------*)*/
1018 /*(* Parameters (use decl_spec not type_spec just for 'register') *)*/
1019 /*(*-----------------------------------------------------------------------*)*/
1020 parameter_type_list:
1021 | parameter_list { ($1, (false, []))}
1022 | parameter_list TComma TEllipsis { ($1, (true, [$2;$3])) }
1026 | decl_spec declaratorp
1027 { let ((returnType,hasreg),iihasreg) = fixDeclSpecForParam $1
1029 (hasreg, Some (fst (fst $2)), ((snd $2) returnType)),
1030 (iihasreg ++ [snd (fst $2)])
1032 | decl_spec abstract_declaratorp
1033 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1
1034 in (hasreg, None, ($2 returnType)), (iihasreg ++ [])
1037 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1
1038 in (hasreg, None, returnType), (iihasreg ++ [])
1042 /*(*----------------------------*)*/
1043 /*(* workarounds *)*/
1044 /*(*----------------------------*)*/
1046 parameter_decl: parameter_decl2 { et "param" (); $1 }
1049 | declarator { LP.add_ident (fst (fst $1)); $1 }
1051 | attributes declarator { LP.add_ident (fst (fst $2)); $2 }
1052 | declarator attributes { LP.add_ident (fst (fst $1)); $1 }
1054 abstract_declaratorp:
1055 | abstract_declarator { $1 }
1057 | attributes abstract_declarator { $2 }
1059 /*(*-----------------------------------------------------------------------*)*/
1060 /*(* helper type rules *)*/
1061 /*(*-----------------------------------------------------------------------*)*/
1063 /*(* for struct and also typename *)*/
1064 /*(* cant put decl_spec cos no storage is allowed for field struct *)*/
1066 | type_spec { addTypeD ($1, nullDecl) }
1067 | type_qualif { {nullDecl with qualifD = (fst $1,[snd $1])}}
1068 | type_spec spec_qualif_list { addTypeD ($1,$2) }
1069 | type_qualif spec_qualif_list { addQualifD ($1,$2) }
1071 spec_qualif_list: spec_qualif_list2 { dt "spec_qualif" (); $1 }
1074 /*(* for pointers in direct_declarator and abstract_declarator *)*/
1076 | type_qualif_attr { {nullDecl with qualifD = (fst $1,[snd $1])} }
1077 | type_qualif_list type_qualif_attr { addQualifD ($2,$1) }
1084 /*(*-----------------------------------------------------------------------*)*/
1085 /*(* xxx_type_id *)*/
1086 /*(*-----------------------------------------------------------------------*)*/
1090 { let (returnType, _) = fixDeclSpecForDecl $1 in returnType }
1091 | spec_qualif_list abstract_declaratort
1092 { let (returnType, _) = fixDeclSpecForDecl $1 in $2 returnType }
1096 abstract_declaratort:
1097 | abstract_declarator { $1 }
1099 | attributes abstract_declarator { $2 }
1102 /*(*************************************************************************)*/
1103 /*(* declaration and initializers *)*/
1104 /*(*************************************************************************)*/
1109 let (returnType,storage) = fixDeclSpecForDecl $1 in
1110 let iistart = Ast_c.fakeInfo () in
1111 DeclList ([{v_namei = None; v_type = returnType;
1112 v_storage = unwrap storage; v_local = local;
1113 v_attr = Ast_c.noattr;
1115 ($2::iistart::snd storage))
1117 | decl_spec init_declarator_list TPtVirg
1119 let (returnType,storage) = fixDeclSpecForDecl $1 in
1120 let iistart = Ast_c.fakeInfo () in
1122 ($2 +> List.map (fun (((((s,iis),f),attrs), ini), iivirg) ->
1126 | Some (ini, iini) -> Some ini, [iini]
1128 if fst (unwrap storage) = StoTypedef
1129 then LP.add_typedef s;
1130 {v_namei = Some ((s, ini), iis::iini);
1131 v_type = f returnType;
1132 v_storage = unwrap storage;
1138 ), ($3::iistart::snd storage))
1142 | TMacroDecl TOPar argument_list TCPar TPtVirg
1144 MacroDecl ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]) }
1145 | Tstatic TMacroDecl TOPar argument_list TCPar TPtVirg
1147 MacroDecl ((fst $2, $4), [snd $2;$3;$5;$6;fakeInfo();$1]) }
1148 | Tstatic TMacroDeclConst TMacroDecl TOPar argument_list TCPar TPtVirg
1150 MacroDecl ((fst $3, $5), [snd $3;$4;$6;$7;fakeInfo();$1;$2])}
1153 /*(*-----------------------------------------------------------------------*)*/
1155 | storage_class_spec { {nullDecl with storageD = (fst $1, [snd $1]) } }
1156 | type_spec { addTypeD ($1,nullDecl) }
1157 | type_qualif { {nullDecl with qualifD = (fst $1, [snd $1]) } }
1158 | Tinline { {nullDecl with inlineD = (true, [$1]) } }
1159 | storage_class_spec decl_spec2 { addStorageD ($1, $2) }
1160 | type_spec decl_spec2 { addTypeD ($1, $2) }
1161 | type_qualif decl_spec2 { addQualifD ($1, $2) }
1162 | Tinline decl_spec2 { addInlineD ((true, $1), $2) }
1164 /*(* can simplify by putting all in _opt ? must have at least one otherwise
1165 * decl_list is ambiguous ? (no cos have ';' between decl)
1169 storage_class_spec2:
1170 | Tstatic { Sto Static, $1 }
1171 | Textern { Sto Extern, $1 }
1172 | Tauto { Sto Auto, $1 }
1173 | Tregister { Sto Register,$1 }
1174 | Ttypedef { StoTypedef, $1 }
1178 | storage_class_spec2 { $1 }
1179 | storage_class_spec2 attributes_storage { $1 (* TODO *) }
1183 /*(*----------------------------*)*/
1184 /*(* workarounds *)*/
1185 /*(*----------------------------*)*/
1187 decl: decl2 { et "decl" (); $1 }
1188 decl_spec: decl_spec2 { dt "declspec" (); $1 }
1190 /*(*-----------------------------------------------------------------------*)*/
1191 /*(* declarators (right part of type and variable) *)*/
1192 /*(*-----------------------------------------------------------------------*)*/
1194 | declaratori { ($1, None) }
1195 | declaratori teq initialize { ($1, Some ($3, $2)) }
1199 /*(*----------------------------*)*/
1200 /*(* workarounds *)*/
1201 /*(*----------------------------*)*/
1202 teq: TEq { et "teq" (); $1 }
1204 init_declarator: init_declarator2 { dt "init" (); $1 }
1207 /*(*----------------------------*)*/
1209 /*(*----------------------------*)*/
1212 | declarator { LP.add_ident (fst (fst $1)); $1, Ast_c.noattr }
1214 | declarator gcc_asm_decl { LP.add_ident (fst (fst $1)); $1, Ast_c.noattr }
1216 | attributes declarator { LP.add_ident (fst (fst $2)); $2, $1 }
1217 | declarator attributes { LP.add_ident (fst (fst $1)); $1, Ast_c.noattr (* TODO *) }
1222 | Tasm TOPar asmbody TCPar { }
1223 | Tasm Tvolatile TOPar asmbody TCPar { }
1226 /*(*-----------------------------------------------------------------------*)*/
1230 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
1231 { InitList (List.rev $2), [$1;$4]++$3 }
1232 | tobrace_ini tcbrace_ini
1233 { InitList [], [$1;$2] } /*(* gccext: *)*/
1237 (* opti: This time we use the weird order of non-terminal which requires in
1238 * the "caller" to do a List.rev cos quite critical. With this wierd order it
1239 * allows yacc to use a constant stack space instead of exploding if we would
1240 * do a 'initialize2 Tcomma initialize_list'.
1244 | initialize2 { [$1, []] }
1245 | initialize_list TComma initialize2 { ($3, [$2])::$1 }
1248 /*(* gccext: condexpr and no assign_expr cos can have ambiguity with comma *)*/
1252 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
1253 { InitList (List.rev $2), [$1;$4]++$3 }
1254 | tobrace_ini tcbrace_ini
1255 { InitList [], [$1;$2] }
1257 /*(* gccext: labeled elements, a.k.a designators *)*/
1258 | designator_list TEq initialize2
1259 { InitDesignators ($1, $3), [$2] }
1261 /*(* gccext: old format *)*/
1262 | ident TDotDot initialize2
1263 { InitFieldOld (fst $1, $3), [snd $1; $2] } /*(* in old kernel *)*/
1265 | TOCro const_expr TCCro initialize2
1266 { InitIndexOld ($2, $4), [$1;$3] }
1271 /*(* they can be nested, can have a .x.[3].y *)*/
1274 { DesignatorField (fst $2), [$1;snd $2] }
1275 | TOCro const_expr TCCro
1276 { DesignatorIndex ($2), [$1;$3] }
1277 | TOCro const_expr TEllipsis const_expr TCCro
1278 { DesignatorRange ($2, $4), [$1;$3;$5] }
1281 /*(*----------------------------*)*/
1282 /*(* workarounds *)*/
1283 /*(*----------------------------*)*/
1285 gcc_comma_opt_struct:
1287 | /*(* empty *)*/ { [Ast_c.fakeInfo() +> Ast_c.rewrap_str ","] }
1296 /*(*************************************************************************)*/
1298 /*(*************************************************************************)*/
1301 | struct_or_union ident tobrace_struct struct_decl_list_gcc tcbrace_struct
1302 { StructUnion (fst $1, Some (fst $2), $4), [snd $1;snd $2;$3;$5] }
1303 | struct_or_union tobrace_struct struct_decl_list_gcc tcbrace_struct
1304 { StructUnion (fst $1, None, $3), [snd $1;$2;$4] }
1305 | struct_or_union ident
1306 { StructUnionName (fst $1, fst $2), [snd $1;snd $2] }
1309 | Tstruct { Struct, $1 }
1310 | Tunion { Union, $1 }
1312 | Tstruct attributes { Struct, $1 (* TODO *) }
1313 | Tunion attributes { Union, $1 (* TODO *) }
1318 | field_declaration { DeclarationField $1, noii }
1319 | TPtVirg { EmptyField, [$1] }
1320 | TMacroStructDecl { MacroStructDeclTodo, [] }
1324 { CppDirectiveStruct $1, noii }
1325 | cpp_ifdef_directive/*(* struct_decl_list ... *)*/
1326 { IfdefStruct $1, noii }
1330 | spec_qualif_list struct_declarator_list TPtVirg
1332 let (returnType,storage) = fixDeclSpecForDecl $1 in
1333 if fst (unwrap storage) <> NoSto
1334 then internal_error "parsing dont allow this";
1336 FieldDeclList ($2 +> (List.map (fun (f, iivirg) ->
1337 f returnType, iivirg))
1339 (* dont need to check if typedef or func initialised cos
1340 * grammar dont allow typedef nor initialiser in struct
1344 | spec_qualif_list TPtVirg
1346 (* gccext: allow empty elements if it is a structdef or enumdef *)
1347 let (returnType,storage) = fixDeclSpecForDecl $1 in
1348 if fst (unwrap storage) <> NoSto
1349 then internal_error "parsing dont allow this";
1351 FieldDeclList ([(Simple (None, returnType), []) , []], [$2])
1360 { (fun x -> Simple (Some (fst (fst $1)), (snd $1) x), [snd (fst $1)]) }
1361 | dotdot const_expr2
1362 { (fun x -> BitField (None, x, $2), [$1]) }
1363 | declaratorsd dotdot const_expr2
1364 { (fun x -> BitField (Some (fst(fst $1)),
1371 /*(*----------------------------*)*/
1372 /*(* workarounds *)*/
1373 /*(*----------------------------*)*/
1375 | declarator { (*also ? LP.add_ident (fst (fst $1)); *) $1 }
1377 | attributes declarator { $2 }
1378 | declarator attributes { $1 }
1383 struct_or_union_spec: s_or_u_spec2 { dt "su" (); $1 }
1384 struct_or_union: struct_or_union2 { et "su" (); $1 }
1385 struct_decl: struct_decl2 { et "struct" (); $1 }
1387 dotdot: TDotDot { et "dotdot" (); $1 }
1388 const_expr2: const_expr { dt "const_expr2" (); $1 }
1390 struct_decl_list_gcc:
1391 | struct_decl_list { $1 }
1392 | /*(* empty *)*/ { [] } /*(* gccext: allow empty struct *)*/
1395 /*(*************************************************************************)*/
1397 /*(*************************************************************************)*/
1399 | Tenum tobrace_enum enumerator_list gcc_comma_opt tcbrace_enum
1400 { Enum (None, $3), [$1;$2;$5] ++ $4 }
1401 | Tenum ident tobrace_enum enumerator_list gcc_comma_opt tcbrace_enum
1402 { Enum (Some (fst $2), $4), [$1; snd $2; $3;$6] ++ $5 }
1404 { EnumName (fst $2), [$1; snd $2] }
1407 | idente { (fst $1, None), [snd $1] }
1408 | idente TEq const_expr { (fst $1, Some $3), [snd $1; $2] }
1412 /*(*----------------------------*)*/
1413 /*(* workarounds *)*/
1414 /*(*----------------------------*)*/
1416 idente: ident { LP.add_ident (fst $1); $1 }
1420 /*(*************************************************************************)*/
1422 /*(*************************************************************************)*/
1423 function_definition: function_def { fixFunc $1 }
1427 | decl_list decl { $1 ++ [$2] }
1430 | start_fun compound { LP.del_scope(); ($1, $2) }
1431 | start_fun decl_list compound {
1432 pr2 "OLD STYLE DECL NOT WELL SUPPORTED";
1433 (* TODO: undo the typedef added ? *)
1438 start_fun: start_fun2
1440 fix_add_params_ident $1;
1441 (* toreput? !LP._lexer_hint.toplevel <- false; *)
1445 start_fun2: decl_spec declaratorfd
1446 { let (returnType,storage) = fixDeclSpecForFuncDef $1 in
1447 let (id, attrs) = $2 in
1448 (fst id, fixOldCDecl ((snd id) returnType) , storage, attrs)
1451 /*(*----------------------------*)*/
1452 /*(* workarounds *)*/
1453 /*(*----------------------------*)*/
1456 | declarator { et "declaratorfd" (); $1, Ast_c.noattr }
1458 | attributes declarator { et "declaratorfd" (); $2, $1 }
1459 | declarator attributes { et "declaratorfd" (); $1, Ast_c.noattr }
1463 /*(*************************************************************************)*/
1464 /*(* cpp directives *)*/
1465 /*(*************************************************************************)*/
1468 | TIncludeStart TIncludeFilename
1470 let (i1, in_ifdef) = $1 in
1473 (* redo some lexing work :( *)
1476 | _ when s =~ "^\"\\(.*\\)\"$" ->
1477 Local (Common.split "/" (matched1 s))
1478 | _ when s =~ "^\\<\\(.*\\)\\>$" ->
1479 NonLocal (Common.split "/" (matched1 s))
1483 Include { i_include = (inc_file, [i1;i2]);
1484 i_rel_pos = Ast_c.noRelPos();
1485 i_is_in_ifdef = !in_ifdef;
1486 i_content = Ast_c.noi_content;
1490 | TDefine TIdentDefine define_val TDefEOL
1491 { Define ((fst $2, [$1; snd $2;$4]), (DefineVar, $3)) }
1494 (* The TOParDefine is introduced to avoid ambiguity with previous rules.
1495 * A TOParDefine is a TOPar that was just next to the ident.
1497 | TDefine TIdentDefine TOParDefine param_define_list TCPar define_val TDefEOL
1499 ((fst $2, [$1; snd $2;$7]),
1500 (DefineFunc ($4, [$3;$5]), $6))
1503 | TUndef { Undef (fst $1, [snd $1]) }
1504 | TCppDirectiveOther { PragmaAndCo ([$1]) }
1506 /*(* perhaps better to use assign_expr ? but in that case need
1507 * do a assign_expr_of_string in parse_c
1510 | expr { DefineExpr $1 }
1511 | statement { DefineStmt $1 }
1512 | decl { DefineStmt (Decl ($1 Ast_c.NotLocalDecl), []) }
1514 /*(*old: | TypedefIdent { DefineType (nQ,(TypeName(fst $1,noTypedefDef()),[snd $1]))}*)*/
1515 | spec_qualif_list { DefineTodo }
1516 | function_definition { DefineFunction $1 }
1518 | TOBraceDefineInit initialize_list gcc_comma_opt_struct TCBrace comma_opt
1519 { DefineInit (InitList (List.rev $2), [$1;$4]++$3++$5) }
1521 /*(* note: had a conflict before when were putting TInt instead of expr *)*/
1522 | Tdo statement Twhile TOPar expr TCPar
1526 then pr2 "WIERD: in macro and have not a while(0)";
1528 DefineDoWhileZero (($2,$5), [$1;$3;$4;$6])
1531 /*(* a few special cases *)*/
1532 | stat_or_decl stat_or_decl_list { DefineTodo }
1534 | statement statement { DefineTodo }
1535 | decl function_definition { DefineTodo }
1538 | Tasm TOPar asmbody TCPar { DefineTodo }
1539 | Tasm Tvolatile TOPar asmbody TCPar { DefineTodo }
1542 /*(* aliases macro *)*/
1543 | TMacroAttr { DefineTodo }
1544 | storage_class_spec { DefineTodo }
1545 | Tinline { DefineTodo }
1547 | /*(* empty *)*/ { DefineEmpty }
1551 | TIdent { fst $1, [snd $1] }
1552 | TypedefIdent { fst $1, [snd $1] }
1553 | TDefParamVariadic { fst $1, [snd $1] }
1554 | TEllipsis { "...", [$1] }
1555 /*(* they reuse keywords :( *)*/
1556 | Tregister { "register", [$1] }
1561 cpp_ifdef_directive:
1563 { let (tag,ii) = $1 in
1564 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1566 { let (tag,ii) = $1 in
1567 IfdefDirective ((IfdefElse, IfdefTag (Common.some !tag)), [ii]) }
1569 { let (tag,ii) = $1 in
1570 IfdefDirective ((IfdefElseif, IfdefTag (Common.some !tag)), [ii]) }
1572 { let (tag,ii) = $1 in
1573 IfdefDirective ((IfdefEndif, IfdefTag (Common.some !tag)), [ii]) }
1576 { let (_b, tag,ii) = $1 in
1577 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1579 { let (_b, tag,ii) = $1 in
1580 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1582 { let (_b, tag,ii) = $1 in
1583 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1588 /*(* no conflict ? no need for a TMacroTop ? apparently not as at toplevel
1589 * the rule are slightly different, they cant be statement and so expr
1590 * at the top, only decl or function definition.
1592 | identifier TOPar argument_list TCPar TPtVirg
1593 { MacroTop (fst $1, $3, [snd $1;$2;$4;$5]) }
1595 /*(* TCParEOL to fix the end-of-stream bug of ocamlyacc *)*/
1596 | identifier TOPar argument_list TCParEOL
1597 { MacroTop (fst $1, $3, [snd $1;$2;$4;fakeInfo()]) }
1599 /*(* ex: EXPORT_NO_SYMBOLS; *)*/
1600 | identifier TPtVirg { EmptyDef [snd $1;$2] }
1604 /*(*************************************************************************)*/
1606 /*(*************************************************************************)*/
1608 external_declaration:
1609 | function_definition { Definition $1 }
1610 | decl { Declaration ($1 Ast_c.NotLocalDecl) }
1614 | external_declaration { $1 }
1621 | cpp_ifdef_directive /* (*external_declaration_list ...*)*/
1624 /*(* can have asm declaration at toplevel *)*/
1625 | Tasm TOPar asmbody TCPar TPtVirg { EmptyDef [$1;$2;$4;$5] }
1628 (* in ~/kernels/src/linux-2.5.2/drivers/isdn/hisax/isdnl3.c sometimes
1629 * the function ends with }; instead of just }
1630 * can also remove this rule and report "parse error" pb to morton
1632 | TPtVirg { EmptyDef [$1] }
1635 | EOF { FinalDef $1 }
1640 /*(*************************************************************************)*/
1641 /*(* some generic workarounds *)*/
1642 /*(*************************************************************************)*/
1644 tobrace: TOBrace { LP.push_context LP.InFunction; LP.new_scope (); $1 }
1645 tcbrace: TCBrace { LP.pop_context(); LP.del_scope (); $1 }
1647 tobrace_enum: TOBrace { LP.push_context LP.InEnum; $1 }
1648 tcbrace_enum: TCBrace { LP.pop_context (); $1 }
1650 tobrace_ini: TOBrace { LP.push_context LP.InInitializer; $1 }
1651 tcbrace_ini: TCBrace { LP.pop_context (); $1 }
1653 tobrace_struct: TOBrace { LP.push_context LP.InStruct; $1}
1654 tcbrace_struct: TCBrace { LP.pop_context (); $1 }
1660 { LP.new_scope ();et "topar" ();
1661 LP.push_context LP.InParameter;
1665 { LP.del_scope ();dt "tcpar" ();
1673 /*(*************************************************************************)*/
1674 /*(* xxx_list, xxx_opt *)*/
1675 /*(*************************************************************************)*/
1681 | statement_list { ([], $1) }
1682 | decl_list { ($1, []) }
1683 | decl_list statement_list { ($1,$2) }
1685 statement_list: stat_or_decl_list { $1 }
1692 | decl_list decl { $1 ++ [$2] }
1695 | statement { [$1] }
1696 | statement_list statement { $1 ++ [$2] }
1704 | string_elem { $1 }
1705 | string_list string_elem { $1 ++ $2 }
1708 | colon_asm { [$1] }
1709 | colon_asm_list colon_asm { $1 ++ [$2] }
1712 | colon_option { [$1, []] }
1713 | colon_option_list TComma colon_option { $1 ++ [$3, [$2]] }
1717 | argument_ne { [$1, []] }
1718 | argument_list_ne TComma argument { $1 ++ [$3, [$2]] }
1721 | argument { [$1, []] }
1722 | argument_list TComma argument { $1 ++ [$3, [$2]] }
1726 | assign_expr { [$1, []] }
1727 | expression_list TComma assign_expr { $1 ++ [$3, [$2]] }
1732 | struct_decl { [$1] }
1733 | struct_decl_list struct_decl { $1 ++ [$2] }
1736 struct_declarator_list:
1737 | struct_declarator { [$1, []] }
1738 | struct_declarator_list TComma struct_declarator { $1 ++ [$3, [$2]] }
1742 | enumerator { [$1, []] }
1743 | enumerator_list TComma enumerator { $1 ++ [$3, [$2]] }
1746 init_declarator_list:
1747 | init_declarator { [$1, []] }
1748 | init_declarator_list TComma init_declarator { $1 ++ [$3, [$2]] }
1752 | parameter_decl { [$1, []] }
1753 | parameter_list TComma parameter_decl { $1 ++ [$3, [$2]] }
1757 | TAction taction_list_ne { $1 :: $2 }
1760 /*old: was generating conflict, hence now taction_list_ne
1761 | (* empty *) { [] }
1763 | taction_list TAction { $1 ++ [$2] }
1766 | TAction taction_list { $1 :: $2 }
1769 | /*(* empty *)*/ { [] }
1770 | param_define { [$1, []] }
1771 | param_define_list TComma param_define { $1 ++ [$3, [$2]] }
1774 | designator { [$1] }
1775 | designator_list designator { $1 ++ [$2] }
1778 | attribute { [$1] }
1779 | attribute_list attribute { $1 ++ [$2] }
1781 attribute_storage_list:
1782 | attribute_storage { [$1] }
1783 | attribute_storage_list attribute_storage { $1 ++ [$2] }
1786 attributes: attribute_list { $1 }
1788 attributes_storage: attribute_storage_list { $1 }
1791 /*(* gccext: which allow a trailing ',' in enum, as in perl *)*/
1794 | /*(* empty *)*/ { [] }
1798 | /*(* empty *)*/ { [] }
1808 | /*(* empty *)*/ { None }
1819 | /*(* empty *)*/ { None }