permit multiline comments and strings in macros
[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 module T = Token_c
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 86)
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 x),ii2)} as _v)) ->
102 raise (Semantic ((Printf.sprintf "two or more data types: t %s ii %s\ntypeD %s ii2 %s\n" (Dumper.dump t) (Dumper.dump ii) (Dumper.dump x) (Dumper.dump ii2)), fake_pi))
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_once ("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_once ("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 %token <string * Ast_c.info> TKRParam
404 %token <string * Ast_c.info> Tconstructorname /* parsing_hack for c++ */
405 /*(* appears mostly after some fix_xxx in parsing_hack *)*/
406 %token <string * Ast_c.info> TypedefIdent
407
408
409 /*
410 (* Some tokens like TOPar and TCPar are used as synchronisation stuff,
411 * in parsing_hack.ml. So if define special tokens like TOParDefine and
412 * TCParEOL, then take care to also modify in Token_helpers.
413 *)
414 */
415
416 %token <Ast_c.info> TOPar TCPar TOBrace TCBrace TOCro TCCro
417 %token <Ast_c.info> TDot TComma TPtrOp
418 %token <Ast_c.info> TInc TDec
419 %token <Ast_c.assignOp * Ast_c.info> TAssign
420 %token <Ast_c.info> TEq
421 %token <Ast_c.info> TWhy TTilde TBang
422 %token <Ast_c.info> TEllipsis
423 %token <Ast_c.info> TDotDot
424
425 %token <Ast_c.info> TPtVirg
426 %token <Ast_c.info>
427 TOrLog TAndLog TOr TXor TAnd TEqEq TNotEq TInf TSup TInfEq TSupEq
428 TShl TShr
429 TPlus TMinus TMul TDiv TMod TMin TMax
430
431 %token <Ast_c.info>
432 Tchar Tshort Tint Tdouble Tfloat Tlong Tunsigned Tsigned Tvoid
433 Tsize_t Tssize_t Tptrdiff_t
434 Tauto Tregister Textern Tstatic
435 Ttypedef
436 Tconst Tvolatile
437 Tstruct Tunion Tenum
438 Tbreak Telse Tswitch Tcase Tcontinue Tfor Tdo Tif Twhile Treturn
439 Tgoto Tdefault
440 Tsizeof Tnew Tdelete TOParCplusplusInit Tnamespace
441
442 /*(* C99 *)*/
443 %token <Ast_c.info>
444 Trestrict
445
446 /*(*-----------------------------------------*)*/
447 /*(* gccext: extra tokens *)*/
448 /*(*-----------------------------------------*)*/
449 %token <Ast_c.info> Tasm
450 %token <Ast_c.info> Tattribute
451 %token <Ast_c.info> TattributeNoarg
452 %token <Ast_c.info> Tinline
453 %token <Ast_c.info> Ttypeof
454
455 /*(*-----------------------------------------*)*/
456 /*(* cppext: extra tokens *)*/
457 /*(*-----------------------------------------*)*/
458 /*(* coupling with Token_helpers.is_cpp_token *)*/
459
460
461 /*(*---------------*)*/
462 /*(* define *)*/
463 /*(*---------------*)*/
464
465 %token <Ast_c.info> TDefine
466 %token <(string * Ast_c.info)> TDefParamVariadic
467
468 /*(* disappear after fix_tokens_define *)*/
469 %token <Ast_c.info> TCppEscapedNewline
470
471 %token <Ast_c.info> TCppConcatOp
472
473 /*(* appear after fix_tokens_define *)*/
474 %token <Ast_c.info> TOParDefine
475 %token <Ast_c.info> TOBraceDefineInit
476
477 %token <(string * Ast_c.info)> TIdentDefine /*(* same *)*/
478 %token <Ast_c.info> TDefEOL /*(* same *)*/
479
480
481 /*(*---------------*)*/
482 /*(* include *)*/
483 /*(*---------------*)*/
484
485
486 /*(* used only in lexer_c, then transformed in comment or splitted in tokens *)*/
487 %token <(string * string * bool ref * Ast_c.info)> TInclude
488
489 /*(* tokens coming from above, generated in parse_c from TInclude, etc *)*/
490 %token <(Ast_c.info * bool ref)> TIncludeStart
491 %token <(string * Ast_c.info)> TIncludeFilename
492
493
494 /*(*---------------*)*/
495 /*(* ifdef *)*/
496 /*(*---------------*)*/
497
498 /*(* coupling: Token_helpers.is_cpp_instruction *)*/
499 %token <((int * int) option ref * Ast_c.info)>
500 TIfdef TIfdefelse TIfdefelif TEndif
501 %token <(bool * (int * int) option ref * Ast_c.info)>
502 TIfdefBool TIfdefMisc TIfdefVersion
503
504 /*(*---------------*)*/
505 /*(* other *)*/
506 /*(*---------------*)*/
507
508 %token <Ast_c.info> TUndef
509
510 %token <Ast_c.info> TCppDirectiveOther
511
512 /*(*---------------*)*/
513 /*(* macro use *)*/
514 /*(*---------------*)*/
515
516 /*(* appear after fix_tokens_cpp, cf also parsing_hacks#hint *)*/
517
518 %token <(string * Ast_c.info)> TMacroAttr
519 %token <(string * Ast_c.info)> TMacroStmt
520 %token <(string * Ast_c.info)> TMacroIdentBuilder
521 /*(* no need value for the moment *)*/
522 %token <(string * Ast_c.info)> TMacroString
523 %token <(string * Ast_c.info)> TMacroDecl
524 %token <Ast_c.info> TMacroDeclConst
525
526 %token <(string * Ast_c.info)> TMacroIterator
527 /*(*
528 %token <(string * Ast_c.info)> TMacroTop
529 %token <(string * Ast_c.info)> TMacroStructDecl
530 *)*/
531
532 %token <(string * Ast_c.info)> TMacroAttrStorage
533
534
535 /*(*---------------*)*/
536 /*(* other *)*/
537 /*(*---------------*)*/
538
539
540 /*(* should disappear after parsing_hack *)*/
541 %token <Ast_c.info> TCommentSkipTagStart TCommentSkipTagEnd
542
543
544 /*(* appear after parsing_hack *)*/
545 %token <Ast_c.info> TCParEOL
546
547 %token <Ast_c.info> TAction
548
549
550 /*(* TCommentMisc still useful ? obsolete ? *)*/
551 %token <Ast_c.info> TCommentMisc
552 %token <(Token_c.cppcommentkind * Ast_c.info)> TCommentCpp
553
554
555 /*(*-----------------------------------------*)*/
556 %token <Ast_c.info> EOF
557
558 /*(*-----------------------------------------*)*/
559
560 /*(* must be at the top so that it has the lowest priority *)*/
561 %nonassoc SHIFTHERE
562
563 %nonassoc Telse
564
565 %left TOrLog
566 %left TAndLog
567 %left TOr
568 %left TXor
569 %left TAnd
570 %left TEqEq TNotEq
571 %left TInf TSup TInfEq TSupEq
572 %left TShl TShr
573 %left TPlus TMinus
574 %left TMul TDiv TMod TMin TMax
575
576 /*(*************************************************************************)*/
577 /*(* Rules type declaration *)*/
578 /*(*************************************************************************)*/
579
580 %start main celem statement expr type_name
581 %type <Ast_c.program> main
582 %type <Ast_c.toplevel> celem
583
584 %type <Ast_c.statement> statement
585 %type <Ast_c.expression> expr
586 %type <Ast_c.fullType> type_name
587
588 %%
589 /*(*************************************************************************)*/
590 /*
591 (* TOC:
592 * toplevel (obsolete)
593 *
594 * ident
595 * expression
596 * statement
597 * types with
598 * - left part (type_spec, qualif),
599 * - right part (declarator, abstract declarator)
600 * - aux part (parameters)
601 * declaration, storage, initializers
602 * struct
603 * enum
604 * cpp directives
605 * celem (=~ main)
606 *
607 * generic workarounds (obrace, cbrace for context setting)
608 * xxx_list, xxx_opt
609 *)
610 */
611 /*(*************************************************************************)*/
612
613 /*(*************************************************************************)*/
614 /*(* toplevel *)*/
615 /*(*************************************************************************)*/
616 /*(* no more used; now that use error recovery *)*/
617
618 main:
619 translation_unit EOF { $1 }
620
621 translation_unit:
622 |
623 { [] }
624 | translation_unit external_declaration
625 { !LP._lexer_hint.context_stack <- [LP.InTopLevel]; $1 ++ [$2] }
626 | translation_unit Tnamespace TIdent TOBrace translation_unit TCBrace
627 { !LP._lexer_hint.context_stack <- [LP.InTopLevel];
628 $1 ++ [Namespace ($5, [$2; snd $3; $4; $6])] }
629
630
631 /*(*************************************************************************)*/
632 /*(* ident *)*/
633 /*(*************************************************************************)*/
634
635 /*(* Why this ? Why not s/ident/TIdent ? cos there is multiple namespaces in C,
636 * so a label can have the same name that a typedef, same for field and tags
637 * hence sometimes the use of ident instead of TIdent.
638 *)*/
639 ident:
640 | TIdent { $1 }
641 | TypedefIdent { $1 }
642
643
644 identifier:
645 | TIdent { $1 }
646
647 /*
648 (* cppext: string concatenation of idents
649 * also cppext: gccext: ##args for variadic macro
650 *)
651 */
652 identifier_cpp:
653 | TIdent
654 { RegularName (mk_string_wrap $1) }
655 | ident_extra_cpp { $1 }
656
657 ident_cpp:
658 | TIdent
659 { RegularName (mk_string_wrap $1) }
660 | TypedefIdent
661 { RegularName (mk_string_wrap $1) }
662 | ident_extra_cpp { $1 }
663
664 ident_extra_cpp:
665 | TIdent TCppConcatOp identifier_cpp_list
666 {
667 CppConcatenatedName (
668 match $3 with
669 | [] -> raise (Impossible 87)
670 | (x,concatnull)::xs ->
671 assert(null concatnull);
672 (mk_string_wrap $1, [])::(x,[$2])::xs
673 )
674 }
675 | TCppConcatOp TIdent
676 { CppVariadicName (fst $2, [$1; snd $2]) }
677 | TMacroIdentBuilder TOPar param_define_list TCPar
678 { CppIdentBuilder ((fst $1, [snd $1;$2;$4]), $3) }
679
680 identifier_cpp_list:
681 | TIdent { [mk_string_wrap $1, []] }
682 | identifier_cpp_list TCppConcatOp TIdent { $1 ++ [mk_string_wrap $3, [$2]] }
683
684 /*(*************************************************************************)*/
685 /*(* expr *)*/
686 /*(*************************************************************************)*/
687
688 expr:
689 | assign_expr { $1 }
690 | expr TComma assign_expr { mk_e (Sequence ($1,$3)) [$2] }
691
692 /*(* bugfix: in C grammar they put unary_expr, but in fact it must be
693 * cast_expr, otherwise (int * ) xxx = &yy; is not allowed
694 *)*/
695 assign_expr:
696 | cond_expr { $1 }
697 | cast_expr TAssign assign_expr { mk_e(Assignment ($1,fst $2,$3)) [snd $2]}
698 | cast_expr TEq assign_expr { mk_e(Assignment ($1,SimpleAssign,$3)) [$2]}
699
700 /*(* gccext: allow optional then part hence gcc_opt_expr
701 * bugfix: in C grammar they put TDotDot cond_expr, but in fact it must be
702 * assign_expr, otherwise pnp ? x : x = 0x388 is not allowed
703 *)*/
704 cond_expr:
705 | arith_expr
706 { $1 }
707 | arith_expr TWhy gcc_opt_expr TDotDot assign_expr
708 { mk_e (CondExpr ($1,$3,$5)) [$2;$4] }
709
710
711 arith_expr:
712 | cast_expr { $1 }
713 | arith_expr TMul arith_expr { mk_e(Binary ($1, Arith Mul, $3)) [$2] }
714 | arith_expr TDiv arith_expr { mk_e(Binary ($1, Arith Div, $3)) [$2] }
715 | arith_expr TMin arith_expr { mk_e(Binary ($1, Arith Min, $3)) [$2] }
716 | arith_expr TMax arith_expr { mk_e(Binary ($1, Arith Max, $3)) [$2] }
717 | arith_expr TMod arith_expr { mk_e(Binary ($1, Arith Mod, $3)) [$2] }
718 | arith_expr TPlus arith_expr { mk_e(Binary ($1, Arith Plus, $3)) [$2] }
719 | arith_expr TMinus arith_expr { mk_e(Binary ($1, Arith Minus, $3)) [$2] }
720 | arith_expr TShl arith_expr { mk_e(Binary ($1, Arith DecLeft, $3)) [$2] }
721 | arith_expr TShr arith_expr { mk_e(Binary ($1, Arith DecRight, $3)) [$2] }
722 | arith_expr TInf arith_expr { mk_e(Binary ($1, Logical Inf, $3)) [$2] }
723 | arith_expr TSup arith_expr { mk_e(Binary ($1, Logical Sup, $3)) [$2] }
724 | arith_expr TInfEq arith_expr { mk_e(Binary ($1, Logical InfEq, $3)) [$2] }
725 | arith_expr TSupEq arith_expr { mk_e(Binary ($1, Logical SupEq, $3)) [$2] }
726 | arith_expr TEqEq arith_expr { mk_e(Binary ($1, Logical Eq, $3)) [$2] }
727 | arith_expr TNotEq arith_expr { mk_e(Binary ($1, Logical NotEq, $3)) [$2] }
728 | arith_expr TAnd arith_expr { mk_e(Binary ($1, Arith And, $3)) [$2] }
729 | arith_expr TOr arith_expr { mk_e(Binary ($1, Arith Or, $3)) [$2] }
730 | arith_expr TXor arith_expr { mk_e(Binary ($1, Arith Xor, $3)) [$2] }
731 | arith_expr TAndLog arith_expr { mk_e(Binary ($1, Logical AndLog, $3)) [$2] }
732 | arith_expr TOrLog arith_expr { mk_e(Binary ($1, Logical OrLog, $3)) [$2] }
733
734 cast_expr:
735 | unary_expr { $1 }
736 | topar2 type_name tcpar2 cast_expr { mk_e(Cast ($2, $4)) [$1;$3] }
737
738 unary_expr:
739 | postfix_expr { $1 }
740 | TInc unary_expr { mk_e(Infix ($2, Inc)) [$1] }
741 | TDec unary_expr { mk_e(Infix ($2, Dec)) [$1] }
742 | unary_op cast_expr { mk_e(Unary ($2, fst $1)) [snd $1] }
743 | Tsizeof unary_expr { mk_e(SizeOfExpr ($2)) [$1] }
744 | Tsizeof topar2 type_name tcpar2 { mk_e(SizeOfType ($3)) [$1;$2;$4] }
745 | Tnew new_argument { mk_e(New (None, $2)) [$1] }
746 | Tnew TOPar argument_list_ne TCPar new_argument { mk_e(New (Some $3, $5)) [$1; $2; $4] }
747 | Tdelete cast_expr { mk_e(Delete $2) [$1] }
748
749 new_argument:
750 | TIdent TOPar argument_list_ne TCPar
751 { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
752 Left (mk_e(FunCall (fn, $3)) [$2;$4]) }
753 | TIdent TOPar TCPar
754 { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
755 Left(mk_e(FunCall (fn, [])) [$2;$3]) }
756 | TypedefIdent TOPar argument_list_ne TCPar
757 { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
758 Left (mk_e(FunCall (fn, $3)) [$2;$4]) }
759 | TypedefIdent TOPar TCPar
760 { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in
761 Left (mk_e(FunCall (fn, [])) [$2;$3]) }
762 | type_spec
763 { let ty = addTypeD ($1,nullDecl) in
764 let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam ty in
765 Right (ArgType { p_namei = None; p_type = returnType;
766 p_register = hasreg, iihasreg;
767 } )
768 }
769 | new_argument TOCro expr TCCro
770 {
771 match $1 with
772 Left(e) -> Left(mk_e(ArrayAccess (e, $3)) [$2;$4])
773 | Right(ArgType(ty)) -> (* lots of hacks to make the right type *)
774 let fty = mk_ty (Array (Some $3, ty.Ast_c.p_type)) [$2;$4] in
775 let pty = { ty with p_type = fty } in
776 Right(ArgType pty)
777 | _ -> raise (Impossible 88)
778 }
779
780 unary_op:
781 | TAnd { GetRef, $1 }
782 | TMul { DeRef, $1 }
783 | TPlus { UnPlus, $1 }
784 | TMinus { UnMinus, $1 }
785 | TTilde { Tilde, $1 }
786 | TBang { Not, $1 }
787 /*(* gccext: have that a lot in old kernel to get address of local label.
788 * cf gcc manual "local labels as values".
789 *)*/
790 | TAndLog { GetRefLabel, $1 }
791
792 postfix_expr:
793 | primary_expr { $1 }
794 | postfix_expr TOCro expr TCCro
795 { mk_e(ArrayAccess ($1, $3)) [$2;$4] }
796 | postfix_expr TOPar argument_list_ne TCPar
797 { mk_e(FunCall ($1, $3)) [$2;$4] }
798 | postfix_expr TOPar TCPar { mk_e(FunCall ($1, [])) [$2;$3] }
799 | postfix_expr TDot ident_cpp { mk_e(RecordAccess ($1,$3)) [$2] }
800 | postfix_expr TPtrOp ident_cpp { mk_e(RecordPtAccess ($1,$3)) [$2] }
801 | postfix_expr TInc { mk_e(Postfix ($1, Inc)) [$2] }
802 | postfix_expr TDec { mk_e(Postfix ($1, Dec)) [$2] }
803
804 /*(* gccext: also called compound literals *)*/
805 | topar2 type_name tcpar2 TOBrace TCBrace
806 { mk_e(Constructor ($2, (InitList [], [$4;$5]))) [$1;$3] }
807 | topar2 type_name tcpar2 TOBrace initialize_list gcc_comma_opt TCBrace
808 { mk_e(Constructor ($2, (InitList (List.rev $5),[$4;$7]++$6))) [$1;$3] }
809
810
811 primary_expr:
812 | identifier_cpp { mk_e(Ident ($1)) [] }
813 | TInt
814 { let (str,(sign,base)) = fst $1 in
815 mk_e(Constant (Int (str,Si(sign,base)))) [snd $1] }
816 | TFloat { mk_e(Constant (Float (fst $1))) [snd $1] }
817 | TString { mk_e(Constant (String (fst $1))) [snd $1] }
818 | TChar { mk_e(Constant (Char (fst $1))) [snd $1] }
819 | TOPar expr TCPar { mk_e(ParenExpr ($2)) [$1;$3] } /*(* forunparser: *)*/
820
821 /*(* gccext: cppext: TODO better ast ? *)*/
822 | TMacroString { mk_e(Constant (MultiString [fst $1])) [snd $1] }
823 | string_elem string_list
824 { mk_e(Constant (MultiString ["TODO: MultiString"])) ($1 ++ $2) }
825
826 /*(* gccext: allow statement as expressions via ({ statement }) *)*/
827 | TOPar compound TCPar { mk_e(StatementExpr ($2)) [$1;$3] }
828
829
830
831 /*(*----------------------------*)*/
832 /*(* cppext: *)*/
833 /*(*----------------------------*)*/
834
835 /*(* cppext: *)*/
836 /*(* to avoid conflicts have to introduce a _not_empty (ne) version *)*/
837 argument_ne:
838 | assign_expr { Left $1 }
839 | parameter_decl { Right (ArgType $1) }
840 | action_higherordermacro_ne { Right (ArgAction $1) }
841
842
843 argument:
844 | assign_expr { Left $1 }
845 | parameter_decl { Right (ArgType $1) }
846 /*(* had conflicts before, but julia fixed them *)*/
847 | action_higherordermacro { Right (ArgAction $1) }
848
849 action_higherordermacro_ne:
850 | taction_list_ne
851 { if null $1
852 then ActMisc [Ast_c.fakeInfo()]
853 else ActMisc $1
854 }
855
856
857 action_higherordermacro:
858 | taction_list
859 { if null $1
860 then ActMisc [Ast_c.fakeInfo()]
861 else ActMisc $1
862 }
863
864
865 /*(*----------------------------*)*/
866 /*(* workarounds *)*/
867 /*(*----------------------------*)*/
868
869 /*(* would like evalInt $1 but require too much info *)*/
870 const_expr: cond_expr { $1 }
871
872
873 topar2: TOPar { et "topar2" (); $1 }
874 tcpar2: TCPar { et "tcpar2" (); $1 (*TODO? et ? sure ? c pas dt plutot ? *) }
875
876
877
878 /*(*************************************************************************)*/
879 /*(* statement *)*/
880 /*(*************************************************************************)*/
881
882 statement: statement2 { mk_st (fst $1) (snd $1) }
883
884 statement2:
885 | labeled { Labeled (fst $1), snd $1 }
886 | compound { Compound (fst $1), snd $1 }
887 | expr_statement { ExprStatement(fst $1), snd $1 }
888 | selection { Selection (fst $1), snd $1 ++ [fakeInfo()] }
889 | iteration { Iteration (fst $1), snd $1 ++ [fakeInfo()] }
890 | jump TPtVirg { Jump (fst $1), snd $1 ++ [$2] }
891
892 /*(* gccext: *)*/
893 | Tasm TOPar asmbody TCPar TPtVirg { Asm $3, [$1;$2;$4;$5] }
894 | Tasm Tvolatile TOPar asmbody TCPar TPtVirg { Asm $4, [$1;$2;$3;$5;$6] }
895
896 /*(* cppext: *)*/
897 | TMacroStmt { MacroStmt, [snd $1] }
898
899
900
901
902 /*(* note that case 1: case 2: i++; would be correctly parsed, but with
903 * a Case (1, (Case (2, i++))) :(
904 *)*/
905 labeled:
906 | ident_cpp TDotDot sw_stat_or_decl { Label ($1, $3), [$2] }
907 | Tcase const_expr TDotDot sw_stat_or_decl { Case ($2, $4), [$1; $3] }
908 | Tcase const_expr TEllipsis const_expr TDotDot sw_stat_or_decl
909 { CaseRange ($2, $4, $6), [$1;$3;$5] } /*(* gccext: allow range *)*/
910 | Tdefault TDotDot sw_stat_or_decl { Default $3, [$1; $2] }
911
912 sw_stat_or_decl:
913 | decl { mk_st (Decl ($1 Ast_c.LocalDecl)) Ast_c.noii }
914 | statement { $1 }
915
916
917 end_labeled:
918 /*(* gccext: allow toto: }
919 * was generating each 30 shift/Reduce conflicts,
920 * mais ca va, ca fait ce qu'il faut.
921 * update: julia fixed the problem by introducing end_labeled
922 * and modifying below stat_or_decl_list
923 *)*/
924 | ident_cpp TDotDot
925 { Label ($1, (mk_st (ExprStatement None) Ast_c.noii)), [$2] }
926 | Tcase const_expr TDotDot
927 { Case ($2, (mk_st (ExprStatement None) Ast_c.noii)), [$1;$3] }
928 | Tdefault TDotDot
929 { Default (mk_st (ExprStatement None) Ast_c.noii), [$1; $2] }
930
931
932
933
934
935 compound: tobrace compound2 tcbrace { $2, [$1; $3] }
936
937
938 /*
939 (* cppext: because of cpp, some stuff looks like declaration but are in
940 * fact statement but too hard to figure out, and if parse them as
941 * expression, then we force to have first decls and then exprs, then
942 * will have a parse error. So easier to let mix decl/statement.
943 * Moreover it helps to not make such a difference between decl and
944 * statement for further coccinelle phases to factorize code.
945 *)*/
946 compound2:
947 | { ([]) }
948 | stat_or_decl_list { $1 }
949
950
951 stat_or_decl_list:
952 | stat_or_decl { [$1] }
953 /*(* gccext: to avoid conflicts, cf end_labeled above *)*/
954 | end_labeled { [StmtElem (mk_st (Labeled (fst $1)) (snd $1))] }
955 /*(* old: conflicts | stat_or_decl_list stat_or_decl { $1 ++ [$2] } *)*/
956 | stat_or_decl stat_or_decl_list { $1 :: $2 }
957
958 stat_or_decl:
959 | decl { StmtElem (mk_st (Decl ($1 Ast_c.LocalDecl)) Ast_c.noii) }
960 | statement { StmtElem $1 }
961
962 /*(* gccext: *)*/
963 | function_definition { StmtElem (mk_st (NestedFunc $1) Ast_c.noii) }
964
965 /* (* cppext: *)*/
966 | cpp_directive
967 { CppDirectiveStmt $1 }
968 | cpp_ifdef_directive/*(* stat_or_decl_list ...*)*/
969 { IfdefStmt $1 }
970
971
972 expr_statement:
973 | TPtVirg { None, [$1] }
974 | expr TPtVirg { Some $1, [$2] }
975
976 selection:
977 | Tif TOPar expr TCPar statement %prec SHIFTHERE
978 { If ($3, $5, (mk_st (ExprStatement None) Ast_c.noii)), [$1;$2;$4] }
979 | Tif TOPar expr TCPar statement Telse statement
980 { If ($3, $5, $7), [$1;$2;$4;$6] }
981 | Tswitch TOPar expr TCPar statement
982 { Switch ($3,$5), [$1;$2;$4] }
983
984 iteration:
985 | Twhile TOPar expr TCPar statement
986 { While ($3,$5), [$1;$2;$4] }
987 | Tdo statement Twhile TOPar expr TCPar TPtVirg
988 { DoWhile ($2,$5), [$1;$3;$4;$6;$7] }
989 | Tfor TOPar expr_statement expr_statement TCPar statement
990 { For (ForExp $3,$4,(None, []),$6), [$1;$2;$5]}
991 | Tfor TOPar expr_statement expr_statement expr TCPar statement
992 { For (ForExp $3,$4,(Some $5, []),$7), [$1;$2;$6] }
993 /*(* c++ext: for(int i = 0; i < n; i++)*)*/
994 | Tfor TOPar decl expr_statement TCPar statement
995 { For (ForDecl ($3 Ast_c.LocalDecl),$4,(None, []),$6), [$1;$2;$5]}
996 | Tfor TOPar decl expr_statement expr TCPar statement
997 { For (ForDecl ($3 Ast_c.LocalDecl),$4,(Some $5, []),$7), [$1;$2;$6] }
998 /*(* cppext: *)*/
999 | TMacroIterator TOPar argument_list_ne TCPar statement
1000 { MacroIteration (fst $1, $3, $5), [snd $1;$2;$4] }
1001 | TMacroIterator TOPar TCPar statement
1002 { MacroIteration (fst $1, [], $4), [snd $1;$2;$3] }
1003
1004 /*(* the ';' in the caller grammar rule will be appended to the infos *)*/
1005 jump:
1006 | Tgoto ident_cpp { Goto ($2), [$1] }
1007 | Tcontinue { Continue, [$1] }
1008 | Tbreak { Break, [$1] }
1009 | Treturn { Return, [$1] }
1010 | Treturn expr { ReturnExpr $2, [$1] }
1011 | Tgoto TMul expr { GotoComputed $3, [$1;$2] }
1012
1013
1014
1015 /*(*----------------------------*)*/
1016 /*(* gccext: *)*/
1017 /*(*----------------------------*)*/
1018 string_elem:
1019 | TString { [snd $1] }
1020 /*(* cppext: ex= printk (KERN_INFO "xxx" UTS_RELEASE) *)*/
1021 | TMacroString { [snd $1] }
1022
1023
1024 asmbody:
1025 | string_list colon_asm_list { $1, $2 }
1026 | string_list { $1, [] } /*(* in old kernel *)*/
1027
1028
1029 colon_asm: TDotDot colon_option_list { Colon $2, [$1] }
1030
1031 colon_option:
1032 | TString { ColonMisc, [snd $1] }
1033 | TString TOPar asm_expr TCPar { ColonExpr $3, [snd $1; $2;$4] }
1034 /*(* cppext: certainly a macro *)*/
1035 | TOCro identifier TCCro TString TOPar asm_expr TCPar
1036 { ColonExpr $6, [$1;snd $2;$3;snd $4; $5; $7 ] }
1037 | identifier { ColonMisc, [snd $1] }
1038 | /*(* empty *)*/ { ColonMisc, [] }
1039
1040 asm_expr: assign_expr { $1 }
1041
1042 /*(*************************************************************************)*/
1043 /*(* types *)*/
1044 /*(*************************************************************************)*/
1045
1046
1047 /*(*-----------------------------------------------------------------------*)*/
1048 /*(* Type spec, left part of a type *)*/
1049 /*(*-----------------------------------------------------------------------*)*/
1050 type_spec2:
1051 | Tvoid { Right3 (BaseType Void), [$1] }
1052 | Tchar { Right3 (BaseType (IntType CChar)), [$1]}
1053 | Tint { Right3 (BaseType (IntType (Si (Signed,CInt)))), [$1]}
1054 | Tfloat { Right3 (BaseType (FloatType CFloat)), [$1]}
1055 | Tdouble { Right3 (BaseType (FloatType CDouble)), [$1] }
1056 | Tsize_t { Right3 (BaseType SizeType), [$1] }
1057 | Tssize_t { Right3 (BaseType SSizeType), [$1] }
1058 | Tptrdiff_t { Right3 (BaseType PtrDiffType), [$1] }
1059 | Tshort { Middle3 Short, [$1]}
1060 | Tlong { Middle3 Long, [$1]}
1061 | Tsigned { Left3 Signed, [$1]}
1062 | Tunsigned { Left3 UnSigned, [$1]}
1063 | struct_or_union_spec { Right3 (fst $1), snd $1 }
1064 | enum_spec { Right3 (fst $1), snd $1 }
1065
1066 /*
1067 (* parse_typedef_fix1: cant put: TIdent {} cos it make the grammar
1068 * ambiguous, generates lots of conflicts => we must
1069 * use some tricks: we make the lexer and parser cooperate, cf lexerParser.ml.
1070 *
1071 * parse_typedef_fix2: this is not enough, and you must use
1072 * parse_typedef_fix2 to fully manage typedef problems in grammar.
1073 *
1074 * parse_typedef_fix3:
1075 *
1076 * parse_typedef_fix4: try also to do now some consistency checking in
1077 * Parse_c
1078 *)*/
1079 | TypedefIdent
1080 { let name = RegularName (mk_string_wrap $1) in
1081 Right3 (TypeName (name, Ast_c.noTypedefDef())),[] }
1082
1083 | Ttypeof TOPar assign_expr TCPar { Right3 (TypeOfExpr ($3)), [$1;$2;$4] }
1084 | Ttypeof TOPar type_name TCPar { Right3 (TypeOfType ($3)), [$1;$2;$4] }
1085
1086 /*(*----------------------------*)*/
1087 /*(* workarounds *)*/
1088 /*(*----------------------------*)*/
1089
1090 type_spec: type_spec2 { dt "type" (); $1 }
1091
1092 /*(*-----------------------------------------------------------------------*)*/
1093 /*(* Qualifiers *)*/
1094 /*(*-----------------------------------------------------------------------*)*/
1095
1096 type_qualif:
1097 | Tconst { {const=true ; volatile=false}, $1 }
1098 | Tvolatile { {const=false ; volatile=true}, $1 }
1099 /*(* C99 *)*/
1100 | Trestrict { (* TODO *) {const=false ; volatile=false}, $1 }
1101
1102
1103 /*(*-----------------------------------------------------------------------*)*/
1104 /*(* gccext: attributes *)*/
1105 /*(*-----------------------------------------------------------------------*)*/
1106
1107 attribute:
1108 | Tattribute TOPar /*stuff*/ TCPar { raise Todo }
1109 /*(* cppext: *)*/
1110 | TMacroAttr { Attribute (fst $1), [snd $1] }
1111
1112 attribute_storage:
1113 | TMacroAttrStorage { $1 }
1114
1115 type_qualif_attr:
1116 | type_qualif { $1 }
1117 /*(*TODO !!!!! *)*/
1118 | TMacroAttr { {const=true ; volatile=false}, snd $1 }
1119
1120 /*(*-----------------------------------------------------------------------*)*/
1121 /*(* Declarator, right part of a type + second part of decl (the ident) *)*/
1122 /*(*-----------------------------------------------------------------------*)*/
1123
1124 /*
1125 (* declarator return a couple:
1126 * (name, partial type (a function to be applied to return type))
1127 *
1128 * when int* f(int) we must return Func(Pointer int,int) and not
1129 * Pointer (Func(int,int)
1130 *)*/
1131
1132 declarator:
1133 | pointer direct_d { (fst $2, fun x -> x +> $1 +> (snd $2) ) }
1134 | direct_d { $1 }
1135
1136 /*(* so must do int * const p; if the pointer is constant, not the pointee *)*/
1137 pointer:
1138 | tmul { fun x -> mk_ty (Pointer x) [$1] }
1139 | tmul pointer { fun x -> mk_ty (Pointer ($2 x)) [$1] }
1140 | tmul type_qualif_list
1141 { fun x -> ($2.qualifD, mk_tybis (Pointer x) [$1])}
1142 | tmul type_qualif_list pointer
1143 { fun x -> ($2.qualifD, mk_tybis (Pointer ($3 x)) [$1]) }
1144
1145 tmul:
1146 TMul { $1 }
1147 | TAnd
1148 { if !Flag.c_plus_plus
1149 then $1
1150 else
1151 let i = Ast_c.parse_info_of_info $1 in
1152 raise (Semantic("& not allowed in C types, try -c++ option", i)) }
1153
1154
1155 direct_d:
1156 | identifier_cpp
1157 { ($1, fun x -> x) }
1158 | TOPar declarator TCPar /*(* forunparser: old: $2 *)*/
1159 { (fst $2, fun x -> mk_ty (ParenType ((snd $2) x)) [$1;$3]) }
1160 | direct_d tocro tccro
1161 { (fst $1,fun x->(snd $1) (mk_ty (Array (None,x)) [$2;$3])) }
1162 | direct_d tocro const_expr tccro
1163 { (fst $1,fun x->(snd $1) (mk_ty (Array (Some $3,x)) [$2;$4])) }
1164 | direct_d topar tcpar
1165 { (fst $1,
1166 fun x->(snd $1)
1167 (mk_ty (FunctionType (x,(([],(false, []))))) [$2;$3]))
1168 }
1169 | direct_d topar parameter_type_list tcpar
1170 { (fst $1,fun x->(snd $1)
1171 (mk_ty (FunctionType (x, $3)) [$2;$4]))
1172 }
1173
1174
1175 /*(*----------------------------*)*/
1176 /*(* workarounds *)*/
1177 /*(*----------------------------*)*/
1178
1179 tocro: TOCro { et "tocro" ();$1 }
1180 tccro: TCCro { dt "tccro" ();$1 }
1181
1182 /*(*-----------------------------------------------------------------------*)*/
1183 abstract_declarator:
1184 | pointer { $1 }
1185 | direct_abstract_declarator { $1 }
1186 | pointer direct_abstract_declarator { fun x -> x +> $2 +> $1 }
1187
1188 direct_abstract_declarator:
1189 | TOPar abstract_declarator TCPar /*(* forunparser: old: $2 *)*/
1190 { fun x -> mk_ty (ParenType ($2 x)) [$1;$3] }
1191
1192 | TOCro TCCro
1193 { fun x -> mk_ty (Array (None, x)) [$1;$2] }
1194 | TOCro const_expr TCCro
1195 { fun x -> mk_ty (Array (Some $2, x)) [$1;$3] }
1196 | direct_abstract_declarator TOCro TCCro
1197 { fun x -> $1 (mk_ty (Array (None, x)) [$2;$3]) }
1198 | direct_abstract_declarator TOCro const_expr TCCro
1199 { fun x -> $1 (mk_ty (Array (Some $3,x)) [$2;$4]) }
1200 | TOPar TCPar
1201 { fun x -> mk_ty (FunctionType (x, ([], (false, [])))) [$1;$2] }
1202 | topar parameter_type_list tcpar
1203 { fun x -> mk_ty (FunctionType (x, $2)) [$1;$3] }
1204 /*(* subtle: here must also use topar, not TOPar, otherwise if have for
1205 * instance (xxx ( * )(xxx)) cast, then the second xxx may still be a Tident
1206 * but we want to reduce topar, to set the InParameter so that
1207 * parsing_hack can get a chance to change the type of xxx into a typedef.
1208 * That's an example where parsing_hack and the lookahead of ocamlyacc does
1209 * not go very well together ... we got the info too late. We got
1210 * a similar pb with xxx xxx; declaration, cf parsing_hack.ml and the
1211 * "disable typedef cos special case ..." message.
1212 *)*/
1213 | direct_abstract_declarator topar tcpar
1214 { fun x -> $1 (mk_ty (FunctionType (x, (([], (false, []))))) [$2;$3]) }
1215 | direct_abstract_declarator topar parameter_type_list tcpar
1216 { fun x -> $1 (mk_ty (FunctionType (x, $3)) [$2;$4]) }
1217
1218 /*(*-----------------------------------------------------------------------*)*/
1219 /*(* Parameters (use decl_spec not type_spec just for 'register') *)*/
1220 /*(*-----------------------------------------------------------------------*)*/
1221 parameter_type_list:
1222 | parameter_list { ($1, (false, []))}
1223 | parameter_list TComma TEllipsis { ($1, (true, [$2;$3])) }
1224
1225
1226 parameter_decl2:
1227 TKRParam {
1228 let name = RegularName (mk_string_wrap $1) in
1229 LP.add_ident (str_of_name name);
1230 { p_namei = Some name;
1231 p_type = mk_ty NoType [];
1232 p_register = (false, []);
1233 }
1234 }
1235 | decl_spec declaratorp
1236 { let ((returnType,hasreg),iihasreg) = fixDeclSpecForParam $1 in
1237 let (name, ftyp) = $2 in
1238 { p_namei = Some (name);
1239 p_type = ftyp returnType;
1240 p_register = (hasreg, iihasreg);
1241 }
1242 }
1243 | decl_spec abstract_declaratorp
1244 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1 in
1245 { p_namei = None;
1246 p_type = $2 returnType;
1247 p_register = hasreg, iihasreg;
1248 }
1249 }
1250 | decl_spec
1251 { let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam $1 in
1252 { p_namei = None;
1253 p_type = returnType;
1254 p_register = hasreg, iihasreg;
1255 }
1256 }
1257
1258
1259 /*(*----------------------------*)*/
1260 /*(* workarounds *)*/
1261 /*(*----------------------------*)*/
1262
1263 parameter_decl: parameter_decl2 { et "param" (); $1 }
1264 | attributes parameter_decl2 { et "param" (); $2 }
1265
1266 declaratorp:
1267 | declarator { LP.add_ident (str_of_name (fst $1)); $1 }
1268 /*(* gccext: *)*/
1269 | attributes declarator { LP.add_ident (str_of_name (fst $2)); $2 }
1270 | declarator attributes { LP.add_ident (str_of_name (fst $1)); $1 }
1271
1272 abstract_declaratorp:
1273 | abstract_declarator { $1 }
1274 /*(* gccext: *)*/
1275 | attributes abstract_declarator { $2 }
1276
1277 /*(*-----------------------------------------------------------------------*)*/
1278 /*(* helper type rules *)*/
1279 /*(*-----------------------------------------------------------------------*)*/
1280
1281 /*(* for struct and also typename *)*/
1282 /*(* cant put decl_spec cos no storage is allowed for field struct *)*/
1283 spec_qualif_list2:
1284 | type_spec { addTypeD ($1, nullDecl) }
1285 | type_qualif { {nullDecl with qualifD = (fst $1,[snd $1])}}
1286 | type_spec spec_qualif_list { addTypeD ($1,$2) }
1287 | type_qualif spec_qualif_list { addQualifD ($1,$2) }
1288
1289 spec_qualif_list: spec_qualif_list2 { dt "spec_qualif" (); $1 }
1290
1291
1292 /*(* for pointers in direct_declarator and abstract_declarator *)*/
1293 type_qualif_list:
1294 | type_qualif_attr { {nullDecl with qualifD = (fst $1,[snd $1])} }
1295 | type_qualif_list type_qualif_attr { addQualifD ($2,$1) }
1296
1297
1298
1299
1300
1301
1302 /*(*-----------------------------------------------------------------------*)*/
1303 /*(* xxx_type_id *)*/
1304 /*(*-----------------------------------------------------------------------*)*/
1305
1306 type_name:
1307 | spec_qualif_list
1308 { let (returnType, _) = fixDeclSpecForDecl $1 in returnType }
1309 | spec_qualif_list abstract_declaratort
1310 { let (returnType, _) = fixDeclSpecForDecl $1 in $2 returnType }
1311
1312
1313
1314 abstract_declaratort:
1315 | abstract_declarator { $1 }
1316 /*(* gccext: *)*/
1317 | attributes abstract_declarator { $2 }
1318
1319
1320 /*(*************************************************************************)*/
1321 /*(* declaration and initializers *)*/
1322 /*(*************************************************************************)*/
1323
1324 decl2:
1325 | decl_spec TPtVirg
1326 { function local ->
1327 let (returnType,storage) = fixDeclSpecForDecl $1 in
1328 let iistart = Ast_c.fakeInfo () in
1329 DeclList ([{v_namei = None; v_type = returnType;
1330 v_storage = unwrap storage; v_local = local;
1331 v_attr = Ast_c.noattr;
1332 v_type_bis = ref None;
1333 },[]],
1334 ($2::iistart::snd storage))
1335 }
1336 | decl_spec init_declarator_list TPtVirg
1337 { function local ->
1338 let (returnType,storage) = fixDeclSpecForDecl $1 in
1339 let iistart = Ast_c.fakeInfo () in
1340 DeclList (
1341 ($2 +> List.map (fun ((((name,f),attrs), ini), iivirg) ->
1342 let s = str_of_name name in
1343 if fst (unwrap storage) =*= StoTypedef
1344 then LP.add_typedef s;
1345 {v_namei = Some (name, ini);
1346 v_type = f returnType;
1347 v_storage = unwrap storage;
1348 v_local = local;
1349 v_attr = attrs;
1350 v_type_bis = ref None;
1351 },
1352 iivirg
1353 )
1354 ), ($3::iistart::snd storage))
1355 }
1356 /*(* cppext: *)*/
1357
1358 | TMacroDecl TOPar argument_list TCPar TPtVirg
1359 { function _ ->
1360 MacroDecl ((fst $1, $3, true), [snd $1;$2;$4;$5;fakeInfo()]) }
1361 | Tstatic TMacroDecl TOPar argument_list TCPar TPtVirg
1362 { function _ ->
1363 MacroDecl ((fst $2, $4, true), [snd $2;$3;$5;$6;fakeInfo();$1]) }
1364 | Tstatic TMacroDeclConst TMacroDecl TOPar argument_list TCPar TPtVirg
1365 { function _ ->
1366 MacroDecl ((fst $3, $5, true), [snd $3;$4;$6;$7;fakeInfo();$1;$2])}
1367
1368
1369 | TMacroDecl TOPar argument_list TCPar teq initialize TPtVirg
1370 { function _ ->
1371 MacroDeclInit ((fst $1, $3, $6), [snd $1;$2;$4;$5;$7;fakeInfo()]) }
1372 | Tstatic TMacroDecl TOPar argument_list TCPar teq initialize TPtVirg
1373 { function _ ->
1374 MacroDeclInit ((fst $2, $4, $7),[snd $2;$3;$5;$6;$8;fakeInfo();$1]) }
1375 | Tstatic TMacroDeclConst TMacroDecl TOPar argument_list TCPar
1376 teq initialize TPtVirg
1377 { function _ ->
1378 MacroDeclInit
1379 ((fst $3, $5, $8), [snd $3;$4;$6;$7;$9;fakeInfo();$1;$2])}
1380
1381
1382 /*(*-----------------------------------------------------------------------*)*/
1383 decl_spec2:
1384 | storage_class_spec { {nullDecl with storageD = (fst $1, [snd $1]) } }
1385 | type_spec { addTypeD ($1,nullDecl) }
1386 | type_qualif { {nullDecl with qualifD = (fst $1, [snd $1]) } }
1387 | Tinline { {nullDecl with inlineD = (true, [$1]) } }
1388 | storage_class_spec decl_spec2 { addStorageD ($1, $2) }
1389 | type_spec decl_spec2 { addTypeD ($1, $2) }
1390 | type_qualif decl_spec2 { addQualifD ($1, $2) }
1391 | Tinline decl_spec2 { addInlineD ((true, $1), $2) }
1392
1393 /*(* can simplify by putting all in _opt ? must have at least one otherwise
1394 * decl_list is ambiguous ? (no cos have ';' between decl)
1395 *)*/
1396
1397
1398 storage_class_spec2:
1399 | Tstatic { Sto Static, $1 }
1400 | Textern { Sto Extern, $1 }
1401 | Tauto { Sto Auto, $1 }
1402 | Tregister { Sto Register,$1 }
1403 | Ttypedef { StoTypedef, $1 }
1404
1405 storage_class_spec:
1406 /*(* gccext: *)*/
1407 | storage_class_spec2 { $1 }
1408 | storage_class_spec2 attribute_storage_list { $1 (* TODO *) }
1409
1410
1411
1412 /*(*----------------------------*)*/
1413 /*(* workarounds *)*/
1414 /*(*----------------------------*)*/
1415
1416 decl: decl2 { et "decl" (); $1 }
1417 decl_spec: decl_spec2 { dt "declspec" (); $1 }
1418
1419 /*(*-----------------------------------------------------------------------*)*/
1420 /*(* declarators (right part of type and variable) *)*/
1421 /*(*-----------------------------------------------------------------------*)*/
1422 init_declarator2:
1423 | declaratori { ($1, NoInit) }
1424 | declaratori teq initialize { ($1, ValInit($2, $3)) }
1425 /* C++ only */
1426 | declaratori TOParCplusplusInit argument_list TCPar
1427 { ($1, ConstrInit($3,[$2;$4])) }
1428
1429
1430 /*(*----------------------------*)*/
1431 /*(* workarounds *)*/
1432 /*(*----------------------------*)*/
1433 teq: TEq { et "teq" (); $1 }
1434
1435 init_declarator: init_declarator2 { dt "init" (); $1 }
1436
1437
1438 /*(*----------------------------*)*/
1439 /*(* gccext: *)*/
1440 /*(*----------------------------*)*/
1441
1442 declaratori:
1443 | declarator { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr }
1444 /*(* gccext: *)*/
1445 | declarator gcc_asm_decl { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr }
1446 /*(* gccext: *)*/
1447 | attributes declarator { LP.add_ident (str_of_name (fst $2)); $2, $1 }
1448 | declarator attributes { LP.add_ident (str_of_name (fst $1)); $1, Ast_c.noattr (* TODO *) }
1449
1450
1451
1452 gcc_asm_decl:
1453 | Tasm TOPar asmbody TCPar { }
1454 | Tasm Tvolatile TOPar asmbody TCPar { }
1455
1456
1457 /*(*-----------------------------------------------------------------------*)*/
1458 initialize:
1459 | assign_expr
1460 { InitExpr $1, [] }
1461 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
1462 { InitList (List.rev $2), [$1;$4]++$3 }
1463 | tobrace_ini tcbrace_ini
1464 { InitList [], [$1;$2] } /*(* gccext: *)*/
1465
1466
1467 /*
1468 (* opti: This time we use the weird order of non-terminal which requires in
1469 * the "caller" to do a List.rev cos quite critical. With this weird order it
1470 * allows yacc to use a constant stack space instead of exploding if we would
1471 * do a 'initialize2 Tcomma initialize_list'.
1472 *)
1473 */
1474 initialize_list:
1475 | initialize2 { [$1, []] }
1476 | initialize_list TComma initialize2 { ($3, [$2])::$1 }
1477
1478
1479 /*(* gccext: condexpr and no assign_expr cos can have ambiguity with comma *)*/
1480 initialize2:
1481 | cond_expr
1482 { InitExpr $1, [] }
1483 | tobrace_ini initialize_list gcc_comma_opt_struct tcbrace_ini
1484 { InitList (List.rev $2), [$1;$4]++$3 }
1485 | tobrace_ini tcbrace_ini
1486 { InitList [], [$1;$2] }
1487
1488 /*(* gccext: labeled elements, a.k.a designators *)*/
1489 | designator_list TEq initialize2
1490 { InitDesignators ($1, $3), [$2] }
1491
1492 /*(* gccext: old format *)*/
1493 | ident TDotDot initialize2
1494 { InitFieldOld (fst $1, $3), [snd $1; $2] } /*(* in old kernel *)*/
1495 /* conflict
1496 | TOCro const_expr TCCro initialize2
1497 { InitIndexOld ($2, $4), [$1;$3] }
1498 */
1499
1500
1501
1502 /*(* they can be nested, can have a .x[3].y *)*/
1503 designator:
1504 | TDot ident
1505 { DesignatorField (fst $2), [$1;snd $2] }
1506 | TOCro const_expr TCCro
1507 { DesignatorIndex ($2), [$1;$3] }
1508 | TOCro const_expr TEllipsis const_expr TCCro
1509 { DesignatorRange ($2, $4), [$1;$3;$5] }
1510
1511
1512 /*(*----------------------------*)*/
1513 /*(* workarounds *)*/
1514 /*(*----------------------------*)*/
1515
1516 gcc_comma_opt_struct:
1517 | TComma { [$1] }
1518 | /*(* empty *)*/ { [Ast_c.fakeInfo() +> Ast_c.rewrap_str ","] }
1519
1520
1521
1522
1523
1524
1525
1526
1527 /*(*************************************************************************)*/
1528 /*(* struct *)*/
1529 /*(*************************************************************************)*/
1530
1531 s_or_u_spec2:
1532 | struct_or_union ident tobrace_struct struct_decl_list_gcc tcbrace_struct
1533 { StructUnion (fst $1, Some (fst $2), $4), [snd $1;snd $2;$3;$5] }
1534 | struct_or_union tobrace_struct struct_decl_list_gcc tcbrace_struct
1535 { StructUnion (fst $1, None, $3), [snd $1;$2;$4] }
1536 | struct_or_union ident
1537 { StructUnionName (fst $1, fst $2), [snd $1;snd $2] }
1538
1539 struct_or_union2:
1540 | Tstruct { Struct, $1 }
1541 | Tunion { Union, $1 }
1542 /*(* gccext: *)*/
1543 | Tstruct attributes { Struct, $1 (* TODO *) }
1544 | Tunion attributes { Union, $1 (* TODO *) }
1545
1546
1547
1548 struct_decl2:
1549 | field_declaration { DeclarationField $1 }
1550 | TPtVirg { EmptyField $1 }
1551
1552 /*(* no conflict ? no need for a TMacroStruct ? apparently not as at struct
1553 * the rule are slightly different.
1554 *)*/
1555 | identifier TOPar argument_list TCPar TPtVirg
1556 { MacroDeclField ((fst $1, $3), [snd $1;$2;$4;$5;fakeInfo()]) }
1557
1558 /*(* cppext: *)*/
1559 | cpp_directive
1560 { CppDirectiveStruct $1 }
1561 | cpp_ifdef_directive/*(* struct_decl_list ... *)*/
1562 { IfdefStruct $1 }
1563
1564
1565 field_declaration:
1566 | spec_qualif_list struct_declarator_list TPtVirg
1567 {
1568 let (returnType,storage) = fixDeclSpecForDecl $1 in
1569 if fst (unwrap storage) <> NoSto
1570 then internal_error "parsing dont allow this";
1571
1572 FieldDeclList ($2 +> (List.map (fun (f, iivirg) ->
1573 f returnType, iivirg))
1574 ,[$3])
1575 (* dont need to check if typedef or func initialised cos
1576 * grammar dont allow typedef nor initialiser in struct
1577 *)
1578 }
1579
1580 | spec_qualif_list TPtVirg
1581 {
1582 (* gccext: allow empty elements if it is a structdef or enumdef *)
1583 let (returnType,storage) = fixDeclSpecForDecl $1 in
1584 if fst (unwrap storage) <> NoSto
1585 then internal_error "parsing dont allow this";
1586
1587 FieldDeclList ([(Simple (None, returnType)) , []], [$2])
1588 }
1589
1590
1591
1592
1593
1594 struct_declarator:
1595 | declaratorsd
1596 { (fun x -> Simple (Some (fst $1), (snd $1) x)) }
1597 | dotdot const_expr2
1598 { (fun x -> BitField (None, x, $1, $2)) }
1599 | declaratorsd dotdot const_expr2
1600 { (fun x -> BitField (Some (fst $1), ((snd $1) x), $2, $3)) }
1601
1602
1603 /*(*----------------------------*)*/
1604 /*(* workarounds *)*/
1605 /*(*----------------------------*)*/
1606 declaratorsd:
1607 | declarator { (*also ? LP.add_ident (fst (fst $1)); *) $1 }
1608 /*(* gccext: *)*/
1609 | attributes declarator { $2 }
1610 | declarator attributes { $1 }
1611
1612
1613
1614
1615 struct_or_union_spec: s_or_u_spec2 { dt "su" (); $1 }
1616 struct_or_union: struct_or_union2 { et "su" (); $1 }
1617 struct_decl: struct_decl2 { et "struct" (); $1 }
1618
1619 dotdot: TDotDot { et "dotdot" (); $1 }
1620 const_expr2: const_expr { dt "const_expr2" (); $1 }
1621
1622 struct_decl_list_gcc:
1623 | struct_decl_list { $1 }
1624 | /*(* empty *)*/ { [] } /*(* gccext: allow empty struct *)*/
1625
1626
1627 /*(*************************************************************************)*/
1628 /*(* enum *)*/
1629 /*(*************************************************************************)*/
1630 enum_spec:
1631 | Tenum tobrace_enum enumerator_list gcc_comma_opt_struct tcbrace_enum
1632 { Enum (None, $3), [$1;$2;$5] ++ $4 }
1633 | Tenum ident tobrace_enum enumerator_list gcc_comma_opt_struct tcbrace_enum
1634 { Enum (Some (fst $2), $4), [$1; snd $2; $3;$6] ++ $5 }
1635 | Tenum ident
1636 { EnumName (fst $2), [$1; snd $2] }
1637
1638 enumerator:
1639 | idente { $1, None }
1640 | idente TEq const_expr { $1, Some ($2, $3) }
1641
1642
1643 /*(*----------------------------*)*/
1644 /*(* workarounds *)*/
1645 /*(*----------------------------*)*/
1646
1647 idente: ident_cpp { LP.add_ident (str_of_name $1); $1 }
1648
1649
1650
1651 /*(*************************************************************************)*/
1652 /*(* function *)*/
1653 /*(*************************************************************************)*/
1654 function_definition: function_def { fixFunc $1 }
1655
1656 decl_list:
1657 | decl { [$1 Ast_c.LocalDecl] }
1658 | decl_list decl { $1 ++ [$2 Ast_c.LocalDecl] }
1659
1660 /* hack : to drop when a better solution is found */
1661 cpp_directive_list:
1662 | cpp_directive { }
1663 | cpp_directive_list cpp_directive { }
1664
1665 function_def:
1666 | start_fun compound { LP.del_scope(); ($1, $2, None) }
1667 | start_fun cpp_directive_list compound { LP.del_scope(); ($1, $3, None) }
1668 | start_fun decl_list compound {
1669 (* TODO: undo the typedef added ? *)
1670 LP.del_scope();
1671 ($1, $3, Some $2)
1672 }
1673
1674 start_fun: start_fun2
1675 { LP.new_scope();
1676 fix_add_params_ident $1;
1677 (* toreput? !LP._lexer_hint.toplevel <- false; *)
1678 $1
1679 }
1680
1681 start_fun2: decl_spec declaratorfd
1682 { let (returnType,storage) = fixDeclSpecForFuncDef $1 in
1683 let (id, attrs) = $2 in
1684 (fst id, fixOldCDecl ((snd id) returnType) , storage, attrs)
1685 }
1686 | ctor_dtor { $1 }
1687
1688 ctor_dtor:
1689 | Tconstructorname topar tcpar {
1690 let id = RegularName (mk_string_wrap $1) in
1691 let ret = mk_ty NoType [] in
1692 let ty = mk_ty (FunctionType (ret, (([], (false, []))))) [$2;$3] in
1693 let storage = ((NoSto,false),[]) in
1694 let attrs = [] in
1695 (id, ty, storage, attrs) }
1696 | Tconstructorname topar parameter_type_list tcpar {
1697 let id = RegularName (mk_string_wrap $1) in
1698 let ret = mk_ty NoType [] in
1699 let ty = mk_ty (FunctionType (ret, $3)) [$2;$4] in
1700 let storage = ((NoSto,false),[]) in
1701 let attrs = [] in
1702 (id, ty, storage, attrs) }
1703
1704 /*(*----------------------------*)*/
1705 /*(* workarounds *)*/
1706 /*(*----------------------------*)*/
1707
1708 /* It would be very nice if we could make declarator aware that this is
1709 coming from a function definition. Then on the ( and ) cases, it could
1710 set the state to something other than InParameter. Then the case
1711 (TIdent (s, i1)::(TComma _|TCPar _)::_ , (TComma _ |TOPar _)::_ )
1712 in parsing_hacks.ml would not have to consider K&R variable declarations
1713 as typedefs. Unfortunately, doing something about this problem seems to
1714 introduce conflicts in the parser. */
1715
1716 declaratorfd:
1717 | declarator { et "declaratorfd" (); $1, Ast_c.noattr }
1718 /*(* gccext: *)*/
1719 | attributes declarator { et "declaratorfd" (); $2, $1 }
1720 | declarator attributes { et "declaratorfd" (); $1, Ast_c.noattr }
1721
1722
1723
1724 /*(*************************************************************************)*/
1725 /*(* cpp directives *)*/
1726 /*(*************************************************************************)*/
1727
1728 cpp_directive:
1729 | TIncludeStart TIncludeFilename
1730 {
1731 let (i1, in_ifdef) = $1 in
1732 let (s, i2) = $2 in
1733
1734 (* redo some lexing work :( *)
1735 let inc_file =
1736 match () with
1737 | _ when s =~ "^\"\\(.*\\)\"$" ->
1738 Local (Common.split "/" (matched1 s))
1739 | _ when s =~ "^\\<\\(.*\\)\\>$" ->
1740 NonLocal (Common.split "/" (matched1 s))
1741 | _ ->
1742 Weird s
1743 in
1744 Include { i_include = (inc_file, [i1;i2]);
1745 i_rel_pos = Ast_c.noRelPos();
1746 i_is_in_ifdef = !in_ifdef;
1747 i_content = Ast_c.noi_content;
1748 }
1749 }
1750
1751 | TDefine TIdentDefine define_val TDefEOL
1752 { Define ((fst $2, [$1; snd $2;$4]), (DefineVar, $3)) }
1753
1754 /*
1755 (* The TOParDefine is introduced to avoid ambiguity with previous rules.
1756 * A TOParDefine is a TOPar that was just next to the ident.
1757 *)*/
1758 | TDefine TIdentDefine TOParDefine param_define_list TCPar define_val TDefEOL
1759 { Define
1760 ((fst $2, [$1; snd $2; $7]),
1761 (DefineFunc ($4, [$3;$5]), $6))
1762 }
1763
1764 | TUndef TIdentDefine TDefEOL
1765 { Define((fst $2, [$1; snd $2; $3]), (Undef,DefineEmpty)) }
1766 | TCppDirectiveOther { PragmaAndCo ([$1]) }
1767
1768
1769
1770
1771
1772 /*(* perhaps better to use assign_expr ? but in that case need
1773 * do a assign_expr_of_string in parse_c
1774 *)*/
1775 define_val:
1776 | expr { DefineExpr $1 }
1777 | statement { DefineStmt $1 }
1778 | decl { DefineStmt (mk_st (Decl ($1 Ast_c.NotLocalDecl)) Ast_c.noii) }
1779
1780 /*(*old:
1781 * | TypedefIdent { DefineType (nQ,(TypeName(fst $1,noTypedefDef()),[snd $1]))}
1782 * get conflicts:
1783 * | spec_qualif_list TMul
1784 * { let (returnType, _) = fixDeclSpecForDecl $1 in DefineType returnType }
1785 *)
1786 */
1787 | decl_spec
1788 { let returnType = fixDeclSpecForMacro $1 in
1789 DefineType returnType
1790 }
1791 | decl_spec abstract_declarator
1792 { let returnType = fixDeclSpecForMacro $1 in
1793 let typ = $2 returnType in
1794 DefineType typ
1795 }
1796
1797 /*(* can be in conflict with decl_spec, maybe change fixDeclSpecForMacro
1798 * to also allow storage ?
1799 | storage_class_spec { DefineTodo }
1800 | Tinline { DefineTodo }
1801 *)*/
1802
1803 | stat_or_decl stat_or_decl_list
1804 { DefineMulti
1805 (List.map
1806 (function
1807 StmtElem e -> e
1808 | _ -> failwith "unexpected statement for DefineMulti")
1809 ($1 :: $2)) }
1810 /*(*
1811 | statement statement { DefineTodo }
1812 | decl function_definition { DefineTodo }
1813 *)*/
1814
1815
1816
1817
1818 | function_definition { DefineFunction $1 }
1819
1820 | TOBraceDefineInit initialize_list gcc_comma_opt_struct TCBrace comma_opt
1821 { DefineInit (InitList (List.rev $2), [$1;$4]++$3++$5) }
1822
1823 /*(* note: had a conflict before when were putting TInt instead of expr *)*/
1824 | Tdo statement Twhile TOPar expr TCPar
1825 {
1826 (* TOREPUT
1827 if fst $5 <> "0"
1828 then pr2 "WEIRD: in macro and have not a while(0)";
1829 *)
1830 DefineDoWhileZero (($2,$5), [$1;$3;$4;$6])
1831 }
1832
1833 | Tasm TOPar asmbody TCPar { DefineTodo }
1834 | Tasm Tvolatile TOPar asmbody TCPar { DefineTodo }
1835
1836 /*(* aliases macro *)*/
1837 | TMacroAttr { DefineTodo }
1838
1839 | /*(* empty *)*/ { DefineEmpty }
1840
1841
1842
1843
1844 param_define:
1845 | TIdent { mk_string_wrap $1 }
1846 | TypedefIdent { mk_string_wrap $1 }
1847 | TDefParamVariadic { mk_string_wrap $1 }
1848 | TEllipsis { "...", [$1] }
1849 /*(* they reuse keywords :( *)*/
1850 | Tregister { "register", [$1] }
1851
1852
1853
1854
1855 cpp_ifdef_directive:
1856 | TIfdef
1857 { let (tag,ii) = $1 in
1858 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1859 | TIfdefelse
1860 { let (tag,ii) = $1 in
1861 IfdefDirective ((IfdefElse, IfdefTag (Common.some !tag)), [ii]) }
1862 | TIfdefelif
1863 { let (tag,ii) = $1 in
1864 IfdefDirective ((IfdefElseif, IfdefTag (Common.some !tag)), [ii]) }
1865 | TEndif
1866 { let (tag,ii) = $1 in
1867 IfdefDirective ((IfdefEndif, IfdefTag (Common.some !tag)), [ii]) }
1868
1869 | TIfdefBool
1870 { let (_b, tag,ii) = $1 in
1871 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1872 | TIfdefMisc
1873 { let (_b, tag,ii) = $1 in
1874 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1875 | TIfdefVersion
1876 { let (_b, tag,ii) = $1 in
1877 IfdefDirective ((Ifdef, IfdefTag (Common.some !tag)), [ii]) }
1878
1879
1880 /*(* cppext: *)*/
1881 cpp_other:
1882 /*(* no conflict ? no need for a TMacroTop ? apparently not as at toplevel
1883 * the rule are slightly different, they cant be statement and so expr
1884 * at the top, only decl or function definition.
1885 *)*/
1886 | identifier TOPar argument_list TCPar TPtVirg
1887 {
1888 Declaration(MacroDecl((fst $1, $3, true), [snd $1;$2;$4;$5;fakeInfo()]))
1889 (* old: MacroTop (fst $1, $3, [snd $1;$2;$4;$5]) *)
1890 }
1891
1892 /*(* TCParEOL to fix the end-of-stream bug of ocamlyacc *)*/
1893 | identifier TOPar argument_list TCParEOL
1894 { Declaration (MacroDecl ((fst $1, $3, false), [snd $1;$2;$4;fakeInfo()])) }
1895
1896 /*(* ex: EXPORT_NO_SYMBOLS; *)*/
1897 | identifier TPtVirg { EmptyDef [snd $1;$2] }
1898
1899
1900
1901 /*(*************************************************************************)*/
1902 /*(* celem *)*/
1903 /*(*************************************************************************)*/
1904
1905 external_declaration:
1906 | function_definition { Definition $1 }
1907 | decl { Declaration ($1 Ast_c.NotLocalDecl) }
1908
1909
1910 celem:
1911 | Tnamespace TIdent TOBrace translation_unit TCBrace
1912 { !LP._lexer_hint.context_stack <- [LP.InTopLevel];
1913 Namespace ($4, [$1; snd $2; $3; $5]) }
1914
1915 | external_declaration { $1 }
1916
1917 /*(* cppext: *)*/
1918 | cpp_directive
1919 { CppTop $1 }
1920 | cpp_other
1921 { $1 }
1922 | cpp_ifdef_directive /* (*external_declaration_list ...*)*/
1923 { IfdefTop $1 }
1924
1925 /*(* can have asm declaration at toplevel *)*/
1926 | Tasm TOPar asmbody TCPar TPtVirg { EmptyDef [$1;$2;$4;$5] }
1927
1928 /*
1929 (* in ~/kernels/src/linux-2.5.2/drivers/isdn/hisax/isdnl3.c sometimes
1930 * the function ends with }; instead of just }
1931 * can also remove this rule and report "parse error" pb to morton
1932 *)*/
1933 | TPtVirg { EmptyDef [$1] }
1934
1935
1936 | EOF { FinalDef $1 }
1937
1938
1939
1940
1941 /*(*************************************************************************)*/
1942 /*(* some generic workarounds *)*/
1943 /*(*************************************************************************)*/
1944
1945 tobrace: TOBrace { LP.push_context LP.InFunction; LP.new_scope (); $1 }
1946 tcbrace: TCBrace { LP.pop_context(); LP.del_scope (); $1 }
1947
1948 tobrace_enum: TOBrace { LP.push_context LP.InEnum; $1 }
1949 tcbrace_enum: TCBrace { LP.pop_context (); $1 }
1950
1951 tobrace_ini: TOBrace { LP.push_context LP.InInitializer; $1 }
1952 tcbrace_ini: TCBrace { LP.pop_context (); $1 }
1953
1954 tobrace_struct: TOBrace { LP.push_context LP.InStruct; $1}
1955 tcbrace_struct: TCBrace { LP.pop_context (); $1 }
1956
1957
1958
1959
1960 topar: TOPar
1961 { LP.new_scope ();et "topar" ();
1962 LP.push_context LP.InParameter;
1963 $1
1964 }
1965 tcpar: TCPar
1966 { LP.del_scope ();dt "tcpar" ();
1967 LP.pop_context ();
1968 $1
1969 }
1970
1971
1972
1973
1974 /*(*************************************************************************)*/
1975 /*(* xxx_list, xxx_opt *)*/
1976 /*(*************************************************************************)*/
1977
1978
1979 /*(* old:
1980 compound2:
1981 | { ([],[]) }
1982 | statement_list { ([], $1) }
1983 | decl_list { ($1, []) }
1984 | decl_list statement_list { ($1,$2) }
1985
1986 statement_list: stat_or_decl_list { $1 }
1987 *)*/
1988
1989
1990 /*(*
1991 decl_list:
1992 | decl { [$1] }
1993 | decl_list decl { $1 ++ [$2] }
1994
1995 statement_list:
1996 | statement { [$1] }
1997 | statement_list statement { $1 ++ [$2] }
1998 *)*/
1999
2000
2001
2002
2003
2004 string_list:
2005 | string_elem { $1 }
2006 | string_list string_elem { $1 ++ $2 }
2007
2008 colon_asm_list:
2009 | colon_asm { [$1] }
2010 | colon_asm_list colon_asm { $1 ++ [$2] }
2011
2012 colon_option_list:
2013 | colon_option { [$1, []] }
2014 | colon_option_list TComma colon_option { $1 ++ [$3, [$2]] }
2015
2016
2017 argument_list_ne:
2018 | argument_ne { [$1, []] }
2019 | argument_list_ne TComma argument { $1 ++ [$3, [$2]] }
2020
2021 argument_list:
2022 | argument { [$1, []] }
2023 | argument_list TComma argument { $1 ++ [$3, [$2]] }
2024
2025 /*(*
2026 expression_list:
2027 | assign_expr { [$1, []] }
2028 | expression_list TComma assign_expr { $1 ++ [$3, [$2]] }
2029 *)*/
2030
2031
2032 struct_decl_list:
2033 | struct_decl { [$1] }
2034 | struct_decl_list struct_decl { $1 ++ [$2] }
2035
2036
2037 struct_declarator_list:
2038 | struct_declarator { [$1, []] }
2039 | struct_declarator_list TComma struct_declarator { $1 ++ [$3, [$2]] }
2040
2041
2042 enumerator_list:
2043 | enumerator { [$1, []] }
2044 | enumerator_list TComma enumerator { $1 ++ [$3, [$2]] }
2045
2046
2047 init_declarator_list:
2048 | init_declarator { [$1, []] }
2049 | init_declarator_list TComma init_declarator { $1 ++ [$3, [$2]] }
2050
2051
2052 parameter_list:
2053 | parameter_decl { [$1, []] }
2054 | parameter_list TComma parameter_decl { $1 ++ [$3, [$2]] }
2055
2056 taction_list_ne:
2057 | TAction { [$1] }
2058 | TAction taction_list_ne { $1 :: $2 }
2059
2060 taction_list:
2061 /*old: was generating conflict, hence now taction_list_ne
2062 | (* empty *) { [] }
2063 | TAction { [$1] }
2064 | taction_list TAction { $1 ++ [$2] }
2065 */
2066 | { [] }
2067 | TAction taction_list { $1 :: $2 }
2068
2069 param_define_list:
2070 | /*(* empty *)*/ { [] }
2071 | param_define { [$1, []] }
2072 | param_define_list TComma param_define { $1 ++ [$3, [$2]] }
2073
2074 designator_list:
2075 | designator { [$1] }
2076 | designator_list designator { $1 ++ [$2] }
2077
2078 attribute_list:
2079 | attribute { [$1] }
2080 | attribute_list attribute { $1 ++ [$2] }
2081
2082 attribute_storage_list:
2083 | attribute_storage { [$1] }
2084 | attribute_storage_list attribute_storage { $1 ++ [$2] }
2085
2086
2087 attributes: attribute_list { $1 }
2088
2089
2090
2091 /*(* gccext: which allow a trailing ',' in enum, as in perl *)*/
2092 gcc_comma_opt:
2093 | TComma { [$1] }
2094 | /*(* empty *)*/ { [] }
2095
2096 comma_opt:
2097 | TComma { [$1] }
2098 | /*(* empty *)*/ { [] }
2099
2100 /*(*
2101 gcc_opt_virg:
2102 | TPtVirg { }
2103 | { }
2104 *)*/
2105
2106 gcc_opt_expr:
2107 | expr { Some $1 }
2108 | /*(* empty *)*/ { None }
2109
2110 /*(*
2111 opt_ptvirg:
2112 | TPtVirg { [$1] }
2113 | { [] }
2114 *)*/
2115
2116