Release coccinelle-0.2.4
[bpt/coccinelle.git] / parsing_cocci / parser_cocci_menhir.mly
CommitLineData
9bc82bae
C
1/*
2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
7 *
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
11 *
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
22 */
23
24
c491d8ee
C
25/*
26 * Copyright 2010, INRIA, University of Copenhagen
27 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
28 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
29 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
30 * This file is part of Coccinelle.
31 *
32 * Coccinelle is free software: you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation, according to version 2 of the License.
35 *
36 * Coccinelle is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
40 *
41 * You should have received a copy of the GNU General Public License
42 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
43 *
44 * The authors reserve the right to distribute this or future versions of
45 * Coccinelle under other licenses.
46 */
47
48
34e49164
C
49%{
50
51(* Not clear how to allow function declarations to specify a return type
52and how to allow both to be specified as static, because they are in
53different rules. The rules seem to have to be combined, which would allow
54functions to be declared as local variables *)
55
56(* Not clear how to let a function have a parameter of type void. At the
57moment, void is allowed to be the type of a variable, which is wrong, and a
58parameter needs both a type and an identifier *)
59module Ast0 = Ast0_cocci
60module Ast = Ast_cocci
61module P = Parse_aux
62%}
63
64%token EOF
65
66%token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
413ffc02 67%token TIdExpression TInitialiser TDeclaration TField
34e49164 68%token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
faf9a90c 69%token TPure TContext TGenerated
34e49164 70%token TTypedef TDeclarer TIterator TName TPosition TPosAny
faf9a90c 71%token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
951c7801 72%token TScript TInitialize TFinalize TNothing TVirtual
34e49164
C
73%token<string> TRuleName
74
75%token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
1eddfd50 76%token<Data.clt> Tsize_t Tssize_t Tptrdiff_t
faf9a90c 77%token<Data.clt> Tvoid Tstruct Tunion Tenum
34e49164
C
78%token<Data.clt> Tunsigned Tsigned
79
80%token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
81%token<Data.clt> Tconst Tvolatile
82%token<string * Data.clt> Tattr
83
84%token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
85%token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
c3e37e97
C
86%token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
87%token <Ast_cocci.added_string * Data.clt> TPragma
34e49164 88
951c7801
C
89%token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
90%token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
91%token <Parse_aux.expinfo> TMetaErr
92%token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
413ffc02 93%token <Parse_aux.info> TMetaInit TMetaDecl TMetaField
951c7801
C
94%token <Parse_aux.list_info> TMetaParamList TMetaExpList
95%token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
96%token <Parse_aux.pos_info> TMetaPos
34e49164
C
97
98%token TArob TArobArob TPArob
99%token <string> TScriptData
100
101%token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
1be43e12 102%token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
34e49164
C
103
104%token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
105%token <Data.clt> TMid0 TCPar TCPar0
106
0708f913 107%token <string> TPathIsoFile
34e49164
C
108%token <string * Data.clt> TIncludeL TIncludeNL
109%token <Data.clt * token> TDefine
708f4980 110%token <Data.clt * token * int * int> TDefineParam
34e49164
C
111%token <string * Data.clt> TMinusFile TPlusFile
112
113%token <Data.clt> TInc TDec
114
115%token <string * Data.clt> TString TChar TFloat TInt
116
117%token <Data.clt> TOrLog
118%token <Data.clt> TAndLog
119%token <Data.clt> TOr
120%token <Data.clt> TXor
faf9a90c 121%token <Data.clt> TAnd
5636bb2c 122%token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq TSub
34e49164 123%token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
413ffc02 124%token <Ast_cocci.arithOp * Data.clt> TShLOp TShROp /* TShl TShr */
34e49164
C
125%token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
126%token <Data.clt> TPlus TMinus
127%token <Data.clt> TMul TTilde
128
1be43e12 129%token <Data.clt> TOBrace TCBrace TOInit
34e49164
C
130%token <Data.clt> TOCro TCCro
131
132%token <Data.clt> TPtrOp
133
978fd7e5 134%token TMPtVirg TCppConcatOp
34e49164
C
135%token <Data.clt> TEq TDot TComma TPtVirg
136%token <Ast_cocci.assignOp * Data.clt> TAssign
137
138%token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
c3e37e97 139%token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression
34e49164 140
aba5c457
C
141%token TUnderscore
142
34e49164
C
143%token TInvalid
144
145/* operator precedence */
146%nonassoc TIf
147%nonassoc TElse
148
149%left TOrLog
150%left TAndLog
151%left TOr
152%left TXor
faf9a90c 153%left TAnd
34e49164
C
154%left TEqEq TNotEq
155%left TLogOp /* TInf TSup TInfEq TSupEq */
413ffc02 156%left TShLOp TShROp /* TShl TShr */
34e49164
C
157%left TPlus TMinus
158%left TMul TDmOp /* TDiv TMod */
159
160%start reinit
161%type <unit> reinit
162
163%start minus_main
164%type <Ast0_cocci.rule> minus_main
165
166%start minus_exp_main
167%type <Ast0_cocci.rule> minus_exp_main
168
169%start plus_main
170%type <Ast0_cocci.rule> plus_main
171
172%start plus_exp_main
173%type <Ast0_cocci.rule> plus_exp_main
174
175%start include_main
978fd7e5 176%type <Data.incl_iso list> include_main
34e49164
C
177
178%start iso_rule_name
179%type <Ast_cocci.rulename>
180iso_rule_name
181
182%start rule_name
183%type <Ast_cocci.rulename>
184rule_name
185
186%start meta_main
187%type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
188
413ffc02 189%start <(string option (*string*) * string option (*ast*)) * (Ast_cocci.meta_name * Ast_cocci.metavar) option> script_meta_main
34e49164
C
190
191%start iso_main
192%type <Ast0_cocci.anything list list> iso_main
193
194%start iso_meta_main
195%type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
196
197%start never_used
198%type <unit> never_used
199
200%%
201
202reinit: { }
203minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
204| m=minus_body TArob { m }
205plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
206| p=plus_body TArob { p }
207minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
208| m=minus_exp_body TArob { m }
209plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
210| p=plus_exp_body TArob { p }
211meta_main: m=metadec { m (!Ast0.rule_name) }
212iso_meta_main: m=metadec { m "" }
213
214/*****************************************************************************
215*
216*
217*****************************************************************************/
218
219pure:
220 TPure { Ast0.Pure }
221| TContext { Ast0.Context }
222| TPure TContext { Ast0.PureContext }
223| TContext TPure { Ast0.PureContext }
224| /* empty */ { Ast0.Impure }
225
226iso_rule_name:
227 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
228
229rule_name:
230 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
231 a=loption(disable) e=exists ee=is_expression TArob
232 { P.make_cocci_rule_name_result nm d i a e ee }
faf9a90c
C
233 | TGenerated extends d=depends i=loption(choose_iso)
234 a=loption(disable) e=exists ee=is_expression TArob
235 /* these rules have no name as a cheap way to ensure that no normal
236 rule inherits their metavariables or depends on them */
237 { P.make_generated_rule_name_result None d i a e ee }
413ffc02
C
238 | TScript TDotDot lang=pure_ident nm=ioption(pure_ident) d=depends TArob
239 { P.make_script_rule_name_result lang nm d }
c3e37e97
C
240 | TInitialize TDotDot lang=pure_ident d=depends TArob
241 { P.make_initial_script_rule_name_result lang d }
242 | TFinalize TDotDot lang=pure_ident d=depends TArob
243 { P.make_final_script_rule_name_result lang d }
34e49164
C
244
245extends:
246 /* empty */ { () }
247| TExtends parent=TRuleName
248 { !Data.install_bindings (parent) }
249
250depends:
251 /* empty */ { Ast.NoDep }
252| TDepends TOn parents=dep { parents }
253
254dep:
255 pnrule { $1 }
256| dep TAndLog dep { Ast.AndDep($1, $3) }
257| dep TOrLog dep { Ast.OrDep ($1, $3) }
258
259pnrule:
260 TRuleName { Ast.Dep $1 }
261| TBang TRuleName { Ast.AntiDep $2 }
262| TEver TRuleName { Ast.EverDep $2 }
263| TNever TRuleName { Ast.NeverDep $2 }
264| TOPar dep TCPar { $2 }
265
266choose_iso:
267 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
268
269disable:
270 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
271
272exists:
273 TExists { Ast.Exists }
274| TForall { Ast.Forall }
34e49164
C
275| { Ast.Undetermined }
276
277is_expression: // for more flexible parsing of top level expressions
278 { false }
279| TExpression { true }
280
281include_main:
282 list(incl) TArob { $1 }
283| list(incl) TArobArob { $1 }
284
285incl:
978fd7e5
C
286 TIncludeL { let (x,_) = $1 in Data.Include(x) }
287| TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
288| TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
951c7801
C
289| TVirtual comma_list(pure_ident)
290 { let names = List.map P.id2name $2 in
291 (* ensure that the names of virtual and real rules don't overlap *)
292 List.iter
293 (function name -> Hashtbl.add Data.all_metadecls name [])
294 names;
295 Data.Virt(names) }
34e49164
C
296
297metadec:
298 ar=arity ispure=pure
299 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
300 { P.create_metadec ar ispure kindfn ids }
b1b2de81
C
301| kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
302 TMPtVirg
303 { P.create_fresh_metadec kindfn ids }
ae4735db
C
304| ar=arity ispure=pure
305 kindfn=metakind_atomic_maybe_virt
306 ids=
307 comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid))
308 TMPtVirg
309 { let (normal,virt) = Common.partition_either (fun x -> x) ids in
310 let (idfn,virtfn) = kindfn in
311 function cr ->
312 (P.create_metadec_with_constraints ar ispure idfn normal cr) @
313 (P.create_metadec_virt ar ispure virtfn virt cr) }
34e49164
C
314| ar=arity ispure=pure
315 kindfn=metakind_atomic
7f004419
C
316 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
317 TMPtVirg
951c7801 318 { P.create_metadec_with_constraints ar ispure kindfn ids }
34e49164
C
319| ar=arity ispure=pure
320 kindfn=metakind_atomic_expi
5636bb2c 321 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe_or_sub))
7f004419 322 TMPtVirg
951c7801 323 { P.create_metadec_with_constraints ar ispure kindfn ids }
34e49164
C
324| ar=arity ispure=pure
325 kindfn=metakind_atomic_expe
5636bb2c
C
326 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(not_ceq_or_sub))
327 TMPtVirg
951c7801 328 { P.create_metadec_with_constraints ar ispure kindfn ids }
34e49164 329| ar=arity TPosition a=option(TPosAny)
951c7801 330 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
faf9a90c
C
331 (* pb: position variables can't be inherited from normal rules, and then
332 there is no way to inherit from a generated rule, so there is no point
333 to have a position variable *)
334 { (if !Data.in_generating
335 then failwith "position variables not allowed in a generated rule file");
336 let kindfn arity name pure check_meta constraints =
34e49164
C
337 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
338 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
339 !Data.add_pos_meta name constraints any; tok in
951c7801 340 P.create_metadec_with_constraints ar false kindfn ids }
34e49164 341| ar=arity ispure=pure
88e71198 342 TParameter Tlist TOCro len=list_len TCCro
34e49164
C
343 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
344 { P.create_len_metadec ar ispure
345 (fun lenname arity name pure check_meta ->
88e71198
C
346 let tok = check_meta(Ast.MetaParamListDecl(arity,name,lenname)) in
347 !Data.add_paramlist_meta name lenname pure; tok)
348 len ids }
34e49164 349| ar=arity ispure=pure
88e71198 350 TExpression Tlist TOCro len=list_len TCCro
34e49164
C
351 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
352 { P.create_len_metadec ar ispure
353 (fun lenname arity name pure check_meta ->
88e71198
C
354 let tok = check_meta(Ast.MetaExpListDecl(arity,name,lenname)) in
355 !Data.add_explist_meta name lenname pure; tok)
356 len ids }
357
358list_len:
359 pure_ident_or_meta_ident { Common.Left $1 }
360| TInt { let (x,clt) = $1 in Common.Right (int_of_string x) }
34e49164 361
b1b2de81 362%inline metakind_fresh:
34e49164 363 TFresh TIdentifier
b1b2de81
C
364 { (fun name check_meta seed ->
365 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
366 !Data.add_fresh_id_meta name; tok) }
367
ae4735db 368/* metavariable kinds with no constraints, etc */
b1b2de81
C
369%inline metakind:
370 TParameter
34e49164
C
371 { (fun arity name pure check_meta ->
372 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
373 !Data.add_param_meta name pure; tok) }
374| TParameter Tlist
375 { (fun arity name pure check_meta ->
88e71198
C
376 let len = Ast.AnyLen in
377 let tok = check_meta(Ast.MetaParamListDecl(arity,name,len)) in
378 !Data.add_paramlist_meta name len pure; tok) }
34e49164
C
379| TExpression Tlist
380 { (fun arity name pure check_meta ->
88e71198
C
381 let len = Ast.AnyLen in
382 let tok = check_meta(Ast.MetaExpListDecl(arity,name,len)) in
383 !Data.add_explist_meta name len pure; tok) }
34e49164
C
384| TType
385 { (fun arity name pure check_meta ->
386 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
faf9a90c 387 !Data.add_type_meta name pure; tok) }
113803cf
C
388| TInitialiser
389 { (fun arity name pure check_meta ->
390 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
391 !Data.add_init_meta name pure; tok) }
34e49164
C
392| TStatement
393 { (fun arity name pure check_meta ->
394 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
395 !Data.add_stm_meta name pure; tok) }
413ffc02
C
396| TDeclaration
397 { (fun arity name pure check_meta ->
398 let tok = check_meta(Ast.MetaDeclDecl(arity,name)) in
399 !Data.add_decl_meta name pure; tok) }
400| TField
401 { (fun arity name pure check_meta ->
402 let tok = check_meta(Ast.MetaFieldDecl(arity,name)) in
403 !Data.add_field_meta name pure; tok) }
34e49164
C
404| TStatement Tlist
405 { (fun arity name pure check_meta ->
406 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
407 !Data.add_stmlist_meta name pure; tok) }
408| TTypedef
409 { (fun arity (_,name) pure check_meta ->
410 if arity = Ast.NONE && pure = Ast0.Impure
411 then (!Data.add_type_name name; [])
412 else raise (Semantic_cocci.Semantic "bad typedef")) }
413| TDeclarer TName
414 { (fun arity (_,name) pure check_meta ->
415 if arity = Ast.NONE && pure = Ast0.Impure
416 then (!Data.add_declarer_name name; [])
417 else raise (Semantic_cocci.Semantic "bad declarer")) }
418| TIterator TName
419 { (fun arity (_,name) pure check_meta ->
420 if arity = Ast.NONE && pure = Ast0.Impure
421 then (!Data.add_iterator_name name; [])
422 else raise (Semantic_cocci.Semantic "bad iterator")) }
423
ae4735db 424%inline metakind_atomic_maybe_virt:
34e49164 425 TIdentifier
ae4735db
C
426 {
427 let idfn arity name pure check_meta constraints =
428 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
429 !Data.add_id_meta name constraints pure; tok in
430 let virtfn arity name pure check_meta virtual_env =
431 try
432 let vl = List.assoc name virtual_env in
433 !Data.add_virt_id_meta_found name vl; []
434 with Not_found ->
435 let name = ("virtual",name) in
436 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
437 !Data.add_virt_id_meta_not_found name pure; tok in
438 (idfn,virtfn) }
439
440%inline metakind_atomic:
441 TFunction
34e49164
C
442 { (fun arity name pure check_meta constraints ->
443 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
444 !Data.add_func_meta name constraints pure; tok) }
445| TLocal TFunction
446 { (fun arity name pure check_meta constraints ->
447 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
448 !Data.add_local_func_meta name constraints pure;
449 tok) }
450| TDeclarer
451 { (fun arity name pure check_meta constraints ->
452 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
453 !Data.add_declarer_meta name constraints pure; tok) }
454| TIterator
455 { (fun arity name pure check_meta constraints ->
456 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
457 !Data.add_iterator_meta name constraints pure; tok) }
458
459%inline metakind_atomic_expi:
460 TError
461 { (fun arity name pure check_meta constraints ->
462 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
463 !Data.add_err_meta name constraints pure; tok) }
464| l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
465 { (fun arity name pure check_meta constraints ->
466 match l with
467 None ->
468 !Data.add_idexp_meta ty name constraints pure;
469 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
470 | Some _ ->
471 !Data.add_local_idexp_meta ty name constraints pure;
472 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
473| l=option(TLocal) TIdExpression m=nonempty_list(TMul)
474 { (fun arity name pure check_meta constraints ->
475 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
476 match l with
477 None ->
478 !Data.add_idexp_meta ty name constraints pure;
479 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
480 | Some _ ->
481 !Data.add_local_idexp_meta ty name constraints pure;
482 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
e6509c05 483| TExpression ty=expression_type
34e49164 484 { (fun arity name pure check_meta constraints ->
e6509c05 485 let ty = Some [ty] in
34e49164
C
486 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
487 !Data.add_exp_meta ty name constraints pure; tok) }
34e49164
C
488| TConstant ty=ioption(meta_exp_type)
489 { (fun arity name pure check_meta constraints ->
490 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
491 !Data.add_const_meta ty name constraints pure; tok) }
492
e6509c05
C
493expression_type:
494 m=nonempty_list(TMul) { P.ty_pointerify Type_cocci.Unknown m }
495| Tenum m=list(TMul)
496 { P.ty_pointerify (Type_cocci.EnumName Type_cocci.NoName) m }
497| Tstruct m=list(TMul)
498 { P.ty_pointerify
499 (Type_cocci.StructUnionName (Type_cocci.Struct,Type_cocci.NoName)) m }
500| Tunion m=list(TMul)
501 { P.ty_pointerify
502 (Type_cocci.StructUnionName (Type_cocci.Union,Type_cocci.NoName)) m }
503
34e49164
C
504%inline metakind_atomic_expe:
505 TExpression
506 { (fun arity name pure check_meta constraints ->
507 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
5636bb2c 508 !Data.add_exp_meta None name constraints pure; tok) }
34e49164
C
509| vl=meta_exp_type // no error if use $1 but doesn't type check
510 { (fun arity name pure check_meta constraints ->
511 let ty = Some vl in
5636bb2c
C
512 (match constraints with
513 Ast0.NotExpCstrt constraints ->
514 List.iter
515 (function c ->
516 match Ast0.unwrap c with
517 Ast0.Constant(_) ->
518 if not
519 (List.exists
520 (function
521 Type_cocci.BaseType(Type_cocci.IntType) -> true
522 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
523 | Type_cocci.BaseType(Type_cocci.LongType) -> true
524 | _ -> false)
525 vl)
526 then
527 failwith "metavariable with int constraint must be an int"
528 | _ -> ())
529 constraints
530 | _ -> ());
34e49164 531 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
5636bb2c 532 !Data.add_exp_meta ty name constraints pure; tok)
951c7801 533 }
34e49164 534
34e49164 535meta_exp_type:
978fd7e5 536 t=typedef_ctype
34e49164 537 { [Ast0_cocci.ast0_type_to_type t] }
5626f154
C
538| t=typedef_ctype TOCro TCCro
539 { [Type_cocci.Array (Ast0_cocci.ast0_type_to_type t)] }
34e49164
C
540| TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
541 { List.map
542 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
543 t }
544
545arity: TBang0 { Ast.UNIQUE }
546 | TWhy0 { Ast.OPT }
547 | TPlus0 { Ast.MULTI }
548 | /* empty */ { Ast.NONE }
549
978fd7e5
C
550/* ---------------------------------------------------------------------- */
551
552%inline
553signable_types:
554 ty=Tchar
555 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
556| ty=Tshort
557 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
558| ty=Tint
559 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
560| p=TMetaType
561 { let (nm,pure,clt) = p in
562 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
563| r=TRuleName TDot p=TIdent
564 { let nm = (r,P.id2name p) in
565 (* this is only possible when we are in a metavar decl. Otherwise,
566 it will be represented already as a MetaType *)
567 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
568 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
569 Ast0.Impure (*will be ignored*))) }
570| ty=Tlong
571 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
572| ty1=Tlong ty2=Tlong
573 { Ast0.wrap
574 (Ast0.BaseType
575 (Ast.LongLongType,
576 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
577
578%inline
579non_signable_types:
580 ty=Tvoid
581 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
582| ty=Tdouble
583 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
584| ty=Tfloat
585 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
1eddfd50
C
586| ty=Tsize_t
587 { Ast0.wrap(Ast0.BaseType(Ast.SizeType,[P.clt2mcode "size_t" ty])) }
588| ty=Tssize_t
589 { Ast0.wrap(Ast0.BaseType(Ast.SSizeType,[P.clt2mcode "ssize_t" ty])) }
590| ty=Tptrdiff_t
591 { Ast0.wrap(Ast0.BaseType(Ast.PtrDiffType,[P.clt2mcode "ptrdiff_t" ty])) }
978fd7e5 592| s=Tenum i=ident
c491d8ee
C
593 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, Some i)) }
594| s=Tenum i=ioption(ident) l=TOBrace ids=enum_decl_list r=TCBrace
595 { (if i = None && !Data.in_iso
596 then failwith "enums must be named in the iso file");
597 Ast0.wrap(Ast0.EnumDef(Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)),
598 P.clt2mcode "{" l, ids, P.clt2mcode "}" r)) }
978fd7e5
C
599| s=struct_or_union i=ident
600 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
601| s=struct_or_union i=ioption(ident)
602 l=TOBrace d=struct_decl_list r=TCBrace
603 { (if i = None && !Data.in_iso
604 then failwith "structures must be named in the iso file");
605 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
606 P.clt2mcode "{" l,
607 d, P.clt2mcode "}" r)) }
608| s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
609 { let (nm,pure,clt) = s in
610 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
611 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
612| p=TTypeId
613 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
614
615%inline
616all_basic_types:
617 r=Tsigned ty=signable_types
618 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
619| r=Tunsigned ty=signable_types
620 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
621| ty=signable_types { ty }
622| ty=non_signable_types { ty }
623
624ctype:
625 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
626 { P.pointerify (P.make_cv cv ty) m }
627| r=Tsigned
628 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
629| r=Tunsigned
630 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
631| lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
632 { let (mids,code) = t in
633 Ast0.wrap
634 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
635
636/* signed, unsigned alone not allowed */
637typedef_ctype:
638 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
639 { P.pointerify (P.make_cv cv ty) m }
640| lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
641 { let (mids,code) = t in
642 Ast0.wrap
643 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
644
645/* ---------------------------------------------------------------------- */
34e49164
C
646
647struct_or_union:
648 s=Tstruct { P.clt2mcode Ast.Struct s }
649 | u=Tunion { P.clt2mcode Ast.Union u }
650
651struct_decl:
c491d8ee
C
652 TNothing { [] }
653 | struct_decl_one { [$1] }
654
655struct_decl_one:
656 | TMetaField { P.meta_field $1 }
34e49164
C
657 | t=ctype d=d_ident pv=TPtVirg
658 { let (id,fn) = d in
c491d8ee 659 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
978fd7e5 660 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
661 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
662 { let (id,fn) = d in
663 let t =
664 Ast0.wrap
665 (Ast0.FunctionPointer
666 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
667 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
c491d8ee 668 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
34e49164
C
669 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
670 { let (id,fn) = d in
671 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
c491d8ee 672 Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv)) }
34e49164
C
673
674struct_decl_list:
675 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
676
677struct_decl_list_start:
678 struct_decl { $1 }
679| struct_decl struct_decl_list_start { $1@$2 }
c491d8ee
C
680| d=edots_when(TEllipsis,struct_decl_one) r=continue_struct_decl_list
681 { (P.mkddots_one "..." d)::r }
34e49164
C
682
683continue_struct_decl_list:
684 /* empty */ { [] }
685| struct_decl struct_decl_list_start { $1@$2 }
686| struct_decl { $1 }
687
34e49164 688
c491d8ee
C
689/* ---------------------------------------------------------------------- */
690/* very restricted what kinds of expressions can appear in an enum decl */
691
692enum_decl_one:
693 | ident { Ast0.wrap(Ast0.Ident($1)) }
694 | ident TEq enum_val
695 { let id = Ast0.wrap(Ast0.Ident($1)) in
696 Ast0.wrap
697 (Ast0.Assignment
698 (id,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,
699 false)) }
700
701enum_val:
702 ident { Ast0.wrap(Ast0.Ident($1)) }
703 | TInt
704 { let (x,clt) = $1 in
705 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
706 | TMetaConst
707 { let (nm,constraints,pure,ty,clt) = $1 in
708 Ast0.wrap
709 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
710 | TMetaExp
711 { let (nm,constraints,pure,ty,clt) = $1 in
712 Ast0.wrap
713 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
714 | TMetaIdExp
715 { let (nm,constraints,pure,ty,clt) = $1 in
716 Ast0.wrap
717 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
718
719enum_decl_list:
720 nonempty_list_start(enum_decl_one,edots_when(TEllipsis,enum_decl_one))
721 { Ast0.wrap(Ast0.DOTS($1 P.mkedots (fun c -> Ast0.EComma c))) }
722
34e49164
C
723/*****************************************************************************/
724
725/* have to inline everything to avoid conflicts? switch to proper
726declarations, statements, and expressions for the subterms */
727
faf9a90c 728minus_body:
34e49164
C
729 f=loption(filespec)
730 b=loption(minus_start)
978fd7e5
C
731 /*ew=loption(error_words)*/
732 { match f@b(*@ew*) with
34e49164
C
733 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
734 | code -> Top_level.top_level code }
735
faf9a90c 736plus_body:
34e49164
C
737 f=loption(filespec)
738 b=loption(plus_start)
978fd7e5
C
739 /*ew=loption(error_words)*/
740 { Top_level.top_level (f@b(*@ew*)) }
34e49164
C
741
742minus_exp_body:
743 f=loption(filespec)
744 b=top_eexpr
978fd7e5
C
745 /*ew=loption(error_words)*/
746 { match f@[b](*@ew*) with
34e49164
C
747 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
748 | code -> Top_level.top_level code }
749
750plus_exp_body:
751 f=loption(filespec)
752 b=top_eexpr
978fd7e5
C
753 /*ew=loption(error_words)*/
754 { Top_level.top_level (f@[b](*@ew*)) }
34e49164
C
755
756filespec:
757 TMinusFile TPlusFile
758 { [Ast0.wrap
759 (Ast0.FILEINFO(P.id2mcode $1,
760 P.id2mcode $2))] }
761
762includes:
763 TIncludeL
764 { Ast0.wrap
7f004419
C
765 (Ast0.Include(P.clt2mcode "#include"
766 (P.drop_pos (P.drop_aft (P.id2clt $1))),
34e49164
C
767 let (arity,ln,lln,offset,col,strbef,straft,pos) =
768 P.id2clt $1 in
769 let clt =
770 (arity,ln,lln,offset,0,strbef,straft,pos) in
771 P.clt2mcode
772 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
773 (P.drop_bef clt))) }
774| TIncludeNL
775 { Ast0.wrap
7f004419
C
776 (Ast0.Include(P.clt2mcode "#include"
777 (P.drop_pos (P.drop_aft (P.id2clt $1))),
34e49164
C
778 let (arity,ln,lln,offset,col,strbef,straft,pos) =
779 P.id2clt $1 in
780 let clt =
781 (arity,ln,lln,offset,0,strbef,straft,pos) in
782 P.clt2mcode
783 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
784 (P.drop_bef clt))) }
5636bb2c
C
785| d=defineop TLineEnd
786 { d (Ast0.wrap(Ast0.DOTS([]))) }
34e49164
C
787| d=defineop t=ctype TLineEnd
788 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
789 d (Ast0.wrap(Ast0.DOTS([ty]))) }
790| defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
791 { let body =
792 match b with
793 [e] ->
794 (match Ast0.unwrap e with
795 Ast0.Exp(e1) ->
796 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
797 | _ -> b)
798 | _ -> b in
799 $1 (Ast0.wrap(Ast0.DOTS(body))) }
800
801defineop:
802 TDefine
803 { let (clt,ident) = $1 in
804 function body ->
805 Ast0.wrap
806 (Ast0.Define
807 (P.clt2mcode "#define" clt,
808 (match ident with
809 TMetaId((nm,constraints,pure,clt)) ->
810 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
811 | TIdent(nm_pure) ->
812 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
813 | _ ->
814 raise
815 (Semantic_cocci.Semantic
816 "unexpected name for a #define")),
817 Ast0.wrap Ast0.NoParams,
818 body)) }
819| TDefineParam define_param_list_option TCPar
708f4980
C
820 { let (clt,ident,parenoff,parencol) = $1 in
821 (* clt is the start of the #define itself *)
34e49164
C
822 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
823 let lp =
0708f913 824 P.clt2mcode "("
708f4980 825 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
34e49164
C
826 function body ->
827 Ast0.wrap
828 (Ast0.Define
829 (P.clt2mcode "#define" clt,
830 (match ident with
831 TMetaId((nm,constraints,pure,clt)) ->
832 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
833 | TIdent(nm_pure) ->
834 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
835 | _ ->
836 raise
837 (Semantic_cocci.Semantic
838 "unexpected name for a #define")),
839 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
840
841/* ---------------------------------------------------------------------- */
842
c491d8ee
C
843dparam: ident { Ast0.wrap(Ast0.DParam $1) }
844
845define_param_list_option:
846 empty_list_start(dparam,TEllipsis)
847 { Ast0.wrap
848 (Ast0.DOTS
849 ($1
850 (fun _ d -> Ast0.wrap(Ast0.DPdots(P.clt2mcode "," d)))
851 (fun c -> Ast0.DPComma c))) }
34e49164
C
852
853/*****************************************************************************/
854
855funproto:
856 s=ioption(storage) t=ctype
857 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
858 { Ast0.wrap
859 (Ast0.UnInit
860 (s,
861 Ast0.wrap
862 (Ast0.FunctionType(Some t,
863 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
864 id, P.clt2mcode ";" pt)) }
34e49164
C
865
866fundecl:
867 f=fninfo
868 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
869 lb=TOBrace b=fun_start rb=TCBrace
978fd7e5
C
870 { P.verify_parameter_declarations (Ast0.undots d);
871 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
34e49164
C
872 f, i,
873 P.clt2mcode "(" lp, d,
874 P.clt2mcode ")" rp,
875 P.clt2mcode "{" lb, b,
876 P.clt2mcode "}" rb)) }
877
878fninfo:
879 /* empty */ { [] }
880 | storage fninfo
881 { try
882 let _ =
883 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
884 raise (Semantic_cocci.Semantic "duplicate storage")
885 with Not_found -> (Ast0.FStorage($1))::$2 }
978fd7e5 886 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
34e49164
C
887 | Tinline fninfo
888 { try
889 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
890 raise (Semantic_cocci.Semantic "duplicate inline")
891 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
892 | Tattr fninfo
893 { try
894 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
895 raise (Semantic_cocci.Semantic "multiple attributes")
896 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
897
898fninfo_nt:
899 /* empty */ { [] }
900 | storage fninfo_nt
901 { try
902 let _ =
903 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
904 raise (Semantic_cocci.Semantic "duplicate storage")
905 with Not_found -> (Ast0.FStorage($1))::$2 }
906 | Tinline fninfo_nt
907 { try
908 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
909 raise (Semantic_cocci.Semantic "duplicate inline")
910 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
911 | Tattr fninfo_nt
912 { try
913 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
914 raise (Semantic_cocci.Semantic "duplicate init")
915 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
916
917storage:
918 s=Tstatic { P.clt2mcode Ast.Static s }
919 | s=Tauto { P.clt2mcode Ast.Auto s }
920 | s=Tregister { P.clt2mcode Ast.Register s }
921 | s=Textern { P.clt2mcode Ast.Extern s }
922
923decl: t=ctype i=ident
924 { Ast0.wrap(Ast0.Param(t, Some i)) }
978fd7e5
C
925 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
926 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
34e49164
C
927 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
928 { let fnptr =
929 Ast0.wrap
930 (Ast0.FunctionPointer
931 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
932 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
933 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
34e49164
C
934 | TMetaParam
935 { let (nm,pure,clt) = $1 in
936 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
937
938name_opt_decl:
939 decl { $1 }
978fd7e5 940 | t=ctype lp=TOPar s=TMul rp=TCPar
34e49164
C
941 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
942 { let fnptr =
943 Ast0.wrap
944 (Ast0.FunctionPointer
945 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
946 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
947 Ast0.wrap(Ast0.Param(fnptr, None)) }
948
949const_vol:
950 Tconst { P.clt2mcode Ast.Const $1 }
951 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
952
953/*****************************************************************************/
954
955statement:
956 includes { $1 } /* shouldn't be allowed to be a single_statement... */
957| TMetaStm
958 { P.meta_stm $1 }
959| expr TPtVirg
960 { P.exp_stm $1 $2 }
961| TIf TOPar eexpr TCPar single_statement %prec TIf
962 { P.ifthen $1 $2 $3 $4 $5 }
963| TIf TOPar eexpr TCPar single_statement TElse single_statement
964 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
965| TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
966 option(eexpr) TCPar single_statement
967 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
968| TWhile TOPar eexpr TCPar single_statement
969 { P.whileloop $1 $2 $3 $4 $5 }
970| TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
971 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
972| iter_ident TOPar eexpr_list_option TCPar single_statement
973 { P.iterator $1 $2 $3 $4 $5 }
fc1ad971
C
974| TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
975 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
34e49164
C
976| TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
977| TReturn TPtVirg { P.ret $1 $2 }
978| TBreak TPtVirg { P.break $1 $2 }
979| TContinue TPtVirg { P.cont $1 $2 }
980| ident TDotDot { P.label $1 $2 }
981| TGoto ident TPtVirg { P.goto $1 $2 $3 }
982| TOBrace fun_start TCBrace
983 { P.seq $1 $2 $3 }
984
985stm_dots:
986 TEllipsis w=list(whenppdecs)
987 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
988| TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
989 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
990 P.clt2mcode "...>" c, List.concat w, false)) }
991| TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
992 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
993 P.clt2mcode "...+>" c, List.concat w, true)) }
994
faf9a90c
C
995%inline stm_dots_ell:
996 a=TEllipsis w=list(whenppdecs)
997 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
998
999%inline stm_dots_nest:
1000 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
1001 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
1002 P.clt2mcode "...>" c, List.concat w, false)) }
1003| a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
1004 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
1005 P.clt2mcode "...+>" c, List.concat w, true)) }
1006
708f4980 1007whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
34e49164
C
1008 { w }
1009
1010/* a statement that fits into a single rule_elem. should nests be included?
1011what about statement metavariables? */
1012rule_elem_statement:
1013 one_decl_var
1014 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
1015| expr TPtVirg { P.exp_stm $1 $2 }
1016| TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
1017| TReturn TPtVirg { P.ret $1 $2 }
1018| TBreak TPtVirg { P.break $1 $2 }
1019| TContinue TPtVirg { P.cont $1 $2 }
1020| TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
1021 { let (mids,code) = $2 in
1022 Ast0.wrap
1023 (Ast0.Disj(P.clt2mcode "(" $1,
1024 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1025 mids, P.clt2mcode ")" $3)) }
1026
1027/* a statement on its own */
1028single_statement:
1029 statement { $1 }
1030 | TOPar0 midzero_list(statement,statement) TCPar0
1031 /* degenerate case, elements are single statements and thus don't
1032 contain dots */
1033 { let (mids,code) = $2 in
1034 Ast0.wrap
1035 (Ast0.Disj(P.clt2mcode "(" $1,
1036 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1037 mids, P.clt2mcode ")" $3)) }
1038
1039case_line:
1040 TDefault TDotDot fun_start
fc1ad971
C
1041 { Ast0.wrap
1042 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
34e49164
C
1043 | TCase eexpr TDotDot fun_start
1044 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
fc1ad971
C
1045/* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
1046 { let (mids,code) = ([],[t]) in
1047 Ast0.wrap
1048 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
34e49164
C
1049
1050/* In the following, an identifier as a type is not fully supported. Indeed,
1051the language is ambiguous: what is foo * bar; */
1052/* The AST DisjDecl cannot be generated because it would be ambiguous with
1053a disjunction on a statement with a declaration in each branch */
1054decl_var:
1055 t=ctype pv=TPtVirg
1056 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
413ffc02 1057 | TMetaDecl { [P.meta_decl $1] }
34e49164
C
1058 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
1059 { List.map
1060 (function (id,fn) ->
1061 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
1062 d }
1063 | f=funproto { [f] }
1064 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1065 {let (id,fn) = d in
1066 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1067 /* type is a typedef name */
1068 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1069 d=comma_list(d_ident) pv=TPtVirg
1070 { List.map
1071 (function (id,fn) ->
1072 let idtype =
1073 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1074 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
1075 d }
1076 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1077 e=initialize pv=TPtVirg
1078 { let (id,fn) = d in
1079 !Data.add_type_name (P.id2name i);
1080 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1081 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1082 P.clt2mcode ";" pv))] }
1083 /* function pointer type */
1084 | s=ioption(storage)
978fd7e5 1085 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
1086 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1087 pv=TPtVirg
1088 { let (id,fn) = d in
1089 let t =
1090 Ast0.wrap
1091 (Ast0.FunctionPointer
1092 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1093 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1094 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
1095 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1096 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
faf9a90c 1097 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
34e49164 1098 | s=ioption(storage)
978fd7e5 1099 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
1100 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1101 q=TEq e=initialize pv=TPtVirg
1102 { let (id,fn) = d in
1103 let t =
1104 Ast0.wrap
1105 (Ast0.FunctionPointer
1106 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1107 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1108 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
002099fc 1109 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
34e49164 1110 { let s = P.clt2mcode "typedef" s in
002099fc
C
1111 List.map
1112 (function id ->
1113 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1114 id }
34e49164
C
1115
1116one_decl_var:
1117 t=ctype pv=TPtVirg
1118 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
413ffc02 1119 | TMetaDecl { P.meta_decl $1 }
34e49164
C
1120 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1121 { let (id,fn) = d in
1122 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1123 | f=funproto { f }
1124 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1125 { let (id,fn) = d in
1126 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1127 /* type is a typedef name */
1128 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1129 d=d_ident pv=TPtVirg
1130 { let (id,fn) = d in
1131 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1132 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1133 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1134 e=initialize pv=TPtVirg
1135 { let (id,fn) = d in
1136 !Data.add_type_name (P.id2name i);
1137 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1138 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1139 P.clt2mcode ";" pv)) }
1140 /* function pointer type */
1141 | s=ioption(storage)
978fd7e5 1142 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
1143 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1144 pv=TPtVirg
1145 { let (id,fn) = d in
1146 let t =
1147 Ast0.wrap
1148 (Ast0.FunctionPointer
1149 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1150 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1151 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1152 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1153 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
faf9a90c 1154 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
34e49164 1155 | s=ioption(storage)
978fd7e5 1156 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
1157 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1158 q=TEq e=initialize pv=TPtVirg
1159 { let (id,fn) = d in
1160 let t =
1161 Ast0.wrap
1162 (Ast0.FunctionPointer
1163 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1164 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1165 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1166
1167
1168d_ident:
1169 ident list(array_dec)
1170 { ($1,
1171 function t ->
1172 List.fold_right
1173 (function (l,i,r) ->
1174 function rest ->
1175 Ast0.wrap
1176 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1177 $2 t) }
1178
1179array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1180
1181initialize:
1182 eexpr
1183 { Ast0.wrap(Ast0.InitExpr($1)) }
1184 | TOBrace initialize_list TCBrace
c491d8ee
C
1185 { if P.struct_initializer $2
1186 then
1187 let il = P.drop_dot_commas $2 in
1188 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1189 else
1190 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
113803cf
C
1191 | TMetaInit
1192 {let (nm,pure,clt) = $1 in
1193 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
34e49164
C
1194
1195initialize2:
1196 /*arithexpr and not eexpr because can have ambiguity with comma*/
1197 /*dots and nests probably not allowed at top level, haven't looked into why*/
1198 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1199| TOBrace initialize_list TCBrace
c491d8ee
C
1200 { if P.struct_initializer $2
1201 then
1202 let il = P.drop_dot_commas $2 in
1203 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1204 else
1205 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
34e49164 1206 /* gccext:, labeled elements */
c491d8ee 1207| list(designator) TEq initialize2 /*can we have another of these on the rhs?*/
113803cf 1208 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
34e49164
C
1209| ident TDotDot initialize2
1210 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
113803cf 1211
951c7801
C
1212designator:
1213 | TDot ident
1214 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1215 | TOCro eexpr TCCro
113803cf 1216 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
951c7801 1217 | TOCro eexpr TEllipsis eexpr TCCro
113803cf
C
1218 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1219 $4,P.clt2mcode "]" $5) }
34e49164
C
1220
1221initialize_list:
c491d8ee
C
1222 empty_list_start(initialize2,edots_when(TEllipsis,initialize))
1223 { Ast0.wrap(Ast0.DOTS($1 P.mkidots (fun c -> Ast0.IComma c))) }
34e49164
C
1224
1225/* a statement that is part of a list */
1226decl_statement:
1227 TMetaStmList
1228 { let (nm,pure,clt) = $1 in
1229 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1230 | decl_var
1231 { List.map
1232 (function x ->
1233 Ast0.wrap
1234 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1235 $1 }
1236 | statement { [$1] }
1237 /* this doesn't allow expressions at top level, because the parser doesn't
1238 know whether there is one. If there is one, this is not sequencible.
1239 If there is not one, then it is. It seems complicated to get around
1240 this at the parser level. We would have to have a check afterwards to
1241 allow this. One case where this would be useful is for a when. Now
1242 we allow a sequence of whens, so one can be on only statements and
1243 one can be on only expressions. */
1244 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1245 { let (mids,code) = t in
1246 if List.for_all
1247 (function x ->
1248 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1249 code
1250 then []
1251 else
1252 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1253 P.clt2mcode ")" $3))] }
1254
1255/* a statement that is part of a list */
1256decl_statement_expr:
1257 TMetaStmList
1258 { let (nm,pure,clt) = $1 in
1259 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1260 | decl_var
1261 { List.map
1262 (function x ->
1263 Ast0.wrap
1264 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1265 $1 }
1266 | statement { [$1] }
1267 /* this doesn't allow expressions at top level, because the parser doesn't
1268 know whether there is one. If there is one, this is not sequencible.
1269 If there is not one, then it is. It seems complicated to get around
1270 this at the parser level. We would have to have a check afterwards to
1271 allow this. One case where this would be useful is for a when. Now
1272 we allow a sequence of whens, so one can be on only statements and
1273 one can be on only expressions. */
1274 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1275 { let (mids,code) = t in
1276 if List.for_all (function [] -> true | _ -> false) code
1277 then []
1278 else
1279 let dot_code =
1280 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1281 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1282 P.clt2mcode ")" $3))] }
1283
1284/*****************************************************************************/
1285
1286/* The following cannot contain <... ...> at the top level. This can only
1287be allowed as an expression when the expression is delimited on both sides
1288by expression-specific markers. In that case, the rule eexpr is used, which
1289allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1290in practice. */
1291expr: basic_expr(expr,invalid) { $1 }
1292/* allows ... and nests */
1293eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1294/* allows nests but not .... */
1295dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1296
1297top_eexpr:
1298 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1299
1300invalid:
1301 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1302
1303dot_expressions:
1304 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1305| nest_expressions { $1 }
1306
485bce71 1307/* not clear what whencode would mean, so just drop it */
34e49164 1308nest_expressions:
485bce71 1309 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
34e49164
C
1310 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1311 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
485bce71
C
1312 P.clt2mcode "...>" c, None, false)) }
1313| TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
34e49164
C
1314 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1315 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
485bce71 1316 P.clt2mcode "...+>" c, None, true)) }
34e49164 1317
485bce71 1318//whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
34e49164
C
1319
1320basic_expr(recurser,primary_extra):
1321 assign_expr(recurser,primary_extra) { $1 }
1322
1323assign_expr(r,pe):
1324 cond_expr(r,pe) { $1 }
1325 | unary_expr(r,pe) TAssign assign_expr_bis
1326 { let (op,clt) = $2 in
1327 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1328 Ast0.set_arg_exp $3,false)) }
1329 | unary_expr(r,pe) TEq assign_expr_bis
1330 { Ast0.wrap
1331 (Ast0.Assignment
1332 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1333
1334assign_expr_bis:
1335 cond_expr(eexpr,dot_expressions) { $1 }
1336 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1337 { let (op,clt) = $2 in
1338 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1339 Ast0.set_arg_exp $3,false)) }
1340 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1341 { Ast0.wrap
1342 (Ast0.Assignment
1343 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1344
1345cond_expr(r,pe):
1346 arith_expr(r,pe) { $1 }
1347 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1348 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1349 P.clt2mcode ":" dd, r)) }
1350
1351arith_expr(r,pe):
1352 cast_expr(r,pe) { $1 }
1353 | arith_expr(r,pe) TMul arith_expr(r,pe)
1354 { P.arith_op Ast.Mul $1 $2 $3 }
1355 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1356 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1357 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1358 { P.arith_op Ast.Plus $1 $2 $3 }
1359 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1360 { P.arith_op Ast.Minus $1 $2 $3 }
413ffc02
C
1361 | arith_expr(r,pe) TShLOp arith_expr(r,pe)
1362 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1363 | arith_expr(r,pe) TShROp arith_expr(r,pe)
34e49164
C
1364 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1365 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1366 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1367 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1368 { P.logic_op Ast.Eq $1 $2 $3 }
1369 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1370 { P.logic_op Ast.NotEq $1 $2 $3 }
1371 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1372 { P.arith_op Ast.And $1 $2 $3 }
1373 | arith_expr(r,pe) TOr arith_expr(r,pe)
1374 { P.arith_op Ast.Or $1 $2 $3 }
1375 | arith_expr(r,pe) TXor arith_expr(r,pe)
1376 { P.arith_op Ast.Xor $1 $2 $3 }
1377 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1378 { P.logic_op Ast.AndLog $1 $2 $3 }
1379 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1380 { P.logic_op Ast.OrLog $1 $2 $3 }
1381
1382cast_expr(r,pe):
1383 unary_expr(r,pe) { $1 }
1384 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1385 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1386 P.clt2mcode ")" rp, e)) }
1387
1388unary_expr(r,pe):
1389 postfix_expr(r,pe) { $1 }
1390 | TInc unary_expr(r,pe)
1391 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1392 | TDec unary_expr(r,pe)
1393 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
0708f913 1394 | unary_op cast_expr(r,pe)
34e49164
C
1395 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1396 | TBang unary_expr(r,pe)
1397 { let mcode = P.clt2mcode Ast.Not $1 in
1398 Ast0.wrap(Ast0.Unary($2, mcode)) }
1399 | TSizeof unary_expr(r,pe)
1400 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1401 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1402 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1403 P.clt2mcode "(" lp,t,
1404 P.clt2mcode ")" rp)) }
1405
1406unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1407 | TMul { P.clt2mcode Ast.DeRef $1 }
1408 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1409 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1410 | TTilde { P.clt2mcode Ast.Tilde $1 }
1411
1412postfix_expr(r,pe):
1413 primary_expr(r,pe) { $1 }
1414 | postfix_expr(r,pe) TOCro eexpr TCCro
1415 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1416 P.clt2mcode "]" $4)) }
1417 | postfix_expr(r,pe) TDot ident
1418 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1419 | postfix_expr(r,pe) TPtrOp ident
1420 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1421 $3)) }
1422 | postfix_expr(r,pe) TInc
1423 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1424 | postfix_expr(r,pe) TDec
1425 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1426 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1427 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1428 $3,
1429 P.clt2mcode ")" $4)) }
1430
1431primary_expr(recurser,primary_extra):
1432 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1433 | TInt
1434 { let (x,clt) = $1 in
1435 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1436 | TFloat
1437 { let (x,clt) = $1 in
1438 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1439 | TString
1440 { let (x,clt) = $1 in
1441 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1442 | TChar
1443 { let (x,clt) = $1 in
1444 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1445 | TMetaConst
1446 { let (nm,constraints,pure,ty,clt) = $1 in
1447 Ast0.wrap
1448 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1449 | TMetaErr
1450 { let (nm,constraints,pure,clt) = $1 in
1451 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1452 | TMetaExp
1453 { let (nm,constraints,pure,ty,clt) = $1 in
1454 Ast0.wrap
1455 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1456 | TMetaIdExp
1457 { let (nm,constraints,pure,ty,clt) = $1 in
1458 Ast0.wrap
1459 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1460 | TMetaLocalIdExp
1461 { let (nm,constraints,pure,ty,clt) = $1 in
1462 Ast0.wrap
1463 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1464 | TOPar eexpr TCPar
1465 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1466 P.clt2mcode ")" $3)) }
1467 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1468 { let (mids,code) = $2 in
1469 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1470 code, mids,
1471 P.clt2mcode ")" $3)) }
1472 | primary_extra { $1 }
1473
1474expr_dots(dotter):
1475 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1476
1477// used in NEST
1478no_dot_start_end(grammar,dotter):
1479 g=grammar dg=list(pair(dotter,grammar))
1480 { function dot_builder ->
1481 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1482
1483/*****************************************************************************/
1484
1485pure_ident:
1486 TIdent { $1 }
1487
ae4735db
C
1488pure_ident_kwd:
1489 | TIdentifier { "identifier" }
1490 | TExpression { "expression" }
1491 | TStatement { "statement" }
1492 | TFunction { "function" }
1493 | TLocal { "local" }
1494 | TType { "type" }
1495 | TParameter { "parameter" }
1496 | TIdExpression { "idexpression" }
1497 | TInitialiser { "initialiser" }
1498 | Tlist { "list" }
1499 | TFresh { "fresh" }
1500 | TConstant { "constant" }
1501 | TError { "error" }
1502 | TWords { "words" }
1503 | TPure { "pure" }
1504 | TContext { "context" }
1505 | TGenerated { "generated" }
1506 | TTypedef { "typedef" }
1507 | TDeclarer { "declarer" }
1508 | TIterator { "iterator" }
1509 | TName { "name" }
1510 | TPosition { "position" }
1511
34e49164 1512meta_ident:
ae4735db
C
1513 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1514 | TRuleName TDot pure_ident_kwd { (Some $1,$3) }
34e49164
C
1515
1516pure_ident_or_meta_ident:
1517 pure_ident { (None,P.id2name $1) }
ae4735db 1518 | pure_ident_kwd { (None,$1) }
34e49164 1519 | meta_ident { $1 }
34e49164 1520
b1b2de81 1521pure_ident_or_meta_ident_with_seed:
978fd7e5
C
1522 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1523 | pure_ident_or_meta_ident TEq
1524 separated_nonempty_list(TCppConcatOp,seed_elem)
1525 { match $3 with
1526 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1527 | _ -> ($1,Ast.ListSeed $3) }
1528
1529seed_elem:
1530 TString { let (x,_) = $1 in Ast.SeedString x }
1531| TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1532| TRuleName TDot pure_ident
1533 { let nm = ($1,P.id2name $3) in
1534 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1535 Ast.SeedId nm }
b1b2de81 1536
951c7801
C
1537pure_ident_or_meta_ident_with_x_eq(x_eq):
1538 i=pure_ident_or_meta_ident l=loption(x_eq)
1539 {
1540 (i, l)
1541 }
1542
1543pure_ident_or_meta_ident_with_econstraint(x_eq):
1544 i=pure_ident_or_meta_ident optc=option(x_eq)
1545 {
1546 match optc with
1547 None -> (i, Ast0.NoConstraint)
1548 | Some c -> (i, c)
1549 }
1550
ae4735db
C
1551pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
1552 i=pure_ident_or_meta_ident c=option(constraint_type)
1553 {
1554 Common.Left
1555 (match c with
1556 None -> (i, Ast.IdNoConstraint)
1557 | Some constraint_ -> (i,constraint_))
1558 }
1559| TVirtual TDot pure_ident { Common.Right (P.id2name $3) }
1560
951c7801
C
1561pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1562 i=pure_ident_or_meta_ident c=option(constraint_type)
1563 {
1564 match c with
1565 None -> (i, Ast.IdNoConstraint)
1566 | Some constraint_ -> (i,constraint_)
1567 }
1568
1569re_or_not_eqid:
5636bb2c 1570 re=regexp_eqid {Ast.IdRegExpConstraint re}
951c7801
C
1571 | ne=not_eqid {ne}
1572
1573regexp_eqid:
5636bb2c 1574 TTildeEq re=TString
951c7801
C
1575 { (if !Data.in_iso
1576 then failwith "constraints not allowed in iso file");
1577 (if !Data.in_generating
1578 then failwith "constraints not allowed in a generated rule file");
1579 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1580 }
1581 | TTildeExclEq re=TString
1582 { (if !Data.in_iso
1583 then failwith "constraints not allowed in iso file");
1584 (if !Data.in_generating
1585 then failwith "constraints not allowed in a generated rule file");
1586 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1587 }
34e49164 1588
951c7801 1589not_eqid:
c3e37e97 1590 TNotEq i=pure_ident_or_meta_ident
34e49164
C
1591 { (if !Data.in_iso
1592 then failwith "constraints not allowed in iso file");
faf9a90c
C
1593 (if !Data.in_generating
1594 (* pb: constraints not stored with metavars; too lazy to search for
1595 them in the pattern *)
1596 then failwith "constraints not allowed in a generated rule file");
5636bb2c
C
1597 (match i with
1598 (Some rn,id) ->
1599 let i =
1600 P.check_inherited_constraint i
1601 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1602 Ast.IdNegIdSet([],[i])
1603 | (None,i) -> Ast.IdNegIdSet([i],[])) }
c3e37e97 1604 | TNotEq TOBrace l=comma_list(pure_ident_or_meta_ident) TCBrace
34e49164
C
1605 { (if !Data.in_iso
1606 then failwith "constraints not allowed in iso file");
faf9a90c
C
1607 (if !Data.in_generating
1608 then failwith "constraints not allowed in a generated rule file");
5636bb2c
C
1609 let (str,meta) =
1610 List.fold_left
1611 (function (str,meta) ->
1612 function
1613 (Some rn,id) as i ->
1614 let i =
1615 P.check_inherited_constraint i
1616 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1617 (str,i::meta)
1618 | (None,i) -> (i::str,meta))
1619 ([],[]) l in
1620 Ast.IdNegIdSet(str,meta)
951c7801
C
1621 }
1622
5636bb2c
C
1623re_or_not_eqe_or_sub:
1624 re=regexp_eqid {Ast0.NotIdCstrt re}
1625 | ne=not_eqe {Ast0.NotExpCstrt ne}
1626 | s=sub {Ast0.SubExpCstrt s}
1627
1628not_ceq_or_sub:
1629 ceq=not_ceq {Ast0.NotExpCstrt ceq}
1630 | s=sub {Ast0.SubExpCstrt s}
34e49164
C
1631
1632not_eqe:
1633 TNotEq i=pure_ident
1634 { (if !Data.in_iso
1635 then failwith "constraints not allowed in iso file");
faf9a90c
C
1636 (if !Data.in_generating
1637 then failwith "constraints not allowed in a generated rule file");
951c7801
C
1638 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1639 }
34e49164
C
1640 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1641 { (if !Data.in_iso
1642 then failwith "constraints not allowed in iso file");
faf9a90c
C
1643 (if !Data.in_generating
1644 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1645 List.map
1646 (function i ->
951c7801
C
1647 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1648 l
1649 }
34e49164
C
1650
1651not_ceq:
1652 TNotEq i=ident_or_const
1653 { (if !Data.in_iso
1654 then failwith "constraints not allowed in iso file");
faf9a90c
C
1655 (if !Data.in_generating
1656 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1657 [i] }
1658 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1659 { (if !Data.in_iso
1660 then failwith "constraints not allowed in iso file");
faf9a90c
C
1661 (if !Data.in_generating
1662 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1663 l }
1664
5636bb2c
C
1665sub:
1666 (* has to be inherited because not clear how to check subterm constraints
1667 in the functorized CTL engine, so need the variable to be bound
1668 already when bind the subterm constrained metavariable *)
1669 TSub i=meta_ident
1670 { (if !Data.in_iso
1671 then failwith "constraints not allowed in iso file");
1672 (if !Data.in_generating
1673 then failwith "constraints not allowed in a generated rule file");
1674 let i =
1675 P.check_inherited_constraint i
1676 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in
1677 [i] }
1678 | TSub TOBrace l=comma_list(meta_ident) TCBrace
1679 { (if !Data.in_iso
1680 then failwith "constraints not allowed in iso file");
1681 (if !Data.in_generating
1682 then failwith "constraints not allowed in a generated rule file");
1683 List.map
1684 (function i ->
1685 P.check_inherited_constraint i
1686 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)))
1687 l}
1688
34e49164
C
1689ident_or_const:
1690 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1691 | TInt
1692 { let (x,clt) = $1 in
1693 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1694
1695not_pos:
1696 TNotEq i=meta_ident
1697 { (if !Data.in_iso
1698 then failwith "constraints not allowed in iso file");
faf9a90c
C
1699 (if !Data.in_generating
1700 then failwith "constraints not allowed in a generated rule file");
5636bb2c
C
1701 let i =
1702 P.check_inherited_constraint i
1703 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in
1704 [i] }
34e49164
C
1705 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1706 { (if !Data.in_iso
1707 then failwith "constraints not allowed in iso file");
faf9a90c
C
1708 (if !Data.in_generating
1709 then failwith "constraints not allowed in a generated rule file");
34e49164 1710 List.map
5636bb2c
C
1711 (function i ->
1712 P.check_inherited_constraint i
1713 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
34e49164
C
1714 l }
1715
1716func_ident: pure_ident
1717 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1718 | TMetaId
1719 { let (nm,constraints,pure,clt) = $1 in
1720 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1721 | TMetaFunc
1722 { let (nm,constraints,pure,clt) = $1 in
1723 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1724 | TMetaLocalFunc
1725 { let (nm,constraints,pure,clt) = $1 in
1726 Ast0.wrap
1727 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1728
1729ident: pure_ident
1730 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1731 | TMetaId
1732 { let (nm,constraints,pure,clt) = $1 in
1733 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1734
1735decl_ident:
1736 TDeclarerId
1737 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1738 | TMetaDeclarer
1739 { let (nm,constraints,pure,clt) = $1 in
1740 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1741
1742iter_ident:
1743 TIteratorId
1744 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1745 | TMetaIterator
1746 { let (nm,constraints,pure,clt) = $1 in
1747 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1748
1749typedef_ident:
1750 pure_ident
1751 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1752 | TMetaType
1753 { let (nm,pure,clt) = $1 in
1754 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1755
1756/*****************************************************************************/
1757
1758decl_list(decl):
c491d8ee
C
1759 empty_list_start(one_dec(decl),TEllipsis)
1760 { Ast0.wrap
1761 (Ast0.DOTS
1762 ($1
1763 (fun _ d -> Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." d)))
1764 (fun c -> Ast0.PComma c))) }
34e49164
C
1765
1766one_dec(decl):
1767 decl { $1 }
1768| TMetaParamList
1769 { let (nm,lenname,pure,clt) = $1 in
1770 let nm = P.clt2mcode nm clt in
88e71198
C
1771 let lenname =
1772 match lenname with
1773 Ast.AnyLen -> Ast0.AnyListLen
1774 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
1775 | Ast.CstLen n -> Ast0.CstListLen n in
34e49164 1776 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
faf9a90c 1777
c491d8ee
C
1778/* ---------------------------------------------------------------------- */
1779/* comma list parser, used for fn params, fn args, enums, initlists,
1780 #define params */
1781
1782/* enums: enum_decl, edots_when(TEllipsis,enum_decl_one)
1783fun s d -> P.mkedots "..." d
1784fun c -> Ast0.EComma c
1785 */
1786
1787empty_list_start(elem,dotter):
1788 /* empty */ { fun build_dots build_comma -> [] }
1789| nonempty_list_start(elem,dotter) { $1 }
1790
1791nonempty_list_start(elem,dotter): /* dots allowed */
1792 elem { fun build_dots build_comma -> [$1] }
1793| elem TComma
1794 { fun build_dots build_comma ->
1795 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1796| elem TComma nonempty_list_start(elem,dotter)
1797 { fun build_dots build_comma ->
1798 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1799 ($3 build_dots build_comma) }
1800| TNothing nonempty_list_start(elem,dotter) { $2 }
1801| d=dotter { fun build_dots build_comma -> [(build_dots "..." d)] }
1802| d=dotter TComma
1803 { fun build_dots build_comma ->
1804 [(build_dots "..." d);Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1805| d=dotter TComma r=continue_list(elem,dotter)
1806 { fun build_dots build_comma ->
1807 (build_dots "..." d)::
1808 (Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1809 (r build_dots build_comma) }
1810
1811continue_list(elem,dotter): /* dots not allowed */
1812 elem { fun build_dots build_comma -> [$1] }
1813| elem TComma
1814 { fun build_dots build_comma ->
1815 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1816| elem TComma nonempty_list_start(elem,dotter)
1817 { fun build_dots build_comma ->
1818 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1819 ($3 build_dots build_comma) }
1820| TNothing nonempty_list_start(elem,dotter) { $2 }
34e49164
C
1821
1822/* ---------------------------------------------------------------------- */
1823
978fd7e5
C
1824/* error words make it complicated to be able to use error as a metavariable
1825name or a type in a metavariable list; for that we would like to allow TError
1826as an ident, but that makes conflicts with this rule. To add back error words,
1827need to find some appropriate delimiter for it, but it has not been used much
1828so just drop it */
1829/*error_words:
34e49164
C
1830 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1831 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
978fd7e5 1832*/
34e49164
C
1833
1834/* ---------------------------------------------------------------------- */
1835/* sequences of statements and expressions */
1836
1837/* There are number of cases that must be considered:
1838
18391. Top level:
1840 Dots and nests allowed at the beginning or end
1841 Expressions allowed at the beginning or end
1842 One function allowed, by itself
18432. A function body:
1844 Dots and nests allowed at the beginning or end
1845 Expressions not allowed at the beginning or end
1846 Functions not allowed
18473. The body of a nest:
1848 Dots and nests not allowed at the beginning or end
1849 Expressions allowed at the beginning or end
1850 Functions not allowed
18514. Whencode:
1852 Dots and nests not allowed at the beginning but allowed at the end
1853 Expressions allowed at the beginning or end
1854 Functions not allowed
1855
1856These are implemented by the rules minus_toplevel_sequence,
1857plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1858when_body_sequence.
1859*/
1860/* ------------------------------------------------------------------------ */
1861/* Minus top level */
1862
1863/* doesn't allow only ... */
1864minus_start:
1865 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1866| ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1be43e12 1867| top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
faf9a90c 1868| toplevel_seq_startne(toplevel_after_dots_init)
34e49164
C
1869 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1870
faf9a90c
C
1871toplevel_seq_startne(after_dots_init):
1872 a=stm_dots_ell b=after_dots_init { a::b }
1873| a=stm_dots_nest b=after_dots_init { a::b }
1874| a=stm_dots_nest { [a] }
1875| expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1876| decl_statement_expr toplevel_after_stm { $1@$2 }
1877
34e49164
C
1878toplevel_seq_start(after_dots_init):
1879 stm_dots after_dots_init { $1::$2 }
1880| expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1881| decl_statement_expr toplevel_after_stm { $1@$2 }
1882
1883toplevel_after_dots_init:
1884 TNothing toplevel_after_exp {$2}
1885| expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1886| decl_statement_expr toplevel_after_stm {$1@$2}
1887
1888toplevel_after_exp:
1889 /* empty */ {[]}
1890| stm_dots toplevel_after_dots {$1::$2}
1891
1892toplevel_after_dots:
1893 /* empty */ {[]}
1894| TNothing toplevel_after_exp {$2}
1895| expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1896| decl_statement_expr toplevel_after_stm {$1@$2}
1897
1898toplevel_after_stm:
1899 /* empty */ {[]}
1900| stm_dots toplevel_after_dots {$1::$2}
1901| decl_statement toplevel_after_stm {$1@$2}
1902
1be43e12
C
1903top_init:
1904 TOInit initialize_list TCBrace
c491d8ee
C
1905 { if P.struct_initializer $2
1906 then
1907 let il = P.drop_dot_commas $2 in
1908 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1909 else
1910 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1be43e12 1911
34e49164
C
1912/* ------------------------------------------------------------------------ */
1913/* Plus top level */
1914
1915/* does allow only ... also allows multiple top-level functions */
1916plus_start:
1917 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1be43e12 1918| top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
34e49164
C
1919| stm_dots plus_after_dots
1920 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1921| expr plus_after_exp
1922 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1923| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1924| decl_statement_expr plus_after_stm
1925 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1926
1927plus_after_exp:
1928 /* empty */ {[]}
1929| stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1930
1931plus_after_dots:
1932 /* empty */ {[]}
1933| TNothing plus_after_exp {$2}
1934| expr plus_after_exp
1935 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1936| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1937| decl_statement_expr plus_after_stm
1938 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1939
1940plus_after_stm:
1941 /* empty */ {[]}
1942| stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1943| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1944| decl_statement plus_after_stm
1945 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1946
1947/* ------------------------------------------------------------------------ */
1948/* Function body */
1949
1950fun_start:
1951 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1952
1953fun_after_stm:
1954 /* empty */ {[]}
1955| stm_dots fun_after_dots {$1::$2}
1956| decl_statement fun_after_stm {$1@$2}
1957
1958fun_after_dots:
1959 /* empty */ {[]}
1960| TNothing fun_after_exp {$2}
1961| expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1962| decl_statement_expr fun_after_stm {$1@$2}
1963
1964fun_after_exp:
1965 stm_dots fun_after_dots {$1::$2}
1966
1967/* hack to allow mixing statements and expressions in an or */
1968fun_after_dots_or:
1969 /* empty */ {[]}
1970| TNothing fun_after_exp_or {$2}
1971| expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1972| decl_statement_expr fun_after_stm {$1@$2}
1973
1974fun_after_exp_or:
1975 /* empty */ {[]}
1976| stm_dots fun_after_dots {$1::$2}
1977
1978/* ------------------------------------------------------------------------ */
1979/* Nest body */
1980
1981nest_start:
1982 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1983
1984nest_after_dots:
1985 decl_statement_expr nest_after_stm {$1@$2}
1986| TNothing nest_after_exp {$2}
1987| expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1988
1989nest_after_stm:
1990 /* empty */ {[]}
1991| stm_dots nest_after_dots {$1::$2}
1992| decl_statement nest_after_stm {$1@$2}
1993
1994nest_after_exp:
1995 /* empty */ {[]}
1996| stm_dots nest_after_dots {$1::$2}
1997
1998/* ------------------------------------------------------------------------ */
1999/*Whencode*/
2000
2001when_start:
2002 expr toplevel_after_exp
2003 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
2004| decl_statement toplevel_after_stm
2005 { Ast0.wrap(Ast0.DOTS($1@$2)) }
2006
2007/* ---------------------------------------------------------------------- */
2008
34e49164
C
2009/* arg expr. may contain a type or a explist metavariable */
2010aexpr:
c491d8ee 2011 dexpr { Ast0.set_arg_exp $1 }
34e49164
C
2012 | TMetaExpList
2013 { let (nm,lenname,pure,clt) = $1 in
2014 let nm = P.clt2mcode nm clt in
2015 let lenname =
2016 match lenname with
88e71198
C
2017 Ast.AnyLen -> Ast0.AnyListLen
2018 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
2019 | Ast.CstLen n -> Ast0.CstListLen n in
34e49164
C
2020 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
2021 | ctype
2022 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
2023
c491d8ee
C
2024eexpr_list_option:
2025 empty_list_start(aexpr,TEllipsis)
2026 { Ast0.wrap
2027 (Ast0.DOTS
2028 ($1
2029 (fun _ d -> Ast0.wrap(Ast0.Edots(P.clt2mcode "..." d,None)))
2030 (fun c -> Ast0.EComma c))) }
34e49164
C
2031
2032/****************************************************************************/
2033
2034// non-empty lists - drop separator
2035comma_list(elem):
2036 separated_nonempty_list(TComma,elem) { $1 }
2037
2038midzero_list(elem,aft):
2039 a=elem b=list(mzl(aft))
2040 { let (mids,code) = List.split b in (mids,(a::code)) }
2041
2042mzl(elem):
2043 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
2044
2045edots_when(dotter,when_grammar):
2046 d=dotter { (d,None) }
2047 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
2048
708f4980 2049whens(when_grammar,simple_when_grammar,any_strict):
34e49164
C
2050 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
2051 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
2052 | TWhen comma_list(any_strict) TLineEnd
2053 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
1be43e12
C
2054 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
2055 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
34e49164
C
2056
2057any_strict:
2058 TAny { Ast.WhenAny }
2059 | TStrict { Ast.WhenStrict }
2060 | TForall { Ast.WhenForall }
2061 | TExists { Ast.WhenExists }
2062
2063/*****************************************************************************
2064*
2065*
2066*****************************************************************************/
2067
2068iso_main:
c3e37e97
C
2069 TIsoExpression e1=eexpr el=list(iso(eexpr)) EOF
2070 { let fn x = Ast0.ExprTag x in P.iso_adjust fn fn e1 el }
2071| TIsoArgExpression e1=eexpr el=list(iso(eexpr)) EOF
2072 { let fn x = Ast0.ArgExprTag x in P.iso_adjust fn fn e1 el }
2073| TIsoTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2074 { let fn x = Ast0.TestExprTag x in P.iso_adjust fn fn e1 el }
2075| TIsoToTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2076 { let ffn x = Ast0.ExprTag x in
2077 let fn x = Ast0.TestExprTag x in
2078 P.iso_adjust ffn fn e1 el }
34e49164 2079| TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
c3e37e97 2080 { let fn x = Ast0.StmtTag x in P.iso_adjust fn fn s1 sl }
34e49164 2081| TIsoType t1=ctype tl=list(iso(ctype)) EOF
c3e37e97 2082 { let fn x = Ast0.TypeCTag x in P.iso_adjust fn fn t1 tl }
34e49164 2083| TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
c3e37e97 2084 { let fn x = Ast0.DotsStmtTag x in P.iso_adjust fn fn e1 el }
34e49164
C
2085| TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
2086 { let check_one = function
2087 [x] -> x
2088 | _ ->
2089 raise
2090 (Semantic_cocci.Semantic
2091 "only one variable per declaration in an isomorphism rule") in
2092 let d1 = check_one d1 in
2093 let dl =
2094 List.map
2095 (function
2096 Common.Left x -> Common.Left(check_one x)
2097 | Common.Right x -> Common.Right(check_one x))
2098 dl in
c3e37e97 2099 let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl }
34e49164
C
2100
2101iso(term):
2102 TIso t=term { Common.Left t }
2103 | TRightIso t=term { Common.Right t }
2104
2105/*****************************************************************************
2106*
2107*
2108*****************************************************************************/
2109
2110never_used: TPragma { () }
2111 | TPArob TMetaPos { () }
2112 | TScriptData { () }
2113
ae4735db 2114script_meta_main:
413ffc02
C
2115 py=pure_ident TMPtVirg
2116 { ((Some (P.id2name py), None), None) }
2117 | py=pure_ident script_name_decl TMPtVirg
2118 { ((Some (P.id2name py), None), Some $2) }
2119 | TOPar TUnderscore TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2120 { ((None, Some (P.id2name ast)), Some $6) }
2121 | TOPar str=pure_ident TComma TUnderscore TCPar script_name_decl TMPtVirg
2122 { ((Some (P.id2name str), None), Some $6) }
2123 | TOPar str=pure_ident TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2124 { ((Some (P.id2name str), Some (P.id2name ast)), Some $6) }
aba5c457
C
2125
2126script_name_decl:
413ffc02 2127 TShLOp TRuleName TDot cocci=pure_ident
aba5c457
C
2128 { let nm = P.id2name cocci in
2129 let mv = Parse_aux.lookup $2 nm in
2130 (($2, nm), mv) }
413ffc02 2131 | TShLOp TVirtual TDot cocci=pure_ident
aba5c457
C
2132 { let nm = P.id2name cocci in
2133 let name = ("virtual", nm) in
2134 let mv = Ast.MetaIdDecl(Ast.NONE,name) in
413ffc02 2135 (name,mv) }