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