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