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