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