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