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