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