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