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