Release coccinelle-0.2.5-rc2
[bpt/coccinelle.git] / parsing_c / parser_c.mly
1 %{
2 (* Yoann Padioleau
3 *
4 * Copyright (C) 2002, 2006, 2007, 2008, 2009 Yoann Padioleau
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License (GPL)
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * file license.txt for more details.
14 *)
15 open Common
16
17 open Ast_c
18
19 module LP = Lexer_parser
20 open Lexer_parser (* for the fields *)
21
22 open Semantic_c (* Semantic exn *)
23
24
25 (*****************************************************************************)
26 (* Wrappers *)
27 (*****************************************************************************)
28 let warning s v =
29 if !Flag_parsing_c.verbose_parsing
30 then Common.warning ("PARSING: " ^ s) v
31 else v
32
33 let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_parsing
34
35 (*****************************************************************************)
36 (* Parse helpers functions *)
37 (*****************************************************************************)
38
39 (*-------------------------------------------------------------------------- *)
40 (* Type related *)
41 (*-------------------------------------------------------------------------- *)
42
43 type shortLong = Short | Long | LongLong
44
45 type decl = {
46 storageD: storagebis wrap;
47 typeD: ((sign option) * (shortLong option) * (typeCbis option)) wrap;
48 qualifD: typeQualifierbis wrap;
49 inlineD: bool wrap;
50 (* note: have a full_info: parse_info list; to remember ordering
51 * between storage, qualifier, type ? well this info is already in
52 * the Ast_c.info, just have to sort them to get good order *)
53 }
54
55 let nullDecl = {
56 storageD = NoSto, [];
57 typeD = (None, None, None), [];
58 qualifD = nullQualif;
59 inlineD = false, [];
60 }
61 let fake_pi = Common.fake_parse_info
62
63 let addStorageD = function
64 | ((x,ii), ({storageD = (NoSto,[])} as v)) -> { v with storageD = (x, [ii]) }
65 | ((x,ii), ({storageD = (y, ii2)} as v)) ->
66 if x =*= y then warning "duplicate storage classes" v
67 else raise (Semantic ("multiple storage classes", fake_pi))
68
69 let addInlineD = function
70 | ((true,ii), ({inlineD = (false,[])} as v)) -> { v with inlineD=(true,[ii])}
71 | ((true,ii), ({inlineD = (true, ii2)} as v)) -> warning "duplicate inline" v
72 | _ -> raise Impossible
73
74
75 let addTypeD = function
76 | ((Left3 Signed,ii) ,({typeD = ((Some Signed, b,c),ii2)} as v)) ->
77 warning "duplicate 'signed'" v
78 | ((Left3 UnSigned,ii) ,({typeD = ((Some UnSigned,b,c),ii2)} as v)) ->
79 warning "duplicate 'unsigned'" v
80 | ((Left3 _,ii), ({typeD = ((Some _,b,c),ii2)} as _v)) ->
81 raise (Semantic ("both signed and unsigned specified", fake_pi))
82 | ((Left3 x,ii), ({typeD = ((None,b,c),ii2)} as v)) ->
83 {v with typeD = (Some x,b,c),ii ++ ii2}
84
85 | ((Middle3 Short,ii), ({typeD = ((a,Some Short,c),ii2)} as v)) ->
86 warning "duplicate 'short'" v
87
88
89 (* gccext: long long allowed *)
90 | ((Middle3 Long,ii), ({typeD = ((a,Some Long ,c),ii2)} as v)) ->
91 { v with typeD = (a, Some LongLong, c),ii++ii2 }
92 | ((Middle3 Long,ii), ({typeD = ((a,Some LongLong ,c),ii2)} as v)) ->
93 warning "triplicate 'long'" v
94
95
96 | ((Middle3 _,ii), ({typeD = ((a,Some _,c),ii2)} as _v)) ->
97 raise (Semantic ("both long and short specified", fake_pi))
98 | ((Middle3 x,ii), ({typeD = ((a,None,c),ii2)} as v)) ->
99 {v with typeD = (a, Some x,c),ii++ii2}
100
101 | ((Right3 t,ii), ({typeD = ((a,b,Some _),ii2)} as _v)) ->
102 raise (Semantic ("two or more data types", fake_pi))
103 | ((Right3 t,ii), ({typeD = ((a,b,None),ii2)} as v)) ->
104 {v with typeD = (a,b, Some t),ii++ii2}
105
106
107 let addQualif = function
108 | ({const=true}, ({const=true} as x)) -> warning "duplicate 'const'" x
109 | ({volatile=true},({volatile=true} as x))-> warning "duplicate 'volatile'" x
110 | ({const=true}, v) -> {v with const=true}
111 | ({volatile=true}, v) -> {v with volatile=true}
112 | _ ->
113 internal_error "there is no noconst or novolatile keyword"
114
115 let addQualifD ((qu,ii), ({qualifD = (v,ii2)} as x)) =
116 { x with qualifD = (addQualif (qu, v),ii::ii2) }
117
118
119 (*-------------------------------------------------------------------------- *)
120 (* Declaration/Function related *)
121 (*-------------------------------------------------------------------------- *)
122
123
124 (* stdC: type section, basic integer types (and ritchie)
125 * To understand the code, just look at the result (right part of the PM)
126 * and go back.
127 *)
128 let (fixDeclSpecForDecl: decl -> (fullType * (storage wrap))) = function
129 {storageD = (st,iist);
130 qualifD = (qu,iiq);
131 typeD = (ty,iit);
132 inlineD = (inline,iinl);
133 } ->
134 let ty',iit' =
135 (match ty with
136 | (None,None,None) ->
137 (* generate fake_info, otherwise type_annotater can crash in
138 * offset.
139 *)
140 warning "type defaults to 'int'" (defaultInt, [fakeInfo fake_pi])
141 | (None, None, Some t) -> (t, iit)
142
143 | (Some sign, None, (None| Some (BaseType (IntType (Si (_,CInt)))))) ->
144 BaseType(IntType (Si (sign, CInt))), iit
145 | ((None|Some Signed),Some x,(None|Some(BaseType(IntType (Si (_,CInt)))))) ->
146 BaseType(IntType (Si (Signed, [Short,CShort; Long, CLong; LongLong, CLongLong] +> List.assoc x))), iit
147 | (Some UnSigned, Some x, (None| Some (BaseType (IntType (Si (_,CInt))))))->
148 BaseType(IntType (Si (UnSigned, [Short,CShort; Long, CLong; LongLong, CLongLong] +> List.assoc x))), iit
149 | (Some sign, None, (Some (BaseType (IntType CChar)))) ->
150 BaseType(IntType (Si (sign, CChar2))), iit
151 | (None, Some Long,(Some(BaseType(FloatType CDouble)))) ->
152 BaseType (FloatType (CLongDouble)), iit
153
154 | (Some _,_, Some _) ->
155 (*mine*)
156 raise (Semantic ("signed, unsigned valid only for char and int", fake_pi))
157 | (_,Some _,(Some(BaseType(FloatType (CFloat|CLongDouble))))) ->
158 raise (Semantic ("long or short specified with floatint type", fake_pi))
159 | (_,Some Short,(Some(BaseType(FloatType CDouble)))) ->
160 raise (Semantic ("the only valid combination is long double", fake_pi))
161
162 | (_, Some _, Some _) ->
163 (* mine *)
164 raise (Semantic ("long, short valid only for int or float", fake_pi))
165
166 (* if do short uint i, then gcc say parse error, strange ? it is
167 * not a parse error, it is just that we dont allow with typedef
168 * either short/long or signed/unsigned. In fact, with
169 * parse_typedef_fix2 (with et() and dt()) now I say too parse
170 * error so this code is executed only when do short struct
171 * {....} and never with a typedef cos now we parse short uint i
172 * as short ident ident => parse error (cos after first short i
173 * pass in dt() mode) *)
174
175 )
176 in
177 ((qu, iiq),
178 (ty', iit'))
179 ,((st, inline),iist++iinl)
180
181
182 let fixDeclSpecForParam = function ({storageD = (st,iist)} as r) ->
183 let ((qu,ty) as v,_st) = fixDeclSpecForDecl r in
184 match st with
185 | (Sto Register) -> (v, true), iist
186 | NoSto -> (v, false), iist
187 | _ ->
188 raise
189 (Semantic ("storage class specified for parameter of function",
190 fake_pi))
191
192 let fixDeclSpecForMacro = function ({storageD = (st,iist)} as r) ->
193 let ((qu,ty) as v,_st) = fixDeclSpecForDecl r in
194 match st with
195 | NoSto -> v
196 | _ ->
197 raise
198 (Semantic ("storage class specified for macro type decl",
199 fake_pi))
200
201
202 let fixDeclSpecForFuncDef x =
203 let (returnType,storage) = fixDeclSpecForDecl x in
204 (match fst (unwrap storage) with
205 | StoTypedef ->
206 raise (Semantic ("function definition declared 'typedef'", fake_pi))
207 | _ -> (returnType, storage)
208 )
209
210
211 (* parameter: (this is the context where we give parameter only when
212 * in func DEFINITION not in funct DECLARATION) We must have a name.
213 * This function ensure that we give only parameterTypeDecl with well
214 * formed Classic constructor todo?: do we accept other declaration
215 * in ? so I must add them to the compound of the deffunc. I dont
216 * have to handle typedef pb here cos C forbid to do VF f { ... }
217 * with VF a typedef of func cos here we dont see the name of the
218 * argument (in the typedef)
219 *)
220 let (fixOldCDecl: fullType -> fullType) = fun ty ->
221 match Ast_c.unwrap_typeC ty with
222 | FunctionType (fullt, (params, (b, iib))) ->
223
224 (* stdC: If the prototype declaration declares a parameter for a
225 * function that you are defining (it is part of a function
226 * definition), then you must write a name within the declarator.
227 * Otherwise, you can omit the name. *)
228 (match params with
229 | [{p_namei = None; p_type = ty2},_] ->
230 (match Ast_c.unwrap_typeC ty2 with
231 | BaseType Void ->
232 ty
233 | _ ->
234 pr2 ("SEMANTIC:parameter name omitted, but I continue");
235 ty
236 )
237
238 | params ->
239 (params +> List.iter (fun (param,_) ->
240 match param with
241 | {p_namei = None} ->
242 (* if majuscule, then certainly macro-parameter *)
243 pr2 ("SEMANTIC:parameter name omitted, but I continue");
244 | _ -> ()
245 ));
246 ty
247 )
248
249 (* todo? can we declare prototype in the decl or structdef,
250 ... => length <> but good kan meme *)
251 | _ ->
252 (* gcc say parse error but dont see why *)
253 raise (Semantic ("seems this is not a function", fake_pi))
254
255
256 let fixFunc (typ, compound, old_style_opt) =
257 let (cp,iicp) = compound in
258
259 let (name, ty, (st,iist), attrs) = typ in
260
261 let (qu, tybis) = ty in
262
263 match Ast_c.unwrap_typeC ty with
264 | FunctionType (fullt, (params,abool)) ->
265 let iifunc = Ast_c.get_ii_typeC_take_care tybis in
266
267 let iistart = Ast_c.fakeInfo () in
268 assert (qu =*= nullQualif);
269
270 (match params with
271 | [{p_namei= None; p_type = ty2}, _] ->
272 (match Ast_c.unwrap_typeC ty2 with
273 | BaseType Void -> ()
274 | _ ->
275 (* failwith "internal errror: fixOldCDecl not good" *)
276 ()
277 )
278 | params ->
279 params +> List.iter (function
280 | ({p_namei = Some s}, _) -> ()
281 | _ -> ()
282 (* failwith "internal errror: fixOldCDecl not good" *)
283 )
284 );
285 (* bugfix: cf tests_c/function_pointer4.c.
286 * Apparemment en C on peut syntaxiquement ecrire ca:
287 *
288 * void a(int)(int x);
289 * mais apres gcc gueule au niveau semantique avec:
290 * xxx.c:1: error: 'a' declared as function returning a function
291 * Je ne faisais pas cette verif. Sur du code comme
292 * void METH(foo)(int x) { ...} , le parser croit (a tort) que foo
293 * est un typedef, et donc c'est parsé comme l'exemple precedent,
294 * ce qui ensuite confuse l'unparser qui n'est pas habitué
295 * a avoir dans le returnType un FunctionType et qui donc
296 * pr_elem les ii dans le mauvais sens ce qui genere au final
297 * une exception. Hence this fix to at least detect the error
298 * at parsing time (not unparsing time).
299 *)
300 (match Ast_c.unwrap_typeC fullt with
301 | FunctionType _ ->
302 let s = Ast_c.str_of_name name in
303 let iis = Ast_c.info_of_name name in
304 pr2 (spf "WEIRD: %s declared as function returning a function." s);
305 pr2 (spf "This is probably because of a macro. Extend standard.h");
306 raise (Semantic (spf "error: %s " s, Ast_c.parse_info_of_info iis))
307 | _ -> ()
308 );
309
310 (* it must be nullQualif,cos parser construct only this*)
311 {f_name = name;
312 f_type = (fullt, (params, abool));
313 f_storage = st;
314 f_body = cp;
315 f_attr = attrs;
316 f_old_c_style = old_style_opt;
317 },
318 (iifunc++iicp++[iistart]++iist)
319 | _ ->
320 raise
321 (Semantic
322 ("you are trying to do a function definition but you dont give " ^
323 "any parameter", fake_pi))
324
325
326 (*-------------------------------------------------------------------------- *)
327 (* parse_typedef_fix2 *)
328 (*-------------------------------------------------------------------------- *)
329
330 let dt s () =
331 if !Flag_parsing_c.debug_etdt then pr2 ("<" ^ s);
332 LP.disable_typedef ()
333
334 let et s () =
335 if !Flag_parsing_c.debug_etdt then pr2 (">" ^ s);
336 LP.enable_typedef ()
337
338
339 let fix_add_params_ident x =
340 let (s, ty, st, _attrs) = x in
341 match Ast_c.unwrap_typeC ty with
342 | FunctionType (fullt, (params, bool)) ->
343
344 (match params with
345 | [{p_namei=None; p_type=ty2}, _] ->
346 (match Ast_c.unwrap_typeC ty2 with
347 | BaseType Void -> ()
348 | _ ->
349 (* failwith "internal errror: fixOldCDecl not good" *)
350 ()
351 )
352 | params ->
353 params +> List.iter (function
354 | ({p_namei= Some name}, _) ->
355 LP.add_ident (Ast_c.str_of_name s)
356 | _ ->
357 ()
358 (* failwith "internal errror: fixOldCDecl not good" *)
359 )
360 )
361 | _ -> ()
362
363
364
365 (*-------------------------------------------------------------------------- *)
366 (* shortcuts *)
367 (*-------------------------------------------------------------------------- *)
368
369 let mk_e e ii = Ast_c.mk_e e ii
370
371 let mk_string_wrap (s,info) = (s, [info])
372
373 %}
374
375 /*(*****************************************************************************)*/
376 /*(* Tokens *)*/
377 /*(*************************************************************************)*/
378
379 /*
380 (*
381 * Some tokens are not even used in this file because they are filtered
382 * in some intermediate phase. But they still must be declared because
383 * ocamllex may generate them, or some intermediate phase may also
384 * generate them (like some functions in parsing_hacks.ml)
385 *)
386 */
387
388 %token <Ast_c.info> TUnknown /*(* unrecognized token *)*/
389
390 /*(* coupling: Token_helpers.is_real_comment *)*/
391 %token <Ast_c.info> TCommentSpace TCommentNewline TComment
392
393 /*(*-----------------------------------------*)*/
394 /*(* the normal tokens *)*/
395 /*(*-----------------------------------------*)*/
396
397 %token <(string * (Ast_c.sign * Ast_c.base)) * Ast_c.info> TInt
398 %token <(string * Ast_c.floatType) * Ast_c.info> TFloat
399 %token <(string * Ast_c.isWchar) * Ast_c.info> TChar
400 %token <(string * Ast_c.isWchar) * Ast_c.info> TString
401
402 %token <string * Ast_c.info> TIdent
403 /*(* appears mostly after some fix_xxx in parsing_hack *)*/
404 %token <string * Ast_c.info> TypedefIdent
405
406
407 /*
408 (* Some tokens like TOPar and TCPar are used as synchronisation stuff,
409 * in parsing_hack.ml. So if define special tokens like TOParDefine and
410 * TCParEOL, then take care to also modify in Token_helpers.
411 *)
412 */
413
414 %token <Ast_c.info> TOPar TCPar TOBrace TCBrace TOCro TCCro
415 %token <Ast_c.info> TDot TComma TPtrOp
416 %token <Ast_c.info> TInc TDec
417 %token <Ast_c.assignOp * Ast_c.info> TAssign
418 %token <Ast_c.info> TEq
419 %token <Ast_c.info> TWhy TTilde TBang
420 %token <Ast_c.info> TEllipsis
421 %token <Ast_c.info> TDotDot
422
423 %token <Ast_c.info> TPtVirg
424 %token <Ast_c.info>
425 TOrLog TAndLog TOr TXor TAnd TEqEq TNotEq TInf TSup TInfEq TSupEq
426 TShl TShr
427 TPlus TMinus TMul TDiv TMod
428
429 %token <Ast_c.info>
430 Tchar Tshort Tint Tdouble Tfloat Tlong Tunsigned Tsigned Tvoid
431 Tsize_t Tssize_t Tptrdiff_t
432 Tauto Tregister Textern Tstatic
433 Ttypedef
434 Tconst Tvolatile
435 Tstruct Tunion Tenum
436 Tbreak Telse Tswitch Tcase Tcontinue Tfor Tdo Tif Twhile Treturn
437 Tgoto Tdefault
438 Tsizeof
439
440 /*(* C99 *)*/
441 %token <Ast_c.info>
442 Trestrict
443
444 /*(*-----------------------------------------*)*/
445 /*(* gccext: extra tokens *)*/
446 /*(*-----------------------------------------*)*/
447 %token <Ast_c.info> Tasm
448 %token <Ast_c.info> Tattribute
449 %token <Ast_c.info> TattributeNoarg
450 %token <Ast_c.info> Tinline
451 %token <Ast_c.info> Ttypeof
452
453 /*(*-----------------------------------------*)*/
454 /*(* cppext: extra tokens *)*/
455 /*(*-----------------------------------------*)*/
456 /*(* coupling with Token_helpers.is_cpp_token *)*/
457
458
459 /*(*---------------*)*/
460 /*(* define *)*/
461 /*(*---------------*)*/
462
463 %token <Ast_c.info> TDefine
464 %token <(string * Ast_c.info)> TDefParamVariadic
465
466 /*(* disappear after fix_tokens_define *)*/
467 %token <Ast_c.info> TCppEscapedNewline
468
469 %token <Ast_c.info> TCppConcatOp
470
471 /*(* appear after fix_tokens_define *)*/
472 %token <Ast_c.info> TOParDefine
473 %token <Ast_c.info> TOBraceDefineInit
474
475 %token <(string * Ast_c.info)> TIdentDefine /*(* same *)*/
476 %token <Ast_c.info> TDefEOL /*(* same *)*/
477
478
479 /*(*---------------*)*/
480 /*(* include *)*/
481 /*(*---------------*)*/
482
483
484 /*(* used only in lexer_c, then transformed in comment or splitted in tokens *)*/
485 %token <(string * string * bool ref * Ast_c.info)> TInclude
486
487 /*(* tokens coming from above, generated in parse_c from TInclude, etc *)*/
488 %token <(Ast_c.info * bool ref)> TIncludeStart
489 %token <(string * Ast_c.info)> TIncludeFilename
490
491
492 /*(*---------------*)*/
493 /*(* ifdef *)*/
494 /*(*---------------*)*/
495
496 /*(* coupling: Token_helpers.is_cpp_instruction *)*/
497 %token <((int * int) option ref * Ast_c.info)>
498 TIfdef TIfdefelse TIfdefelif TEndif
499 %token <(bool * (int * int) option ref * Ast_c.info)>
500 TIfdefBool TIfdefMisc TIfdefVersion
501
502 /*(*---------------*)*/
503 /*(* other *)*/
504 /*(*---------------*)*/
505
506 %token <Ast_c.info> TUndef
507
508 %token <Ast_c.info> TCppDirectiveOther
509
510 /*(*---------------*)*/
511 /*(* macro use *)*/
512 /*(*---------------*)*/
513
514 /*(* appear after fix_tokens_cpp, cf also parsing_hacks#hint *)*/
515
516 %token <(string * Ast_c.info)> TMacroAttr
517 %token <(string * Ast_c.info)> TMacroStmt
518 %token <(string * Ast_c.info)> TMacroIdentBuilder
519 /*(* no need value for the moment *)*/
520 %token <(string * Ast_c.info)> TMacroString
521 %token <(string * Ast_c.info)> TMacroDecl
522 %token <Ast_c.info> TMacroDeclConst
523
524 %token <(string * Ast_c.info)> TMacroIterator
525 /*(*
526 %token <(string * Ast_c.info)> TMacroTop
527 %token <(string * Ast_c.info)> TMacroStructDecl
528 *)*/
529
530 %token <(string * Ast_c.info)> TMacroAttrStorage
531
532
533 /*(*---------------*)*/
534 /*(* other *)*/
535 /*(*---------------*)*/
536
537
538 /*(* should disappear after parsing_hack *)*/
539 %token <Ast_c.info> TCommentSkipTagStart TCommentSkipTagEnd
540
541
542 /*(* appear after parsing_hack *)*/
543 %token <Ast_c.info> TCParEOL
544
545 %token <Ast_c.info> TAction
546
547
548 /*(* TCommentMisc still useful ? obsolete ? *)*/
549 %token <Ast_c.info> TCommentMisc
550 %token <(Token_c.cppcommentkind * Ast_c.info)> TCommentCpp
551
552
553 /*(*-----------------------------------------*)*/
554 %token <Ast_c.info> EOF
555
556 /*(*-----------------------------------------*)*/
557
558 /*(* must be at the top so that it has the lowest priority *)*/
559 %nonassoc SHIFTHERE
560
561 %nonassoc Telse
562
563 %left TOrLog
564 %left TAndLog
565 %left TOr
566 %left TXor
567 %left TAnd
568 %left TEqEq TNotEq
569 %left TInf TSup TInfEq TSupEq
570 %left TShl TShr
571 %left TPlus TMinus
572 %left TMul TDiv TMod
573
574 /*(*************************************************************************)*/
575 /*(* Rules type declaration *)*/
576 /*(*************************************************************************)*/
577
578 %start main celem statement expr type_name
579 %type <Ast_c.program> main
580 %type <Ast_c.toplevel> celem
581
582 %type <Ast_c.statement> statement
583 %type <Ast_c.expression> expr
584 %type <Ast_c.fullType> type_name
585
586 %%
587 /*(*************************************************************************)*/
588 /*
589 (* TOC:
590 * toplevel (obsolete)
591 *
592 * ident
593 * expression
594 * statement
595 * types with
596 * - left part (type_spec, qualif),
597 * - right part (declarator, abstract declarator)
598 * - aux part (parameters)
599 * declaration, storage, initializers
600 * struct
601 * enum
602 * cpp directives
603 * celem (=~ main)
604 *
605 * generic workarounds (obrace, cbrace for context setting)
606 * xxx_list, xxx_opt
607 *)
608 */
609 /*(*************************************************************************)*/
610
611 /*(*************************************************************************)*/
612 /*(* toplevel *)*/
613 /*(*************************************************************************)*/
614 /*(* no more used; now that use error recovery *)*/
615
616 main: translation_unit EOF { $1 }
617
618 translation_unit:
619 | external_declaration
620 { !LP._lexer_hint.context_stack <- [LP.InTopLevel]; [$1] }
621 | translation_unit external_declaration
622 { !LP._lexer_hint.context_stack <- [LP.InTopLevel]; $1 ++ [$2] }
623
624
625
626 /*(*************************************************************************)*/
627 /*(* ident *)*/
628 /*(*************************************************************************)*/
629
630 /*(* Why this ? Why not s/ident/TIdent ? cos there is multiple namespaces in C,
631 * so a label can have the same name that a typedef, same for field and tags
632 * hence sometimes the use of ident instead of TIdent.
633 *)*/
634 ident:
635 | TIdent { $1 }
636 | TypedefIdent { $1 }
637
638
639 identifier:
640 | TIdent { $1 }
641
642 /*
643 (* cppext: string concatenation of idents
644 * also cppext: gccext: ##args for variadic macro
645 *)
646 */
647 identifier_cpp:
648 | TIdent
649 { RegularName (mk_string_wrap $1) }
650 | ident_extra_cpp { $1 }
651
652 ident_cpp:
653 | TIdent
654 { RegularName (mk_string_wrap $1) }
655 | TypedefIdent
656 { RegularName (mk_string_wrap $1) }
657 | ident_extra_cpp { $1 }
658
659 ident_extra_cpp:
660 | TIdent TCppConcatOp identifier_cpp_list
661 {
662 CppConcatenatedName (
663 match $3 with
664 | [] -> raise Impossible
665 | (x,concatnull)::xs ->
666 assert(null concatnull);
667 (mk_string_wrap $1, [])::(x,[$2])::xs
668 )
669 }
670 | TCppConcatOp TIdent
671 { CppVariadicName (fst $2, [$1; snd $2]) }
672 | TMacroIdentBuilder TOPar param_define_list TCPar
673 { CppIdentBuilder ((fst $1, [snd $1;$2;$4]), $3) }
674
675 identifier_cpp_list:
676 | TIdent { [mk_string_wrap $1, []] }
677 | identifier_cpp_list TCppConcatOp TIdent { $1 ++ [mk_string_wrap $3, [$2]] }
678
679 /*(*************************************************************************)*/
680 /*(* expr *)*/
681 /*(*************************************************************************)*/
682
683 expr:
684 | assign_expr { $1 }
685 | expr TComma assign_expr { mk_e (Sequence ($1,$3)) [$2] }
686
687 /*(* bugfix: in C grammar they put unary_expr, but in fact it must be
688 * cast_expr, otherwise (int * ) xxx = &yy; is not allowed
689 *)*/
690 assign_expr:
691 | cond_expr { $1 }
692 | cast_expr TAssign assign_expr { mk_e(Assignment ($1,fst $2,$3)) [snd $2]}
693 | cast_expr TEq assign_expr { mk_e(Assignment ($1,SimpleAssign,$3)) [$2]}
694
695 /*(* gccext: allow optional then part hence gcc_opt_expr
696 * bugfix: in C grammar they put TDotDot cond_expr, but in fact it must be
697 * assign_expr, otherwise pnp ? x : x = 0x388 is not allowed
698 *)*/
699 cond_expr:
700 | arith_expr
701 { $1 }
702 | arith_expr TWhy gcc_opt_expr TDotDot assign_expr
703 { mk_e (CondExpr ($1,$3,$5)) [$2;$4] }
704
705
706 arith_expr:
707 | cast_expr { $1 }
708 | arith_expr TMul arith_expr { mk_e(Binary ($1, Arith Mul, $3)) [$2] }
709 | arith_expr TDiv arith_expr { mk_e(Binary ($1, Arith Div, $3)) [$2] }
710 | arith_expr TMod arith_expr { mk_e(Binary ($1, Arith Mod, $3)) [$2] }
711 | arith_expr TPlus arith_expr { mk_e(Binary ($1, Arith Plus, $3)) [$2] }
712 | arith_expr TMinus arith_expr { mk_e(Binary ($1, Arith Minus, $3)) [$2] }
713 | arith_expr TShl arith_expr { mk_e(Binary ($1, Arith DecLeft, $3)) [$2] }
714 | arith_expr TShr arith_expr { mk_e(Binary ($1, Arith DecRight, $3)) [$2] }
715 | arith_expr TInf arith_expr { mk_e(Binary ($1, Logical Inf, $3)) [$2] }
716 | arith_expr TSup arith_expr { mk_e(Binary ($1, Logical Sup, $3)) [$2] }
717 | arith_expr TInfEq arith_expr { mk_e(Binary ($1, Logical InfEq, $3)) [$2] }
718 | arith_expr TSupEq arith_expr { mk_e(Binary ($1, Logical SupEq, $3)) [$2] }
719 | arith_expr TEqEq arith_expr { mk_e(Binary ($1, Logical Eq, $3)) [$2] }
720 | arith_expr TNotEq arith_expr { mk_e(Binary ($1, Logical NotEq, $3)) [$2] }
721 | arith_expr TAnd arith_expr { mk_e(Binary ($1, Arith And, $3)) [$2] }
722 | arith_expr TOr arith_expr { mk_e(Binary ($1, Arith Or, $3)) [$2] }
723 | arith_expr TXor arith_expr { mk_e(Binary ($1, Arith Xor, $3)) [$2] }
724 | arith_expr TAndLog arith_expr { mk_e(Binary ($1, Logical AndLog, $3)) [$2] }
725 | arith_expr TOrLog arith_expr { mk_e(Binary ($1, Logical OrLog, $3)) [$2] }
726
727 cast_expr:
728 | unary_expr { $1 }
729 | topar2 type_name tcpar2 cast_expr { mk_e(Cast ($2, $4)) [$1;$3] }
730
731 unary_expr:
732 | postfix_expr { $1 }
733 | TInc unary_expr { mk_e(Infix ($2, Inc)) [$1] }
734 | TDec unary_expr { mk_e(Infix ($2, Dec)) [$1] }
735 | unary_op cast_expr { mk_e(Unary ($2, fst $1)) [snd $1] }
736 | Tsizeof unary_expr { mk_e(SizeOfExpr ($2)) [$1] }
737 | Tsizeof topar2 type_name tcpar2 { mk_e(SizeOfType ($3)) [$1;$2;$4] }
738
739 unary_op:
740 | TAnd { GetRef, $1 }
741 | TMul { DeRef, $1 }
742 | TPlus { UnPlus, $1 }
743 | TMinus { UnMinus, $1 }
744 | TTilde { Tilde, $1 }
745 | TBang { Not, $1 }
746 /*(* gccext: have that a lot in old kernel to get address of local label.
747 * cf gcc manual "local labels as values".
748 *)*/
749 | TAndLog { GetRefLabel, $1 }
750
751
752
753 postfix_expr:
754 | primary_expr { $1 }
755 | postfix_expr TOCro expr TCCro
756 { mk_e(ArrayAccess ($1, $3)) [$2;$4] }
757 | postfix_expr TOPar argument_list_ne TCPar
758 { mk_e(FunCall ($1, $3)) [$2;$4] }
759 | postfix_expr TOPar TCPar { mk_e(FunCall ($1, [])) [$2;$3] }
760 | postfix_expr TDot ident_cpp { mk_e(RecordAccess ($1,$3)) [$2] }
761 | postfix_expr TPtrOp ident_cpp { mk_e(RecordPtAccess ($1,$3)) [$2] }
762 | postfix_expr TInc { mk_e(Postfix ($1, Inc)) [$2] }
763 | postfix_expr TDec { mk_e(Postfix ($1, Dec)) [$2] }
764
765 /*(* gccext: also called compound literals *)*/
766 | topar2 type_name tcpar2 TOBrace TCBrace
767 { mk_e(Constructor ($2, [])) [$1;$3;$4;$5] }
768 | topar2 type_name tcpar2 TOBrace initialize_list gcc_comma_opt TCBrace
769 { mk_e(Constructor ($2, List.rev $5)) ([$1;$3;$4;$7] ++ $6) }
770
771 primary_expr:
772 | identifier_cpp { mk_e(Ident ($1)) [] }
773 | TInt
774 { let (str,(sign,base)) = fst $1 in
775 mk_e(Constant (Int (str,Si(sign,base)))) [snd $1] }
776 | TFloat { mk_e(Constant (Float (fst $1))) [snd $1] }
777 | TString { mk_e(Constant (String (fst $1))) [snd $1] }
778 | TChar { mk_e(Constant (Char (fst $1))) [snd $1] }
779 | TOPar expr TCPar { mk_e(ParenExpr ($2)) [$1;$3] } /*(* forunparser: *)*/
780
781 /*(* gccext: cppext: TODO better ast ? *)*/
782 | TMacroString { mk_e(Constant (MultiString [fst $1])) [snd $1] }
783 | string_elem string_list
784 { mk_e(Constant (MultiString ["TODO: MultiString"])) ($1 ++ $2) }
785
786 /*(* gccext: allow statement as expressions via ({ statement }) *)*/
787 | TOPar compound TCPar { mk_e(StatementExpr ($2)) [$1;$3] }
788
789
790
791 /*(*----------------------------*)*/
792 /*(* cppext: *)*/
793 /*(*----------------------------*)*/
794
795 /*(* cppext: *)*/
796 /*(* to avoid conflicts have to introduce a _not_empty (ne) version *)*/
797 argument_ne:
798 | assign_expr { Left $1 }
799 | parameter_decl { Right (ArgType $1) }
800 | action_higherordermacro_ne { Right (ArgAction $1) }
801
802
803 argument:
804 | assign_expr { Left $1 }
805 | parameter_decl { Right (ArgType $1) }
806 /*(* had conflicts before, but julia fixed them *)*/
807 | action_higherordermacro { Right (ArgAction $1) }
808
809 action_higherordermacro_ne:
810 | taction_list_ne
811 { if null $1
812 then ActMisc [Ast_c.fakeInfo()]
813 else ActMisc $1
814 }
815
816
817 action_higherordermacro:
818 | taction_list
819 { if null $1
820 then ActMisc [Ast_c.fakeInfo()]
821 else ActMisc $1
822 }
823
824
825 /*(*----------------------------*)*/
826 /*(* workarounds *)*/
827 /*(*----------------------------*)*/
828
829 /*(* would like evalInt $1 but require too much info *)*/
830 const_expr: cond_expr { $1 }
831
832
833 topar2: TOPar { et "topar2" (); $1 }
834 tcpar2: TCPar { et "tcpar2" (); $1 (*TODO? et ? sure ? c pas dt plutot ? *) }
835
836
837
838 /*(*************************************************************************)*/
839 /*(* statement *)*/
840 /*(*************************************************************************)*/
841
842 statement: statement2 { mk_st (fst $1) (snd $1) }
843
844 statement2:
845 | labeled { Labeled (fst $1), snd $1 }
846 | compound { Compound (fst $1), snd $1 }
847 | expr_statement { ExprStatement(fst $1), snd $1 }
848 | selection { Selection (fst $1), snd $1 ++ [fakeInfo()] }
849 | iteration { Iteration (fst $1), snd $1 ++ [fakeInfo()] }
850 | jump TPtVirg { Jump (fst $1), snd $1 ++ [$2] }
851
852 /*(* gccext: *)*/
853 | Tasm TOPar asmbody TCPar TPtVirg { Asm $3, [$1;$2;$4;$5] }
854 | Tasm Tvolatile TOPar asmbody TCPar TPtVirg { Asm $4, [$1;$2;$3;$5;$6] }
855
856 /*(* cppext: *)*/
857 | TMacroStmt { MacroStmt, [snd $1] }
858
859
860
861
862 /*(* note that case 1: case 2: i++; would be correctly parsed, but with
863 * a Case (1, (Case (2, i++))) :(
864 *)*/
865 labeled:
866 | ident_cpp TDotDot statement { Label ($1, $3), [$2] }
867 | Tcase const_expr TDotDot statement { Case ($2, $4), [$1; $3] }
868 | Tcase const_expr TEllipsis const_expr TDotDot statement
869 { CaseRange ($2, $4, $6), [$1;$3;$5] } /*(* gccext: allow range *)*/
870 | Tdefault TDotDot statement { Default $3, [$1; $2] }
871
872 end_labeled:
873 /*(* gccext: allow toto: }
874 * was generating each 30 shift/Reduce conflicts,
875 * mais ca va, ca fait ce qu'il faut.
876 * update: julia fixed the problem by introducing end_labeled
877 * and modifying below stat_or_decl_list
878 *)*/
879 | ident_cpp TDotDot
880 { Label ($1, (mk_st (ExprStatement None) Ast_c.noii)), [$2] }
881 | Tcase const_expr TDotDot
882 { Case ($2, (mk_st (ExprStatement None) Ast_c.noii)), [$1;$3] }
883 | Tdefault TDotDot
884 { Default (mk_st (ExprStatement None) Ast_c.noii), [$1; $2] }
885
886
887
888
889
890 compound: tobrace compound2 tcbrace { $2, [$1; $3] }
891
892
893 /*
894 (* cppext: because of cpp, some stuff looks like declaration but are in
895 * fact statement but too hard to figure out, and if parse them as
896 * expression, then we force to have first decls and then exprs, then
897 * will have a parse error. So easier to let mix decl/statement.
898 * Moreover it helps to not make such a difference between decl and
899 * statement for further coccinelle phases to factorize code.
900 *)*/
901 compound2:
902 | { ([]) }
903 | stat_or_decl_list { $1 }
904
905
906 stat_or_decl_list:
907 | stat_or_decl { [$1] }
908 /*(* gccext: to avoid conflicts, cf end_labeled above *)*/
909 | end_labeled { [StmtElem (mk_st (Labeled (fst $1)) (snd $1))] }
910 /*(* old: conflicts | stat_or_decl_list stat_or_decl { $1 ++ [$2] } *)*/
911 | stat_or_decl stat_or_decl_list { $1 :: $2 }
912
913 stat_or_decl:
914 | decl { StmtElem (mk_st (Decl ($1 Ast_c.LocalDecl)) Ast_c.noii) }
915 | statement { StmtElem $1 }
916
917 /*(* gccext: *)*/
918 | function_definition { StmtElem (mk_st (NestedFunc $1) Ast_c.noii) }
919
920 /* (* cppext: *)*/
921 | cpp_directive
922 { CppDirectiveStmt $1 }
923 | cpp_ifdef_directive/*(* stat_or_decl_list ...*)*/
924 { IfdefStmt $1 }
925
926
927
928
929
930 expr_statement:
931 | TPtVirg { None, [$1] }
932 | expr TPtVirg { Some $1, [$2] }
933
934 selection:
935 | Tif TOPar expr TCPar statement %prec SHIFTHERE
936 { If ($3, $5, (mk_st (ExprStatement None) Ast_c.noii)), [$1;$2;$4] }
937 | Tif TOPar expr TCPar statement Telse statement
938 { If ($3, $5, $7), [$1;$2;$4;$6] }
939 | Tswitch TOPar expr TCPar statement
940 { Switch ($3,$5), [$1;$2;$4] }
941
942 iteration:
943 | Twhile TOPar expr TCPar statement
944 { While ($3,$5), [$1;$2;$4] }
945 | Tdo statement Twhile TOPar expr TCPar TPtVirg
946 { DoWhile ($2,$5), [$1;$3;$4;$6;$7] }
947 | Tfor TOPar expr_statement expr_statement TCPar statement
948 { For ($3,$4,(None, []),$6), [$1;$2;$5]}
949 | Tfor TOPar expr_statement expr_statement expr TCPar statement
950 { For ($3,$4,(Some $5, []),$7), [$1;$2;$6] }
951 /*(* c++ext: for(int i = 0; i < n; i++)*)*/
952 | Tfor TOPar decl expr_statement expr_opt TCPar statement
953 {
954 (* pr2 "DECL in for"; *)
955 MacroIteration ("toto", [], $7),[$1;$2;$6] (* TODOfake ast, TODO need decl2 ? *)
956 }
957 /*(* cppext: *)*/
958 | TMacroIterator TOPar argument_list_ne TCPar statement
959 { MacroIteration (fst $1, $3, $5), [snd $1;$2;$4] }
960 | TMacroIterator TOPar TCPar statement
961 { MacroIteration (fst $1, [], $4), [snd $1;$2;$3] }
962
963 /*(* the ';' in the caller grammar rule will be appended to the infos *)*/
964 jump:
965 | Tgoto ident_cpp { Goto ($2), [$1] }
966 | Tcontinue { Continue, [$1] }
967 | Tbreak { Break, [$1] }
968 | Treturn { Return, [$1] }
969 | Treturn expr { ReturnExpr $2, [$1] }
970 | Tgoto TMul expr { GotoComputed $3, [$1;$2] }
971
972
973
974 /*(*----------------------------*)*/
975 /*(* gccext: *)*/
976 /*(*----------------------------*)*/
977 string_elem:
978 | TString { [snd $1] }
979 /*(* cppext: ex= printk (KERN_INFO "xxx" UTS_RELEASE) *)*/
980 | TMacroString { [snd $1] }
981
982
983 asmbody:
984 | string_list colon_asm_list { $1, $2 }
985 | string_list { $1, [] } /*(* in old kernel *)*/
986
987
988 colon_asm: TDotDot colon_option_list { Colon $2, [$1] }
989
990 colon_option:
991 | TString { ColonMisc, [snd $1] }
992 | TString TOPar asm_expr TCPar { ColonExpr $3, [snd $1; $2;$4] }
993 /*(* cppext: certainly a macro *)*/
994 | TOCro identifier TCCro TString TOPar asm_expr TCPar
995 { ColonExpr $6, [$1;snd $2;$3;snd $4; $5; $7 ] }
996 | identifier { ColonMisc, [snd $1] }
997 | /*(* empty *)*/ { ColonMisc, [] }
998
999 asm_expr: assign_expr { $1 }
1000
1001 /*(*************************************************************************)*/
1002 /*(* types *)*/
1003 /*(*************************************************************************)*/
1004
1005
1006 /*(*-----------------------------------------------------------------------*)*/
1007 /*(* Type spec, left part of a type *)*/
1008 /*(*-----------------------------------------------------------------------*)*/
1009 type_spec2:
1010 | Tvoid { Right3 (BaseType Void), [$1] }
1011 | Tchar { Right3 (BaseType (IntType CChar)), [$1]}
1012 | Tint { Right3 (BaseType (IntType (Si (Signed,CInt)))), [$1]}
1013 | Tfloat { Right3 (BaseType (FloatType CFloat)), [$1]}
1014 | Tdouble { Right3 (BaseType (FloatType CDouble)), [$1] }
1015 | Tsize_t { Right3 (BaseType SizeType), [$1] }
1016 | Tssize_t { Right3 (BaseType SSizeType), [$1] }
1017 | Tptrdiff_t { Right3 (BaseType PtrDiffType), [$1] }
1018 | Tshort { Middle3 Short, [$1]}
1019 | Tlong { Middle3 Long, [$1]}
1020 | Tsigned { Left3 Signed, [$1]}
1021 | Tunsigned { Left3 UnSigned, [$1]}
1022 | struct_or_union_spec { Right3 (fst $1), snd $1 }
1023 | enum_spec { Right3 (fst $1), snd $1 }
1024
1025 /*
1026 (* parse_typedef_fix1: cant put: TIdent {} cos it make the grammar
1027 * ambiguous, generates lots of conflicts => we must
1028 * use some tricks: we make the lexer and parser cooperate, cf lexerParser.ml.
1029 *
1030 * parse_typedef_fix2: this is not enough, and you must use
1031 * parse_typedef_fix2 to fully manage typedef problems in grammar.
1032 *
1033 * parse_typedef_fix3:
1034 *
1035 * parse_typedef_fix4: try also to do now some consistency checking in
1036 * Parse_c
1037 *)*/
1038 | TypedefIdent
1039 { let name = RegularName (mk_string_wrap $1) in
1040 Right3 (TypeName (name, Ast_c.noTypedefDef())),[] }
1041
1042 | Ttypeof TOPar assign_expr TCPar { Right3 (TypeOfExpr ($3)), [$1;$2;$4] }
1043 | Ttypeof TOPar type_name TCPar { Right3 (TypeOfType ($3)), [$1;$2;$4] }
1044
1045 /*(*----------------------------*)*/
1046 /*(* workarounds *)*/
1047 /*(*----------------------------*)*/
1048
1049 type_spec: type_spec2 { dt "type" (); $1 }
1050
1051 /*(*-----------------------------------------------------------------------*)*/
1052 /*(* Qualifiers *)*/
1053 /*(*-----------------------------------------------------------------------*)*/
1054
1055 type_qualif:
1056 | Tconst { {const=true ; volatile=false}, $1 }
1057 | Tvolatile { {const=false ; volatile=true}, $1 }
1058 /*(* C99 *)*/
1059 | Trestrict { (* TODO *) {const=false ; volatile=false}, $1 }
1060
1061
1062 /*(*-----------------------------------------------------------------------*)*/
1063 /*(* gccext: attributes *)*/
1064 /*(*-----------------------------------------------------------------------*)*/
1065
1066 attribute:
1067 | Tattribute TOPar /*stuff*/ TCPar { raise Todo }
1068 /*(* cppext: *)*/
1069 | TMacroAttr { Attribute (fst $1), [snd $1] }
1070
1071 attribute_storage:
1072 | TMacroAttrStorage { $1 }
1073
1074 type_qualif_attr:
1075 | type_qualif { $1 }
1076 /*(*TODO !!!!! *)*/
1077 | TMacroAttr { {const=true ; volatile=false}, snd $1 }
1078
1079 /*(*-----------------------------------------------------------------------*)*/
1080 /*(* Declarator, right part of a type + second part of decl (the ident) *)*/
1081 /*(*-----------------------------------------------------------------------*)*/
1082
1083 /*
1084 (* declarator return a couple:
1085 * (name, partial type (a function to be applied to return type))
1086 *
1087 * when int* f(int) we must return Func(Pointer int,int) and not
1088 * Pointer (Func(int,int)
1089 *)*/
1090
1091 declarator:
1092 | pointer direct_d { (fst $2, fun x -> x +> $1 +> (snd $2) ) }
1093 | direct_d { $1 }
1094
1095 /*(* so must do int * const p; if the pointer is constant, not the pointee *)*/
1096 pointer:
1097 | TMul { fun x -> mk_ty (Pointer x) [$1] }
1098 | TMul pointer { fun x -> mk_ty (Pointer ($2 x)) [$1] }
1099 | TMul type_qualif_list
1100 { fun x -> ($2.qualifD, mk_tybis (Pointer x) [$1])}
1101 | TMul type_qualif_list pointer
1102 { fun x -> ($2.qualifD, mk_tybis (Pointer ($3 x)) [$1]) }
1103
1104
1105 direct_d:
1106 | identifier_cpp
1107 { ($1, fun x -> x) }
1108 | TOPar declarator TCPar /*(* forunparser: old: $2 *)*/
1109 { (fst $2, fun x -> mk_ty (ParenType ((snd $2) x)) [$1;$3]) }
1110 | direct_d tocro tccro
1111 { (fst $1,fun x->(snd $1) (mk_ty (Array (None,x)) [$2;$3])) }
1112 | direct_d tocro const_expr tccro
1113 { (fst $1,fun x->(snd $1) (mk_ty (Array (Some $3,x)) [$2;$4])) }
1114 | direct_d topar tcpar
1115 { (fst $1,
1116 fun x->(snd $1)
1117 (mk_ty (FunctionType (x,(([],(false, []))))) [$2;$3]))
1118 }
1119 | direct_d topar parameter_type_list tcpar
1120 { (fst $1,fun x->(snd $1)
1121 (mk_ty (FunctionType (x, $3)) [$2;$4]))
1122 }
1123
1124
1125 /*(*----------------------------*)*/
1126 /*(* workarounds *)*/
1127 /*(*----------------------------*)*/
1128
1129 tocro: TOCro { et "tocro" ();$1 }
1130 tccro: TCCro { dt "tccro" ();$1 }
1131
1132 /*(*-----------------------------------------------------------------------*)*/
1133 abstract_declarator:
1134 | pointer { $1 }
1135 | direct_abstract_declarator { $1 }
1136 | pointer direct_abstract_declarator { fun x -> x +> $2 +> $1 }
1137
1138 direct_abstract_declarator:
1139 | TOPar abstract_declarator TCPar /*(* forunparser: old: $2 *)*/
1140 { fun x -> mk_ty (ParenType ($2 x)) [$1;$3] }
1141
1142 | TOCro TCCro
1143 { fun x -> mk_ty (Array (None, x)) [$1;$2] }
1144 | TOCro const_expr TCCro
1145 { fun x -> mk_ty (Array (Some $2, x)) [$1;$3] }
1146 | direct_abstract_declarator TOCro TCCro
1147 { fun x -> $1 (mk_ty (Array (None, x)) [$2;$3]) }
1148 | direct_abstract_declarator TOCro const_expr TCCro
1149 { fun x -> $1 (mk_ty (Array (Some $3,x)) [$2;$4]) }
1150 | TOPar TCPar
1151 { fun x -> mk_ty (FunctionType (x, ([], (false, [])))) [$1;$2] }
1152 | topar parameter_type_list tcpar
1153 { fun x -> mk_ty (FunctionType (x, $2)) [$1;$3] }
1154 /*(* subtle: here must also use topar, not TOPar, otherwise if have for
1155 * instance (xxx ( * )(xxx)) cast, then the second xxx may still be a Tident
1156 * but we want to reduce topar, to set the InParameter so that
1157 * parsing_hack can get a chance to change the type of xxx into a typedef.
1158 * That's an example where parsing_hack and the lookahead of ocamlyacc does
1159 * not go very well together ... we got the info too late. We got
1160 * a similar pb with xxx xxx; declaration, cf parsing_hack.ml and the
1161 * "disable typedef cos special case ..." message.
1162 *)*/
1163 | direct_abstract_declarator topar tcpar
1164 { fun x -> $1 (mk_ty (FunctionType (x, (([], (false, []))))) [$2;$3]) }
1165 | direct_abstract_declarator topar parameter_type_list tcpar
1166 { fun x -> $1 (mk_ty (FunctionType (x, $3)) [$2;$4]) }
1167
1168 /*(*-----------------------------------------------------------------------*)*/
1169 /*(* Parameters (use decl_spec not type_spec just for 'register') *)*/
1170 /*(*-----------------------------------------------------------------------*)*/
1171 parameter_type_list:
1172 | parameter_list { ($1, (false, []))}
1173 | parameter_list TComma TEllipsis { ($1, (true, [$2;$3])) }
1174
1175
1176 parameter_decl2:
1177 | decl_spec declaratorp
1178 { let ((returnType,hasreg),iihasreg) = fixDeclSpecForParam $1 in
1179 let (name, ftyp) = $2 in
1180 { p_namei = Some (name);
1181 p_type = ftyp returnType;
1182 p_register = (hasreg, iihasreg);
1183 }
1184 }
1185 | decl_spec abstract_declaratorp
1186 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1 in
1187 { p_namei = None;
1188 p_type = $2 returnType;
1189 p_register = hasreg, iihasreg;
1190 }
1191 }
1192 | decl_spec
1193 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1 in
1194 { p_namei = None;
1195 p_type = returnType;
1196 p_register = hasreg, iihasreg;
1197 }
1198 }
1199
1200
1201 /*(*----------------------------*)*/
1202 /*(* workarounds *)*/
1203 /*(*----------------------------*)*/
1204
1205 parameter_decl: parameter_decl2 { et "param" (); $1 }
1206 | attributes parameter_decl2 { et "param" (); $2 }
1207
1208 declaratorp:
1209 | declarator { LP.add_ident (str_of_name (fst $1)); $1 }
1210 /*(* gccext: *)*/
1211 | attributes declarator { LP.add_ident (str_of_name (fst $2)); $2 }
1212 | declarator attributes { LP.add_ident (str_of_name (fst $1)); $1 }
1213
1214 abstract_declaratorp:
1215 | abstract_declarator { $1 }
1216 /*(* gccext: *)*/
1217 | attributes abstract_declarator { $2 }
1218
1219 /*(*-----------------------------------------------------------------------*)*/
1220 /*(* helper type rules *)*/
1221 /*(*-----------------------------------------------------------------------*)*/
1222
1223 /*(* for struct and also typename *)*/
1224 /*(* cant put decl_spec cos no storage is allowed for field struct *)*/
1225 spec_qualif_list2:
1226 | type_spec { addTypeD ($1, nullDecl) }
1227 | type_qualif { {nullDecl with qualifD = (fst $1,[snd $1])}}
1228 | type_spec spec_qualif_list { addTypeD ($1,$2) }
1229 | type_qualif spec_qualif_list { addQualifD ($1,$2) }
1230
1231 spec_qualif_list: spec_qualif_list2 { dt "spec_qualif" (); $1 }
1232
1233
1234 /*(* for pointers in direct_declarator and abstract_declarator *)*/
1235 type_qualif_list:
1236 | type_qualif_attr { {nullDecl with qualifD = (fst $1,[snd $1])} }
1237 | type_qualif_list type_qualif_attr { addQualifD ($2,$1) }
1238
1239
1240
1241
1242
1243
1244 /*(*-----------------------------------------------------------------------*)*/
1245 /*(* xxx_type_id *)*/
1246 /*(*-----------------------------------------------------------------------*)*/
1247
1248 type_name:
1249 | spec_qualif_list
1250 { let (returnType, _) = fixDeclSpecForDecl $1 in returnType }
1251 | spec_qualif_list abstract_declaratort
1252 { let (returnType, _) = fixDeclSpecForDecl $1 in $2 returnType }
1253
1254
1255
1256 abstract_declaratort:
1257 | abstract_declarator { $1 }
1258 /*(* gccext: *)*/
1259 | attributes abstract_declarator { $2 }
1260
1261
1262 /*(*************************************************************************)*/
1263 /*(* declaration and initializers *)*/
1264 /*(*************************************************************************)*/
1265
1266 decl2:
1267 | decl_spec TPtVirg
1268 { function local ->
1269 let (returnType,storage) = fixDeclSpecForDecl $1 in
1270 let iistart = Ast_c.fakeInfo () in
1271 DeclList ([{v_namei = None; v_type = returnType;
1272 v_storage = unwrap storage; v_local = local;
1273 v_attr = Ast_c.noattr;
1274 v_type_bis = ref None;
1275 },[]],
1276 ($2::iistart::snd storage))
1277 }
1278 | decl_spec init_declarator_list TPtVirg
1279 { function local ->
1280 let (returnType,storage) = fixDeclSpecForDecl $1 in
1281 let iistart = Ast_c.fakeInfo () in
1282 DeclList (
1283 ($2 +> List.map (fun ((((name,f),attrs), ini), iivirg) ->
1284 let s = str_of_name name in
1285 let iniopt =
1286 match ini with
1287 | None -> None
1288 | Some (ini, iini) -> Some (iini, ini)
1289 in
1290 if fst (unwrap storage) =*= StoTypedef
1291 then LP.add_typedef s;
1292 {v_namei = Some (name, iniopt);
1293 v_type = f returnType;
1294 v_storage = unwrap storage;
1295 v_local = local;
1296 v_attr = attrs;
1297 v_type_bis = ref None;
1298 },
1299 iivirg
1300 )
1301 ), ($3::iistart::snd storage))
1302 }
1303 /*(* cppext: *)*/
1304
1305 | TMacroDecl TOPar argument_list TCPar TPtVirg
1306 { function _ ->
1307 MacroDecl ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]) }
1308 | Tstatic TMacroDecl TOPar argument_list TCPar TPtVirg
1309 { function _ ->
1310 MacroDecl ((fst $2, $4), [snd $2;$3;$5;$6;fakeInfo();$1]) }
1311 | Tstatic TMacroDeclConst TMacroDecl TOPar argument_list TCPar TPtVirg
1312 { function _ ->
1313 MacroDecl ((fst $3, $5), [snd $3;$4;$6;$7;fakeInfo();$1;$2])}
1314
1315
1316 /*(*-----------------------------------------------------------------------*)*/
1317 decl_spec2:
1318 | storage_class_spec { {nullDecl with storageD = (fst $1, [snd $1]) } }
1319 | type_spec { addTypeD ($1,nullDecl) }
1320 | type_qualif { {nullDecl with qualifD = (fst $1, [snd $1]) } }
1321 | Tinline { {nullDecl with inlineD = (true, [$1]) } }
1322 | storage_class_spec decl_spec2 { addStorageD ($1, $2) }
1323 | type_spec decl_spec2 { addTypeD ($1, $2) }
1324 | type_qualif decl_spec2 { addQualifD ($1, $2) }
1325 | Tinline decl_spec2 { addInlineD ((true, $1), $2) }
1326
1327 /*(* can simplify by putting all in _opt ? must have at least one otherwise
1328 * decl_list is ambiguous ? (no cos have ';' between decl)
1329 *)*/
1330
1331
1332 storage_class_spec2:
1333 | Tstatic { Sto Static, $1 }
1334 | Textern { Sto Extern, $1 }
1335 | Tauto { Sto Auto, $1 }
1336 | Tregister { Sto Register,$1 }
1337 | Ttypedef { StoTypedef, $1 }
1338
1339 storage_class_spec:
1340 /*(* gccext: *)*/
1341 | storage_class_spec2 { $1 }
1342 | storage_class_spec2 attribute_storage_list { $1 (* TODO *) }
1343
1344
1345
1346 /*(*----------------------------*)*/
1347 /*(* workarounds *)*/
1348 /*(*----------------------------*)*/
1349
1350 decl: decl2 { et "decl" (); $1 }
1351 decl_spec: decl_spec2 { dt "declspec" (); $1 }
1352
1353 /*(*-----------------------------------------------------------------------*)*/
1354 /*(* declarators (right part of type and variable) *)*/
1355 /*(*-----------------------------------------------------------------------*)*/
1356 init_declarator2:
1357 | declaratori { ($1, None) }
1358 | declaratori teq initialize { ($1, Some ($3, $2)) }
1359
1360
1361
1362 /*(*----------------------------*)*/
1363 /*(* workarounds *)*/
1364 /*(*----------------------------*)*/
1365 teq: TEq { et "teq" (); $1 }
1366
1367 init_declarator: init_declarator2 { dt "init" (); $1 }
1368
1369
1370 /*(*----------------------------*)*/
1371 /*(* gccext: *)*/
1372 /*(*----------------------------*)*/
1373
1374 declaratori:
1375 | declarator { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr }
1376 /*(* gccext: *)*/
1377 | declarator gcc_asm_decl { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr }
1378 /*(* gccext: *)*/
1379 | attributes declarator { LP.add_ident (str_of_name (fst $2)); $2, $1 }
1380 | declarator attributes { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr (* TODO *) }
1381
1382
1383
1384 gcc_asm_decl:
1385 | Tasm TOPar asmbody TCPar { }
1386 | Tasm Tvolatile TOPar asmbody TCPar { }
1387
1388
1389 /*(*-----------------------------------------------------------------------*)*/
1390 initialize:
1391 | assign_expr
1392 { InitExpr $1, [] }
1393 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
1394 { InitList (List.rev $2), [$1;$4]++$3 }
1395 | tobrace_ini tcbrace_ini
1396 { InitList [], [$1;$2] } /*(* gccext: *)*/
1397
1398
1399 /*
1400 (* opti: This time we use the weird order of non-terminal which requires in
1401 * the "caller" to do a List.rev cos quite critical. With this weird order it
1402 * allows yacc to use a constant stack space instead of exploding if we would
1403 * do a 'initialize2 Tcomma initialize_list'.
1404 *)
1405 */
1406 initialize_list:
1407 | initialize2 { [$1, []] }
1408 | initialize_list TComma initialize2 { ($3, [$2])::$1 }
1409
1410
1411 /*(* gccext: condexpr and no assign_expr cos can have ambiguity with comma *)*/
1412 initialize2:
1413 | cond_expr
1414 { InitExpr $1, [] }
1415 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
1416 { InitList (List.rev $2), [$1;$4]++$3 }
1417 | tobrace_ini tcbrace_ini
1418 { InitList [], [$1;$2] }
1419
1420 /*(* gccext: labeled elements, a.k.a designators *)*/
1421 | designator_list TEq initialize2
1422 { InitDesignators ($1, $3), [$2] }
1423
1424 /*(* gccext: old format *)*/
1425 | ident TDotDot initialize2
1426 { InitFieldOld (fst $1, $3), [snd $1; $2] } /*(* in old kernel *)*/
1427 /* conflict
1428 | TOCro const_expr TCCro initialize2
1429 { InitIndexOld ($2, $4), [$1;$3] }
1430 */
1431
1432
1433
1434 /*(* they can be nested, can have a .x[3].y *)*/
1435 designator:
1436 | TDot ident
1437 { DesignatorField (fst $2), [$1;snd $2] }
1438 | TOCro const_expr TCCro
1439 { DesignatorIndex ($2), [$1;$3] }
1440 | TOCro const_expr TEllipsis const_expr TCCro
1441 { DesignatorRange ($2, $4), [$1;$3;$5] }
1442
1443
1444 /*(*----------------------------*)*/
1445 /*(* workarounds *)*/
1446 /*(*----------------------------*)*/
1447
1448 gcc_comma_opt_struct:
1449 | TComma { [$1] }
1450 | /*(* empty *)*/ { [Ast_c.fakeInfo() +> Ast_c.rewrap_str ","] }
1451
1452
1453
1454
1455
1456
1457
1458
1459 /*(*************************************************************************)*/
1460 /*(* struct *)*/
1461 /*(*************************************************************************)*/
1462
1463 s_or_u_spec2:
1464 | struct_or_union ident tobrace_struct struct_decl_list_gcc tcbrace_struct
1465 { StructUnion (fst $1, Some (fst $2), $4), [snd $1;snd $2;$3;$5] }
1466 | struct_or_union tobrace_struct struct_decl_list_gcc tcbrace_struct
1467 { StructUnion (fst $1, None, $3), [snd $1;$2;$4] }
1468 | struct_or_union ident
1469 { StructUnionName (fst $1, fst $2), [snd $1;snd $2] }
1470
1471 struct_or_union2:
1472 | Tstruct { Struct, $1 }
1473 | Tunion { Union, $1 }
1474 /*(* gccext: *)*/
1475 | Tstruct attributes { Struct, $1 (* TODO *) }
1476 | Tunion attributes { Union, $1 (* TODO *) }
1477
1478
1479
1480 struct_decl2:
1481 | field_declaration { DeclarationField $1 }
1482 | TPtVirg { EmptyField $1 }
1483
1484 /*(* no conflict ? no need for a TMacroStruct ? apparently not as at struct
1485 * the rule are slightly different.
1486 *)*/
1487 | identifier TOPar argument_list TCPar TPtVirg
1488 { MacroDeclField ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]) }
1489
1490 /*(* cppext: *)*/
1491 | cpp_directive
1492 { CppDirectiveStruct $1 }
1493 | cpp_ifdef_directive/*(* struct_decl_list ... *)*/
1494 { IfdefStruct $1 }
1495
1496
1497 field_declaration:
1498 | spec_qualif_list struct_declarator_list TPtVirg
1499 {
1500 let (returnType,storage) = fixDeclSpecForDecl $1 in
1501 if fst (unwrap storage) <> NoSto
1502 then internal_error "parsing dont allow this";
1503
1504 FieldDeclList ($2 +> (List.map (fun (f, iivirg) ->
1505 f returnType, iivirg))
1506 ,[$3])
1507 (* dont need to check if typedef or func initialised cos
1508 * grammar dont allow typedef nor initialiser in struct
1509 *)
1510 }
1511
1512 | spec_qualif_list TPtVirg
1513 {
1514 (* gccext: allow empty elements if it is a structdef or enumdef *)
1515 let (returnType,storage) = fixDeclSpecForDecl $1 in
1516 if fst (unwrap storage) <> NoSto
1517 then internal_error "parsing dont allow this";
1518
1519 FieldDeclList ([(Simple (None, returnType)) , []], [$2])
1520 }
1521
1522
1523
1524
1525
1526 struct_declarator:
1527 | declaratorsd
1528 { (fun x -> Simple (Some (fst $1), (snd $1) x)) }
1529 | dotdot const_expr2
1530 { (fun x -> BitField (None, x, $1, $2)) }
1531 | declaratorsd dotdot const_expr2
1532 { (fun x -> BitField (Some (fst $1), ((snd $1) x), $2, $3)) }
1533
1534
1535 /*(*----------------------------*)*/
1536 /*(* workarounds *)*/
1537 /*(*----------------------------*)*/
1538 declaratorsd:
1539 | declarator { (*also ? LP.add_ident (fst (fst $1)); *) $1 }
1540 /*(* gccext: *)*/
1541 | attributes declarator { $2 }
1542 | declarator attributes { $1 }
1543
1544
1545
1546
1547 struct_or_union_spec: s_or_u_spec2 { dt "su" (); $1 }
1548 struct_or_union: struct_or_union2 { et "su" (); $1 }
1549 struct_decl: struct_decl2 { et "struct" (); $1 }
1550
1551 dotdot: TDotDot { et "dotdot" (); $1 }
1552 const_expr2: const_expr { dt "const_expr2" (); $1 }
1553
1554 struct_decl_list_gcc:
1555 | struct_decl_list { $1 }
1556 | /*(* empty *)*/ { [] } /*(* gccext: allow empty struct *)*/
1557
1558
1559 /*(*************************************************************************)*/
1560 /*(* enum *)*/
1561 /*(*************************************************************************)*/
1562 enum_spec:
1563 | Tenum tobrace_enum enumerator_list gcc_comma_opt_struct tcbrace_enum
1564 { Enum (None, $3), [$1;$2;$5] ++ $4 }
1565 | Tenum ident tobrace_enum enumerator_list gcc_comma_opt_struct tcbrace_enum
1566 { Enum (Some (fst $2), $4), [$1; snd $2; $3;$6] ++ $5 }
1567 | Tenum ident
1568 { EnumName (fst $2), [$1; snd $2] }
1569
1570 enumerator:
1571 | idente { $1, None }
1572 | idente TEq const_expr { $1, Some ($2, $3) }
1573
1574
1575 /*(*----------------------------*)*/
1576 /*(* workarounds *)*/
1577 /*(*----------------------------*)*/
1578
1579 idente: ident_cpp { LP.add_ident (str_of_name $1); $1 }
1580
1581
1582
1583 /*(*************************************************************************)*/
1584 /*(* function *)*/
1585 /*(*************************************************************************)*/
1586 function_definition: function_def { fixFunc $1 }
1587
1588 decl_list:
1589 | decl { [$1 Ast_c.LocalDecl] }
1590 | decl_list decl { $1 ++ [$2 Ast_c.LocalDecl] }
1591
1592 /* hack : to drop when a better solution is found */
1593 cpp_directive_list:
1594 | cpp_directive { }
1595 | cpp_directive_list cpp_directive { }
1596
1597 function_def:
1598 | start_fun compound { LP.del_scope(); ($1, $2, None) }
1599 | start_fun cpp_directive_list compound { LP.del_scope(); ($1, $3, None) }
1600 | start_fun decl_list compound {
1601 (* TODO: undo the typedef added ? *)
1602 LP.del_scope();
1603 ($1, $3, Some $2)
1604 }
1605
1606 start_fun: start_fun2
1607 { LP.new_scope();
1608 fix_add_params_ident $1;
1609 (* toreput? !LP._lexer_hint.toplevel <- false; *)
1610 $1
1611 }
1612
1613 start_fun2: decl_spec declaratorfd
1614 { let (returnType,storage) = fixDeclSpecForFuncDef $1 in
1615 let (id, attrs) = $2 in
1616 (fst id, fixOldCDecl ((snd id) returnType) , storage, attrs)
1617 }
1618
1619 /*(*----------------------------*)*/
1620 /*(* workarounds *)*/
1621 /*(*----------------------------*)*/
1622
1623 /* It would be very nice if we could make declarator aware that this is
1624 coming from a function definition. Then on the ( and ) cases, it could
1625 set the state to something other than InParameter. Then the case
1626 (TIdent (s, i1)::(TComma _|TCPar _)::_ , (TComma _ |TOPar _)::_ )
1627 in parsing_hacks.ml would not have to consider K&R variable declarations
1628 as typedefs. Unfortunately, doing something about this problem seems to
1629 introduce conflicts in the parser. */
1630
1631 declaratorfd:
1632 | declarator { et "declaratorfd" (); $1, Ast_c.noattr }
1633 /*(* gccext: *)*/
1634 | attributes declarator { et "declaratorfd" (); $2, $1 }
1635 | declarator attributes { et "declaratorfd" (); $1, Ast_c.noattr }
1636
1637
1638
1639 /*(*************************************************************************)*/
1640 /*(* cpp directives *)*/
1641 /*(*************************************************************************)*/
1642
1643 cpp_directive:
1644 | TIncludeStart TIncludeFilename
1645 {
1646 let (i1, in_ifdef) = $1 in
1647 let (s, i2) = $2 in
1648
1649 (* redo some lexing work :( *)
1650 let inc_file =
1651 match () with
1652 | _ when s =~ "^\"\\(.*\\)\"$" ->
1653 Local (Common.split "/" (matched1 s))
1654 | _ when s =~ "^\\<\\(.*\\)\\>$" ->
1655 NonLocal (Common.split "/" (matched1 s))
1656 | _ ->
1657 Weird s
1658 in
1659 Include { i_include = (inc_file, [i1;i2]);
1660 i_rel_pos = Ast_c.noRelPos();
1661 i_is_in_ifdef = !in_ifdef;
1662 i_content = Ast_c.noi_content;
1663 }
1664 }
1665
1666 | TDefine TIdentDefine define_val TDefEOL
1667 { Define ((fst $2, [$1; snd $2;$4]), (DefineVar, $3)) }
1668
1669 /*
1670 (* The TOParDefine is introduced to avoid ambiguity with previous rules.
1671 * A TOParDefine is a TOPar that was just next to the ident.
1672 *)*/
1673 | TDefine TIdentDefine TOParDefine param_define_list TCPar define_val TDefEOL
1674 { Define
1675 ((fst $2, [$1; snd $2; $7]),
1676 (DefineFunc ($4, [$3;$5]), $6))
1677 }
1678
1679 | TUndef TIdentDefine TDefEOL
1680 { Define((fst $2, [$1; snd $2; $3]), (Undef,DefineEmpty)) }
1681 | TCppDirectiveOther { PragmaAndCo ([$1]) }
1682
1683
1684
1685
1686
1687 /*(* perhaps better to use assign_expr ? but in that case need
1688 * do a assign_expr_of_string in parse_c
1689 *)*/
1690 define_val:
1691 | expr { DefineExpr $1 }
1692 | statement { DefineStmt $1 }
1693 | decl { DefineStmt (mk_st (Decl ($1 Ast_c.NotLocalDecl)) Ast_c.noii) }
1694
1695 /*(*old:
1696 * | TypedefIdent { DefineType (nQ,(TypeName(fst $1,noTypedefDef()),[snd $1]))}
1697 * get conflicts:
1698 * | spec_qualif_list TMul
1699 * { let (returnType, _) = fixDeclSpecForDecl $1 in DefineType returnType }
1700 *)
1701 */
1702 | decl_spec
1703 { let returnType = fixDeclSpecForMacro $1 in
1704 DefineType returnType
1705 }
1706 | decl_spec abstract_declarator
1707 { let returnType = fixDeclSpecForMacro $1 in
1708 let typ = $2 returnType in
1709 DefineType typ
1710 }
1711
1712 /* can be in conflict with decl_spec, maybe change fixDeclSpecForMacro
1713 * to also allow storage ?
1714 | storage_class_spec { DefineTodo }
1715 | Tinline { DefineTodo }
1716 */
1717
1718 /*(* a few special cases *)*/
1719 | stat_or_decl stat_or_decl_list { DefineTodo }
1720 /*
1721 | statement statement { DefineTodo }
1722 | decl function_definition { DefineTodo }
1723 */
1724
1725
1726
1727
1728 | function_definition { DefineFunction $1 }
1729
1730 | TOBraceDefineInit initialize_list gcc_comma_opt_struct TCBrace comma_opt
1731 { DefineInit (InitList (List.rev $2), [$1;$4]++$3++$5) }
1732
1733 /*(* note: had a conflict before when were putting TInt instead of expr *)*/
1734 | Tdo statement Twhile TOPar expr TCPar
1735 {
1736 (* TOREPUT
1737 if fst $5 <> "0"
1738 then pr2 "WEIRD: in macro and have not a while(0)";
1739 *)
1740 DefineDoWhileZero (($2,$5), [$1;$3;$4;$6])
1741 }
1742
1743 | Tasm TOPar asmbody TCPar { DefineTodo }
1744 | Tasm Tvolatile TOPar asmbody TCPar { DefineTodo }
1745
1746 /*(* aliases macro *)*/
1747 | TMacroAttr { DefineTodo }
1748
1749 | /*(* empty *)*/ { DefineEmpty }
1750
1751
1752
1753
1754 param_define:
1755 | TIdent { mk_string_wrap $1 }
1756 | TypedefIdent { mk_string_wrap $1 }
1757 | TDefParamVariadic { mk_string_wrap $1 }
1758 | TEllipsis { "...", [$1] }
1759 /*(* they reuse keywords :( *)*/
1760 | Tregister { "register", [$1] }
1761
1762
1763
1764
1765 cpp_ifdef_directive:
1766 | TIfdef
1767 { let (tag,ii) = $1 in
1768 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1769 | TIfdefelse
1770 { let (tag,ii) = $1 in
1771 IfdefDirective ((IfdefElse, IfdefTag (Common.some !tag)), [ii]) }
1772 | TIfdefelif
1773 { let (tag,ii) = $1 in
1774 IfdefDirective ((IfdefElseif, IfdefTag (Common.some !tag)), [ii]) }
1775 | TEndif
1776 { let (tag,ii) = $1 in
1777 IfdefDirective ((IfdefEndif, IfdefTag (Common.some !tag)), [ii]) }
1778
1779 | TIfdefBool
1780 { let (_b, tag,ii) = $1 in
1781 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1782 | TIfdefMisc
1783 { let (_b, tag,ii) = $1 in
1784 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1785 | TIfdefVersion
1786 { let (_b, tag,ii) = $1 in
1787 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1788
1789
1790 /*(* cppext: *)*/
1791 cpp_other:
1792 /*(* no conflict ? no need for a TMacroTop ? apparently not as at toplevel
1793 * the rule are slightly different, they cant be statement and so expr
1794 * at the top, only decl or function definition.
1795 *)*/
1796 | identifier TOPar argument_list TCPar TPtVirg
1797 {
1798 Declaration (MacroDecl ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]))
1799 (* old: MacroTop (fst $1, $3, [snd $1;$2;$4;$5]) *)
1800 }
1801
1802 /*(* TCParEOL to fix the end-of-stream bug of ocamlyacc *)*/
1803 | identifier TOPar argument_list TCParEOL
1804 { MacroTop (fst $1, $3, [snd $1;$2;$4;fakeInfo()]) }
1805
1806 /*(* ex: EXPORT_NO_SYMBOLS; *)*/
1807 | identifier TPtVirg { EmptyDef [snd $1;$2] }
1808
1809
1810
1811 /*(*************************************************************************)*/
1812 /*(* celem *)*/
1813 /*(*************************************************************************)*/
1814
1815 external_declaration:
1816 | function_definition { Definition $1 }
1817 | decl { Declaration ($1 Ast_c.NotLocalDecl) }
1818
1819
1820 celem:
1821 | external_declaration { $1 }
1822
1823 /*(* cppext: *)*/
1824 | cpp_directive
1825 { CppTop $1 }
1826 | cpp_other
1827 { $1 }
1828 | cpp_ifdef_directive /* (*external_declaration_list ...*)*/
1829 { IfdefTop $1 }
1830
1831 /*(* can have asm declaration at toplevel *)*/
1832 | Tasm TOPar asmbody TCPar TPtVirg { EmptyDef [$1;$2;$4;$5] }
1833
1834 /*
1835 (* in ~/kernels/src/linux-2.5.2/drivers/isdn/hisax/isdnl3.c sometimes
1836 * the function ends with }; instead of just }
1837 * can also remove this rule and report "parse error" pb to morton
1838 *)*/
1839 | TPtVirg { EmptyDef [$1] }
1840
1841
1842 | EOF { FinalDef $1 }
1843
1844
1845
1846
1847 /*(*************************************************************************)*/
1848 /*(* some generic workarounds *)*/
1849 /*(*************************************************************************)*/
1850
1851 tobrace: TOBrace { LP.push_context LP.InFunction; LP.new_scope (); $1 }
1852 tcbrace: TCBrace { LP.pop_context(); LP.del_scope (); $1 }
1853
1854 tobrace_enum: TOBrace { LP.push_context LP.InEnum; $1 }
1855 tcbrace_enum: TCBrace { LP.pop_context (); $1 }
1856
1857 tobrace_ini: TOBrace { LP.push_context LP.InInitializer; $1 }
1858 tcbrace_ini: TCBrace { LP.pop_context (); $1 }
1859
1860 tobrace_struct: TOBrace { LP.push_context LP.InStruct; $1}
1861 tcbrace_struct: TCBrace { LP.pop_context (); $1 }
1862
1863
1864
1865
1866 topar: TOPar
1867 { LP.new_scope ();et "topar" ();
1868 LP.push_context LP.InParameter;
1869 $1
1870 }
1871 tcpar: TCPar
1872 { LP.del_scope ();dt "tcpar" ();
1873 LP.pop_context ();
1874 $1
1875 }
1876
1877
1878
1879
1880 /*(*************************************************************************)*/
1881 /*(* xxx_list, xxx_opt *)*/
1882 /*(*************************************************************************)*/
1883
1884
1885 /*(* old:
1886 compound2:
1887 | { ([],[]) }
1888 | statement_list { ([], $1) }
1889 | decl_list { ($1, []) }
1890 | decl_list statement_list { ($1,$2) }
1891
1892 statement_list: stat_or_decl_list { $1 }
1893 *)*/
1894
1895
1896 /*(*
1897 decl_list:
1898 | decl { [$1] }
1899 | decl_list decl { $1 ++ [$2] }
1900
1901 statement_list:
1902 | statement { [$1] }
1903 | statement_list statement { $1 ++ [$2] }
1904 *)*/
1905
1906
1907
1908
1909
1910 string_list:
1911 | string_elem { $1 }
1912 | string_list string_elem { $1 ++ $2 }
1913
1914 colon_asm_list:
1915 | colon_asm { [$1] }
1916 | colon_asm_list colon_asm { $1 ++ [$2] }
1917
1918 colon_option_list:
1919 | colon_option { [$1, []] }
1920 | colon_option_list TComma colon_option { $1 ++ [$3, [$2]] }
1921
1922
1923 argument_list_ne:
1924 | argument_ne { [$1, []] }
1925 | argument_list_ne TComma argument { $1 ++ [$3, [$2]] }
1926
1927 argument_list:
1928 | argument { [$1, []] }
1929 | argument_list TComma argument { $1 ++ [$3, [$2]] }
1930
1931 /*(*
1932 expression_list:
1933 | assign_expr { [$1, []] }
1934 | expression_list TComma assign_expr { $1 ++ [$3, [$2]] }
1935 *)*/
1936
1937
1938 struct_decl_list:
1939 | struct_decl { [$1] }
1940 | struct_decl_list struct_decl { $1 ++ [$2] }
1941
1942
1943 struct_declarator_list:
1944 | struct_declarator { [$1, []] }
1945 | struct_declarator_list TComma struct_declarator { $1 ++ [$3, [$2]] }
1946
1947
1948 enumerator_list:
1949 | enumerator { [$1, []] }
1950 | enumerator_list TComma enumerator { $1 ++ [$3, [$2]] }
1951
1952
1953 init_declarator_list:
1954 | init_declarator { [$1, []] }
1955 | init_declarator_list TComma init_declarator { $1 ++ [$3, [$2]] }
1956
1957
1958 parameter_list:
1959 | parameter_decl { [$1, []] }
1960 | parameter_list TComma parameter_decl { $1 ++ [$3, [$2]] }
1961
1962 taction_list_ne:
1963 | TAction { [$1] }
1964 | TAction taction_list_ne { $1 :: $2 }
1965
1966 taction_list:
1967 /*old: was generating conflict, hence now taction_list_ne
1968 | (* empty *) { [] }
1969 | TAction { [$1] }
1970 | taction_list TAction { $1 ++ [$2] }
1971 */
1972 | { [] }
1973 | TAction taction_list { $1 :: $2 }
1974
1975 param_define_list:
1976 | /*(* empty *)*/ { [] }
1977 | param_define { [$1, []] }
1978 | param_define_list TComma param_define { $1 ++ [$3, [$2]] }
1979
1980 designator_list:
1981 | designator { [$1] }
1982 | designator_list designator { $1 ++ [$2] }
1983
1984 attribute_list:
1985 | attribute { [$1] }
1986 | attribute_list attribute { $1 ++ [$2] }
1987
1988 attribute_storage_list:
1989 | attribute_storage { [$1] }
1990 | attribute_storage_list attribute_storage { $1 ++ [$2] }
1991
1992
1993 attributes: attribute_list { $1 }
1994
1995
1996
1997 /*(* gccext: which allow a trailing ',' in enum, as in perl *)*/
1998 gcc_comma_opt:
1999 | TComma { [$1] }
2000 | /*(* empty *)*/ { [] }
2001
2002 comma_opt:
2003 | TComma { [$1] }
2004 | /*(* empty *)*/ { [] }
2005
2006 /*(*
2007 gcc_opt_virg:
2008 | TPtVirg { }
2009 | { }
2010 *)*/
2011
2012 gcc_opt_expr:
2013 | expr { Some $1 }
2014 | /*(* empty *)*/ { None }
2015
2016 /*(*
2017 opt_ptvirg:
2018 | TPtVirg { [$1] }
2019 | { [] }
2020 *)*/
2021
2022
2023 expr_opt:
2024 | expr { Some $1 }
2025 | /*(* empty *)*/ { None }
2026