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