]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/cic_textual_parser/cicTextualParser.mly
5887fc072a1ea3a3b94c10c08383f5c4811349e5
[helm.git] / helm / ocaml / cic_textual_parser / cicTextualParser.mly
1 /* Copyright (C) 2000, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM 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 HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  */
25
26 %{
27  open Cic;;
28  module U = UriManager;;
29
30  exception InvalidSuffix of string;;
31  exception InductiveTypeURIExpected;;
32  exception UnknownIdentifier of string;;
33  exception ExplicitNamedSubstitutionAppliedToRel;;
34  exception TheLeftHandSideOfAnExplicitNamedSubstitutionMustBeAVariable;;
35  
36  (* merge removing duplicates of two lists free of duplicates *)
37  let union dom1 dom2 =
38   let rec filter =
39    function
40       [] -> []
41     | he::tl ->
42        if List.mem he dom1 then filter tl else he::(filter tl)
43   in
44    dom1 @ (filter dom2)
45  ;;
46
47  let get_index_in_list e =
48   let rec aux i =
49    function
50       [] -> raise Not_found
51     | (Some he)::_ when he = e -> i
52     | _::tl -> aux (i+1) tl
53   in
54    aux 1
55  ;;
56
57  (* Returns the first meta whose number is above the *)
58  (* number of the higher meta.                       *)
59  (*CSC: cut&pasted from proofEngine.ml *)
60  let new_meta () =
61   let rec aux =
62    function
63       None,[] -> 1
64     | Some n,[] -> n
65     | None,(n,_,_)::tl -> aux (Some n,tl)
66     | Some m,(n,_,_)::tl -> if n > m then aux (Some n,tl) else aux (Some m,tl)
67   in
68    1 + aux (None,!CicTextualParser0.metasenv)
69  ;;
70
71  (* identity_relocation_list_for_metavariable i canonical_context         *)
72  (* returns the identity relocation list, which is the list [1 ; ... ; n] *)
73  (* where n = List.length [canonical_context]                             *)
74  (*CSC: ma mi basta la lunghezza del contesto canonico!!!*)
75  (*CSC: cut&pasted from proofEngine.ml *)
76  let identity_relocation_list_for_metavariable canonical_context =
77   let canonical_context_length = List.length canonical_context in
78    let rec aux =
79     function
80        (_,[]) -> []
81      | (n,None::tl) -> None::(aux ((n+1),tl))
82      | (n,_::tl) -> (Some (Cic.Rel n))::(aux ((n+1),tl))
83    in
84     aux (1,canonical_context)
85  ;;
86
87  let deoptionize_exp_named_subst =
88   function
89      None -> [], (function _ -> [])
90    | Some (dom,mk_exp_named_subst) -> dom,mk_exp_named_subst
91  ;;
92
93  let term_of_con_uri uri exp_named_subst =
94   Const (uri,exp_named_subst)
95  ;;
96
97  let term_of_var_uri uri exp_named_subst =
98   Var (uri,exp_named_subst)
99  ;;
100
101  let term_of_indty_uri (uri,tyno) exp_named_subst =
102   MutInd (uri, tyno, exp_named_subst)
103  ;;
104
105  let term_of_indcon_uri (uri,tyno,consno) exp_named_subst =
106   MutConstruct (uri, tyno, consno, exp_named_subst)
107  ;;
108
109  let term_of_uri uri =
110   match uri with
111      CicTextualParser0.ConUri uri ->
112       term_of_con_uri uri
113    | CicTextualParser0.VarUri uri ->
114       term_of_var_uri uri
115    | CicTextualParser0.IndTyUri (uri,tyno) ->
116       term_of_indty_uri (uri,tyno) 
117    | CicTextualParser0.IndConUri (uri,tyno,consno) ->
118       term_of_indcon_uri (uri,tyno,consno)
119  ;;
120
121  let var_uri_of_id id interp =
122   let module CTP0 = CicTextualParser0 in
123    match interp id with
124       None -> raise (UnknownIdentifier id)
125     | Some (CTP0.Uri (CTP0.VarUri uri)) -> uri
126     | Some _ -> raise TheLeftHandSideOfAnExplicitNamedSubstitutionMustBeAVariable
127  ;;
128
129  let indty_uri_of_id id interp =
130   let module CTP0 = CicTextualParser0 in
131    match interp id with
132       None -> raise (UnknownIdentifier id)
133     | Some (CTP0.Uri (CTP0.IndTyUri (uri,tyno))) -> (uri,tyno)
134     | Some _ -> raise InductiveTypeURIExpected
135  ;;
136
137  let mk_implicit () =
138   let newmeta = new_meta () in
139    let new_canonical_context = [] in
140     let irl =
141      identity_relocation_list_for_metavariable new_canonical_context
142     in
143      CicTextualParser0.metasenv :=
144       [newmeta, new_canonical_context, Sort Type ;
145        newmeta+1, new_canonical_context, Meta (newmeta,irl);
146        newmeta+2, new_canonical_context, Meta (newmeta+1,irl)
147       ] @ !CicTextualParser0.metasenv ;
148      [], function _ -> Meta (newmeta+2,irl)
149  ;;
150 %}
151 %token <string> ID
152 %token <int> META
153 %token <int> NUM
154 %token <UriManager.uri> CONURI
155 %token <UriManager.uri> VARURI
156 %token <UriManager.uri * int> INDTYURI
157 %token <UriManager.uri * int * int> INDCONURI
158 %token ALIAS
159 %token LPAREN RPAREN PROD LAMBDA COLON DOT SET PROP TYPE CAST IMPLICIT NONE
160 %token LETIN FIX COFIX SEMICOLON LCURLY RCURLY CASE ARROW LBRACKET RBRACKET EOF
161 %right ARROW
162 %start main
163 %type <string list * ((string -> CicTextualParser0.interp_codomain option) -> Cic.term)> main
164 %%
165 main:
166  expr EOF { $1 }
167 ;
168 expr2:
169    CONURI exp_named_subst
170    { let dom,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
171       dom, function interp -> term_of_con_uri $1 (mk_exp_named_subst interp)
172    }
173  | VARURI exp_named_subst
174    { let dom,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
175       dom, function interp -> term_of_var_uri $1 (mk_exp_named_subst interp)
176    }
177  | INDTYURI exp_named_subst
178    { let dom,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
179       dom, function interp -> term_of_indty_uri $1 (mk_exp_named_subst interp)
180    }
181  | INDCONURI exp_named_subst
182    { let dom,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
183       dom, function interp -> term_of_indcon_uri $1 (mk_exp_named_subst interp)
184    }
185  | ID exp_named_subst
186    { try
187       let res =
188        Rel (get_index_in_list (Name $1) !CicTextualParser0.binders)
189       in
190        (match $2 with
191            None -> ([], function _ -> res)
192          | Some _ -> raise (ExplicitNamedSubstitutionAppliedToRel)
193        )
194      with
195       Not_found ->
196        let dom1,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
197         let dom = union dom1 [$1] in
198          dom,
199           function interp ->
200            match interp $1 with
201               None  -> raise (UnknownIdentifier $1)
202             | Some (CicTextualParser0.Uri uri) ->
203                term_of_uri uri (mk_exp_named_subst interp)
204             | Some CicTextualParser0.Implicit ->
205                (*CSC: not very clean; to maximize code reusage *)
206                snd (mk_implicit ()) ""
207    }
208  | CASE LPAREN expr COLON INDTYURI SEMICOLON expr RPAREN LCURLY branches RCURLY
209     { let dom1,mk_expr1 = $3 in
210       let dom2,mk_expr2 = $7 in
211       let dom3,mk_expr3 = $10 in
212        let dom = union dom1 (union dom2 dom3) in
213         dom,
214         function interp ->
215          MutCase
216           (fst $5,snd $5,(mk_expr2 interp),(mk_expr1 interp),(mk_expr3 interp))
217     }
218  | CASE LPAREN expr COLON ID SEMICOLON expr RPAREN LCURLY branches RCURLY
219     { let dom1,mk_expr1 = $3 in
220       let dom2,mk_expr2 = $7 in
221       let dom3,mk_expr3 = $10 in
222        let dom = union [$5] (union dom1 (union dom2 dom3)) in
223         dom,
224         function interp ->
225          let uri,typeno = indty_uri_of_id $5 interp in
226           MutCase
227            (uri,typeno,(mk_expr2 interp),(mk_expr1 interp),
228              (mk_expr3 interp))
229     }
230  | fixheader LCURLY exprseplist RCURLY
231     { let dom1,foo,ids_and_indexes,mk_types = $1 in
232       let dom2,mk_exprseplist = $3 in
233        let dom = union dom1 dom2 in
234         for i = 1 to List.length ids_and_indexes do
235          CicTextualParser0.binders := List.tl !CicTextualParser0.binders
236         done ;
237         dom,
238          function interp ->
239           let types = mk_types interp in
240           let fixfunsbodies = (mk_exprseplist interp) in
241            let idx =
242             let rec find idx =
243              function
244                 [] -> raise Not_found
245               | (name,_)::_  when name = foo -> idx
246               | _::tl -> find (idx+1) tl
247             in
248              find 0 ids_and_indexes
249            in
250             let fixfuns =
251              List.map2 (fun ((name,recindex),ty) bo -> (name,recindex,ty,bo))
252               (List.combine ids_and_indexes types) fixfunsbodies
253             in
254              Fix (idx,fixfuns)
255     }
256  | cofixheader LCURLY exprseplist RCURLY
257     { let dom1,foo,ids,mk_types = $1 in
258       let dom2,mk_exprseplist = $3 in
259        let dom = union dom1 dom2 in
260         dom,
261          function interp ->
262           let types = mk_types interp in
263           let fixfunsbodies = (mk_exprseplist interp) in
264            let idx =
265             let rec find idx =
266              function
267                 [] -> raise Not_found
268               | name::_  when name = foo -> idx
269               | _::tl -> find (idx+1) tl
270             in
271              find 0 ids
272            in
273             let fixfuns =
274              List.map2 (fun (name,ty) bo -> (name,ty,bo))
275               (List.combine ids types) fixfunsbodies
276             in
277              for i = 1 to List.length fixfuns do
278               CicTextualParser0.binders := List.tl !CicTextualParser0.binders
279              done ;
280              CoFix (idx,fixfuns)
281     }
282  | IMPLICIT
283     { mk_implicit () }
284  | SET  { [], function _ -> Sort Set }
285  | PROP { [], function _ -> Sort Prop }
286  | TYPE { [], function _ -> Sort Type }
287  | LPAREN expr CAST expr RPAREN
288     { let dom1,mk_expr1 = $2 in
289       let dom2,mk_expr2 = $4 in
290        let dom = union dom1 dom2 in
291         dom, function interp -> Cast ((mk_expr1 interp),(mk_expr2 interp))
292     }
293  | META LBRACKET substitutionlist RBRACKET
294     { let dom,mk_substitutionlist = $3 in
295        dom, function interp -> Meta ($1, mk_substitutionlist interp)
296     } 
297  | LPAREN expr expr exprlist RPAREN
298     { let dom1,mk_expr1 = $2 in
299       let dom2,mk_expr2 = $3 in
300       let dom3,mk_exprlist = $4 in
301        let dom = union dom1 (union dom2 dom3) in
302         dom,
303          function interp ->
304           Appl ([mk_expr1 interp ; mk_expr2 interp]@(mk_exprlist interp))
305     }
306 ;
307 exp_named_subst :
308     { None }
309  | LCURLY named_substs RCURLY
310     { Some $2 }
311 ;
312 named_substs :
313    VARURI LETIN expr2
314     { let dom,mk_expr = $3 in
315        dom, function interp -> [$1, mk_expr interp] }
316  | ID LETIN expr2
317     { let dom1,mk_expr = $3 in
318        let dom = union [$1] dom1 in
319         dom, function interp -> [var_uri_of_id $1 interp, mk_expr interp] }
320  | VARURI LETIN expr2 SEMICOLON named_substs
321     { let dom1,mk_expr = $3 in
322       let dom2,mk_named_substs = $5 in
323        let dom = union dom1 dom2 in
324         dom, function interp -> ($1, mk_expr interp)::(mk_named_substs interp)
325     }
326  | ID LETIN expr2 SEMICOLON named_substs
327     { let dom1,mk_expr = $3 in
328       let dom2,mk_named_substs = $5 in
329        let dom = union [$1] (union dom1 dom2) in
330         dom,
331          function interp ->
332           (var_uri_of_id $1 interp, mk_expr interp)::(mk_named_substs interp)
333     }
334 ;
335 expr :
336    pihead expr
337     { CicTextualParser0.binders := List.tl !CicTextualParser0.binders ;
338       let dom1,mk_expr1 = snd $1 in
339       let dom2,mk_expr2 = $2 in
340        let dom = union dom1 dom2 in
341         dom, function interp -> Prod (fst $1, mk_expr1 interp, mk_expr2 interp)
342     }
343  | lambdahead expr
344     { CicTextualParser0.binders := List.tl !CicTextualParser0.binders ;
345       let dom1,mk_expr1 = snd $1 in
346       let dom2,mk_expr2 = $2 in
347        let dom = union dom1 dom2 in
348         dom,function interp -> Lambda (fst $1, mk_expr1 interp, mk_expr2 interp)
349     }
350  | letinhead expr
351     { CicTextualParser0.binders := List.tl !CicTextualParser0.binders ;
352       let dom1,mk_expr1 = snd $1 in
353       let dom2,mk_expr2 = $2 in
354        let dom = union dom1 dom2 in
355         dom, function interp -> LetIn (fst $1, mk_expr1 interp, mk_expr2 interp)
356     }
357  | expr2
358     { $1 }
359 ;
360 fixheader:
361    FIX ID LCURLY fixfunsdecl RCURLY
362     { let dom,ids_and_indexes,mk_types = $4 in
363        let bs =
364         List.rev_map (function (name,_) -> Some (Name name)) ids_and_indexes
365        in
366         CicTextualParser0.binders := bs@(!CicTextualParser0.binders) ;
367         dom, $2, ids_and_indexes, mk_types
368     }
369 ;
370 fixfunsdecl:
371    ID LPAREN NUM RPAREN COLON expr
372     { let dom,mk_expr = $6 in
373        dom, [$1,$3], function interp -> [mk_expr interp]
374     }
375  | ID LPAREN NUM RPAREN COLON expr SEMICOLON fixfunsdecl
376     { let dom1,mk_expr = $6 in
377       let dom2,ids_and_indexes,mk_types = $8 in
378        let dom = union dom1 dom2 in
379         dom, ($1,$3)::ids_and_indexes,
380          function interp -> (mk_expr interp)::(mk_types interp)
381     }
382 ;
383 cofixheader:
384    COFIX ID LCURLY cofixfunsdecl RCURLY
385     { let dom,ids,mk_types = $4 in
386        let bs =
387         List.rev_map (function name -> Some (Name name)) ids
388        in
389         CicTextualParser0.binders := bs@(!CicTextualParser0.binders) ;
390         dom, $2, ids, mk_types
391     }
392 ;
393 cofixfunsdecl:
394    ID COLON expr
395     { let dom,mk_expr = $3 in
396        dom, [$1], function interp -> [mk_expr interp]
397     }
398  | ID COLON expr SEMICOLON cofixfunsdecl
399     { let dom1,mk_expr = $3 in
400       let dom2,ids,mk_types = $5 in
401        let dom = union dom1 dom2 in
402         dom, $1::ids,
403          function interp -> (mk_expr interp)::(mk_types interp)
404     }
405 ;
406 pihead:
407    PROD ID COLON expr DOT
408     { CicTextualParser0.binders := (Some (Name $2))::!CicTextualParser0.binders;
409       let dom,mk_expr = $4 in
410        Cic.Name $2, (dom, function interp -> mk_expr interp)
411     }
412  | expr2 ARROW
413    { CicTextualParser0.binders := (Some Anonymous)::!CicTextualParser0.binders ;
414      let dom,mk_expr = $1 in
415       Anonymous, (dom, function interp -> mk_expr interp)
416    }
417  | LPAREN expr RPAREN ARROW
418    { CicTextualParser0.binders := (Some Anonymous)::!CicTextualParser0.binders ;
419      let dom,mk_expr = $2 in
420       Anonymous, (dom, function interp -> mk_expr interp)
421    }
422  | PROD ID DOT
423     { CicTextualParser0.binders := (Some (Name $2))::!CicTextualParser0.binders;
424       let newmeta = new_meta () in
425        let new_canonical_context = [] in
426         let irl =
427          identity_relocation_list_for_metavariable new_canonical_context
428         in
429          CicTextualParser0.metasenv :=
430           [newmeta, new_canonical_context, Sort Type ;
431            newmeta+1, new_canonical_context, Meta (newmeta,irl)
432           ] @ !CicTextualParser0.metasenv ;
433          Cic.Name $2, ([], function _ -> Meta (newmeta+1,irl))
434     }
435 ;
436 lambdahead:
437    LAMBDA ID COLON expr DOT
438     { CicTextualParser0.binders := (Some (Name $2))::!CicTextualParser0.binders;
439       let dom,mk_expr = $4 in
440        Cic.Name $2, (dom, function interp -> mk_expr interp)
441     }
442  | LAMBDA ID DOT
443     { CicTextualParser0.binders := (Some (Name $2))::!CicTextualParser0.binders;
444       let newmeta = new_meta () in
445        let new_canonical_context = [] in
446         let irl =
447          identity_relocation_list_for_metavariable new_canonical_context
448         in
449          CicTextualParser0.metasenv :=
450           [newmeta, new_canonical_context, Sort Type ;
451            newmeta+1, new_canonical_context, Meta (newmeta,irl)
452           ] @ !CicTextualParser0.metasenv ;
453          Cic.Name $2, ([], function _ -> Meta (newmeta+1,irl))
454     }
455 ;
456 letinhead:
457   LAMBDA ID LETIN expr DOT
458    { CicTextualParser0.binders := (Some (Name $2))::!CicTextualParser0.binders ;
459      let dom,mk_expr = $4 in
460       Cic.Name $2, (dom, function interp -> mk_expr interp)
461    }
462 ;
463 branches:
464     { [], function _ -> [] }
465  | expr SEMICOLON branches
466     { let dom1,mk_expr = $1 in
467       let dom2,mk_branches = $3 in
468        let dom = union dom1 dom2 in
469         dom, function interp -> (mk_expr interp)::(mk_branches interp)
470     }
471  | expr
472     { let dom,mk_expr = $1 in
473        dom, function interp -> [mk_expr interp]
474     }
475 ;
476 exprlist:
477     
478     { [], function _ -> [] }
479  | expr exprlist
480     { let dom1,mk_expr = $1 in
481       let dom2,mk_exprlist = $2 in
482        let dom = union dom1 dom2 in
483         dom, function interp -> (mk_expr interp)::(mk_exprlist interp)
484     }
485 ;
486 exprseplist:
487    expr
488     { let dom,mk_expr = $1 in
489        dom, function interp -> [mk_expr interp]
490     }
491  | expr SEMICOLON exprseplist
492     { let dom1,mk_expr = $1 in
493       let dom2,mk_exprseplist = $3 in
494        let dom = union dom1 dom2 in
495         dom, function interp -> (mk_expr interp)::(mk_exprseplist interp)
496     }
497 ;
498 substitutionlist:
499     { [], function _ -> [] }
500  | expr SEMICOLON substitutionlist
501     { let dom1,mk_expr = $1 in
502       let dom2,mk_substitutionlist = $3 in
503        let dom = union dom1 dom2 in
504         dom,
505          function interp ->(Some (mk_expr interp))::(mk_substitutionlist interp)
506     }
507  | NONE SEMICOLON substitutionlist
508     { let dom,mk_exprsubstitutionlist = $3 in
509        dom, function interp -> None::(mk_exprsubstitutionlist interp)
510     }