]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/tex_cic_textual_parser/texCicTextualParser.mly
- the mathql interpreter is not helm-dependent any more
[helm.git] / helm / ocaml / tex_cic_textual_parser / texCicTextualParser.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,!TexCicTextualParser0.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 (CicTextualParser0.Id 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 (CicTextualParser0.Id 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      TexCicTextualParser0.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       ] @ !TexCicTextualParser0.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 LPAREN RPAREN PROD LAMBDA COLON DOT SET PROP TYPE CAST IMPLICIT NONE
159 %token LETIN FIX COFIX SEMICOLON LCURLY RCURLY CASE ARROW LBRACKET RBRACKET EOF
160 %token DOLLAR
161 %token PLUS MINUS TIMES EQ
162 %right ARROW
163 %right EQ
164 %right PLUS MINUS
165 %right TIMES
166 %start main
167 %type <CicTextualParser0.interpretation_domain_item list * (CicTextualParser0.interpretation -> Cic.term)> main
168 %%
169 main:
170  | EOF { raise CicTextualParser0.Eof } /* FG: was never raised */
171  | DOLLAR DOLLAR EOF {raise CicTextualParser0.Eof }
172  | DOLLAR DOLLAR DOLLAR DOLLAR EOF {raise CicTextualParser0.Eof }
173  | expr EOF { $1 }
174  | DOLLAR expr DOLLAR EOF { $2 }
175  | DOLLAR DOLLAR expr DOLLAR DOLLAR EOF { $3 }
176  | expr SEMICOLON { $1 } /*  FG: to read several terms in a row
177                           *  Do we need to clear some static variables? 
178                           */
179 ;
180 expr2:
181    NUM
182    { [], function interp ->
183       let rec cic_int_of_int =
184        function
185           0 ->
186            Cic.MutConstruct
187             (UriManager.uri_of_string "cic:/Coq/Init/Datatypes/nat.ind",
188              0,1,[])
189         | n ->
190           Cic.Appl
191            [ Cic.MutConstruct
192               (UriManager.uri_of_string "cic:/Coq/Init/Datatypes/nat.ind",
193                0,2,[]) ;
194              cic_int_of_int (n - 1)
195            ]
196       in
197        cic_int_of_int $1
198    }
199  | expr2 PLUS expr2
200    { let dom1,mk_expr1 = $1 in
201      let dom2,mk_expr2 = $3 in
202       let dom = union dom1 dom2 in
203        dom, function interp ->
204         Cic.Appl
205          [Cic.Const
206            (UriManager.uri_of_string "cic:/Coq/Init/Peano/plus.con",[]) ;
207           (mk_expr1 interp) ;
208           (mk_expr2 interp)
209          ]
210    }
211  | expr2 MINUS expr2
212    { let dom1,mk_expr1 = $1 in
213      let dom2,mk_expr2 = $3 in
214       let dom = union dom1 dom2 in
215        dom, function interp ->
216         Cic.Appl
217          [Cic.Const
218            (UriManager.uri_of_string "cic:/Coq/Arith/Minus/minus.con",[]) ;
219           (mk_expr1 interp) ;
220           (mk_expr2 interp)
221          ]
222    }
223  | expr2 TIMES expr2
224    { let dom1,mk_expr1 = $1 in
225      let dom2,mk_expr2 = $3 in
226       let dom = union dom1 dom2 in
227        dom, function interp ->
228         Cic.Appl
229          [Cic.Const
230            (UriManager.uri_of_string "cic:/Coq/Init/Peano/mult.con",[]) ;
231           (mk_expr1 interp) ;
232           (mk_expr2 interp)
233          ]
234    }
235  | expr2 EQ expr2
236    { let dom1,mk_expr1 = $1 in
237      let dom2,mk_expr2 = $3 in
238      let dom3,mk_expr3 = mk_implicit () in
239       let dom = union dom1 (union dom2 dom3) in
240        dom, function interp ->
241         Cic.Appl
242          [Cic.MutInd
243            (UriManager.uri_of_string "cic:/Coq/Init/Logic/eq.ind",0,[]) ;
244           (mk_expr3 interp) ;
245           (mk_expr1 interp) ;
246           (mk_expr2 interp)
247          ]
248    }
249  | CONURI exp_named_subst
250    { let dom,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
251       dom, function interp -> term_of_con_uri $1 (mk_exp_named_subst interp)
252    }
253  | VARURI exp_named_subst
254    { let dom,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
255       dom, function interp -> term_of_var_uri $1 (mk_exp_named_subst interp)
256    }
257  | INDTYURI exp_named_subst
258    { let dom,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
259       dom, function interp -> term_of_indty_uri $1 (mk_exp_named_subst interp)
260    }
261  | INDCONURI exp_named_subst
262    { let dom,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
263       dom, function interp -> term_of_indcon_uri $1 (mk_exp_named_subst interp)
264    }
265  | ID exp_named_subst
266    { try
267       let res =
268        Rel (get_index_in_list (Name $1) !TexCicTextualParser0.binders)
269       in
270        (match $2 with
271            None -> ([], function _ -> res)
272          | Some _ -> raise (ExplicitNamedSubstitutionAppliedToRel)
273        )
274      with
275       Not_found ->
276        let dom1,mk_exp_named_subst = deoptionize_exp_named_subst $2 in
277         let dom = union dom1 [CicTextualParser0.Id $1] in
278          dom,
279           function interp ->
280            match interp (CicTextualParser0.Id $1) with
281               None  -> raise (UnknownIdentifier $1)
282             | Some (CicTextualParser0.Uri uri) ->
283                term_of_uri uri (mk_exp_named_subst interp)
284             | Some CicTextualParser0.Implicit ->
285                (*CSC: not very clean; to maximize code reusage *)
286                snd (mk_implicit ()) ""
287             | Some (CicTextualParser0.Term mk_term) ->
288                (mk_term interp)
289    }
290  | CASE LPAREN expr COLON INDTYURI SEMICOLON expr RPAREN LCURLY branches RCURLY
291     { let dom1,mk_expr1 = $3 in
292       let dom2,mk_expr2 = $7 in
293       let dom3,mk_expr3 = $10 in
294        let dom = union dom1 (union dom2 dom3) in
295         dom,
296         function interp ->
297          MutCase
298           (fst $5,snd $5,(mk_expr2 interp),(mk_expr1 interp),(mk_expr3 interp))
299     }
300  | CASE LPAREN expr COLON ID SEMICOLON expr RPAREN LCURLY branches RCURLY
301     { let dom1,mk_expr1 = $3 in
302       let dom2,mk_expr2 = $7 in
303       let dom3,mk_expr3 = $10 in
304        let dom =
305         union [CicTextualParser0.Id $5] (union dom1 (union dom2 dom3))
306        in
307         dom,
308         function interp ->
309          let uri,typeno = indty_uri_of_id $5 interp in
310           MutCase
311            (uri,typeno,(mk_expr2 interp),(mk_expr1 interp),
312              (mk_expr3 interp))
313     }
314  | fixheader LCURLY exprseplist RCURLY
315     { let dom1,foo,ids_and_indexes,mk_types = $1 in
316       let dom2,mk_exprseplist = $3 in
317        let dom = union dom1 dom2 in
318         for i = 1 to List.length ids_and_indexes do
319          TexCicTextualParser0.binders := List.tl !TexCicTextualParser0.binders
320         done ;
321         dom,
322          function interp ->
323           let types = mk_types interp in
324           let fixfunsbodies = (mk_exprseplist interp) in
325            let idx =
326             let rec find idx =
327              function
328                 [] -> raise Not_found
329               | (name,_)::_  when name = foo -> idx
330               | _::tl -> find (idx+1) tl
331             in
332              find 0 ids_and_indexes
333            in
334             let fixfuns =
335              List.map2 (fun ((name,recindex),ty) bo -> (name,recindex,ty,bo))
336               (List.combine ids_and_indexes types) fixfunsbodies
337             in
338              Fix (idx,fixfuns)
339     }
340  | cofixheader LCURLY exprseplist RCURLY
341     { let dom1,foo,ids,mk_types = $1 in
342       let dom2,mk_exprseplist = $3 in
343        let dom = union dom1 dom2 in
344         dom,
345          function interp ->
346           let types = mk_types interp in
347           let fixfunsbodies = (mk_exprseplist interp) in
348            let idx =
349             let rec find idx =
350              function
351                 [] -> raise Not_found
352               | name::_  when name = foo -> idx
353               | _::tl -> find (idx+1) tl
354             in
355              find 0 ids
356            in
357             let fixfuns =
358              List.map2 (fun (name,ty) bo -> (name,ty,bo))
359               (List.combine ids types) fixfunsbodies
360             in
361              for i = 1 to List.length fixfuns do
362               TexCicTextualParser0.binders :=
363                List.tl !TexCicTextualParser0.binders
364              done ;
365              CoFix (idx,fixfuns)
366     }
367  | IMPLICIT
368     { mk_implicit () }
369  | SET  { [], function _ -> Sort Set }
370  | PROP { [], function _ -> Sort Prop }
371  | TYPE { [], function _ -> Sort Type }
372  | LPAREN expr CAST expr RPAREN
373     { let dom1,mk_expr1 = $2 in
374       let dom2,mk_expr2 = $4 in
375        let dom = union dom1 dom2 in
376         dom, function interp -> Cast ((mk_expr1 interp),(mk_expr2 interp))
377     }
378  | META LBRACKET substitutionlist RBRACKET
379     { let dom,mk_substitutionlist = $3 in
380        dom, function interp -> Meta ($1, mk_substitutionlist interp)
381     } 
382  | LPAREN expr exprlist RPAREN
383     { let length,dom2,mk_exprlist = $3 in
384        match length with
385           0 -> $2
386         | _ ->
387           let dom1,mk_expr1 = $2 in
388            let dom = union dom1 dom2 in
389             dom,
390              function interp ->
391               Appl ((mk_expr1 interp)::(mk_exprlist interp))
392     }
393 ;
394 exp_named_subst :
395     { None }
396  | LCURLY named_substs RCURLY
397     { Some $2 }
398 ;
399 named_substs :
400    VARURI LETIN expr2
401     { let dom,mk_expr = $3 in
402        dom, function interp -> [$1, mk_expr interp] }
403  | ID LETIN expr2
404     { let dom1,mk_expr = $3 in
405        let dom = union [CicTextualParser0.Id $1] dom1 in
406         dom, function interp -> [var_uri_of_id $1 interp, mk_expr interp] }
407  | VARURI LETIN expr2 SEMICOLON named_substs
408     { let dom1,mk_expr = $3 in
409       let dom2,mk_named_substs = $5 in
410        let dom = union dom1 dom2 in
411         dom, function interp -> ($1, mk_expr interp)::(mk_named_substs interp)
412     }
413  | ID LETIN expr2 SEMICOLON named_substs
414     { let dom1,mk_expr = $3 in
415       let dom2,mk_named_substs = $5 in
416        let dom = union [CicTextualParser0.Id $1] (union dom1 dom2) in
417         dom,
418          function interp ->
419           (var_uri_of_id $1 interp, mk_expr interp)::(mk_named_substs interp)
420     }
421 ;
422 expr :
423    pihead expr
424     { TexCicTextualParser0.binders := List.tl !TexCicTextualParser0.binders ;
425       let dom1,mk_expr1 = snd $1 in
426       let dom2,mk_expr2 = $2 in
427        let dom = union dom1 dom2 in
428         dom, function interp -> Prod (fst $1, mk_expr1 interp, mk_expr2 interp)
429     }
430  | lambdahead expr
431     { TexCicTextualParser0.binders := List.tl !TexCicTextualParser0.binders ;
432       let dom1,mk_expr1 = snd $1 in
433       let dom2,mk_expr2 = $2 in
434        let dom = union dom1 dom2 in
435         dom,function interp -> Lambda (fst $1, mk_expr1 interp, mk_expr2 interp)
436     }
437  | letinhead expr
438     { TexCicTextualParser0.binders := List.tl !TexCicTextualParser0.binders ;
439       let dom1,mk_expr1 = snd $1 in
440       let dom2,mk_expr2 = $2 in
441        let dom = union dom1 dom2 in
442         dom, function interp -> LetIn (fst $1, mk_expr1 interp, mk_expr2 interp)
443     }
444  | expr2
445     { $1 }
446 ;
447 fixheader:
448    FIX ID LCURLY fixfunsdecl RCURLY
449     { let dom,ids_and_indexes,mk_types = $4 in
450        let bs =
451         List.rev_map (function (name,_) -> Some (Name name)) ids_and_indexes
452        in
453         TexCicTextualParser0.binders := bs@(!TexCicTextualParser0.binders) ;
454         dom, $2, ids_and_indexes, mk_types
455     }
456 ;
457 fixfunsdecl:
458    ID LPAREN NUM RPAREN COLON expr
459     { let dom,mk_expr = $6 in
460        dom, [$1,$3], function interp -> [mk_expr interp]
461     }
462  | ID LPAREN NUM RPAREN COLON expr SEMICOLON fixfunsdecl
463     { let dom1,mk_expr = $6 in
464       let dom2,ids_and_indexes,mk_types = $8 in
465        let dom = union dom1 dom2 in
466         dom, ($1,$3)::ids_and_indexes,
467          function interp -> (mk_expr interp)::(mk_types interp)
468     }
469 ;
470 cofixheader:
471    COFIX ID LCURLY cofixfunsdecl RCURLY
472     { let dom,ids,mk_types = $4 in
473        let bs =
474         List.rev_map (function name -> Some (Name name)) ids
475        in
476         TexCicTextualParser0.binders := bs@(!TexCicTextualParser0.binders) ;
477         dom, $2, ids, mk_types
478     }
479 ;
480 cofixfunsdecl:
481    ID COLON expr
482     { let dom,mk_expr = $3 in
483        dom, [$1], function interp -> [mk_expr interp]
484     }
485  | ID COLON expr SEMICOLON cofixfunsdecl
486     { let dom1,mk_expr = $3 in
487       let dom2,ids,mk_types = $5 in
488        let dom = union dom1 dom2 in
489         dom, $1::ids,
490          function interp -> (mk_expr interp)::(mk_types interp)
491     }
492 ;
493 pihead:
494    PROD ID COLON expr DOT
495     { TexCicTextualParser0.binders :=
496        (Some (Name $2))::!TexCicTextualParser0.binders;
497       let dom,mk_expr = $4 in
498        Cic.Name $2, (dom, function interp -> mk_expr interp)
499     }
500  | expr2 ARROW
501    { TexCicTextualParser0.binders :=
502       (Some Anonymous)::!TexCicTextualParser0.binders ;
503      let dom,mk_expr = $1 in
504       Anonymous, (dom, function interp -> mk_expr interp)
505    }
506  | PROD ID DOT
507     { TexCicTextualParser0.binders :=
508        (Some (Name $2))::!TexCicTextualParser0.binders;
509       let newmeta = new_meta () in
510        let new_canonical_context = [] in
511         let irl =
512          identity_relocation_list_for_metavariable new_canonical_context
513         in
514          TexCicTextualParser0.metasenv :=
515           [newmeta, new_canonical_context, Sort Type ;
516            newmeta+1, new_canonical_context, Meta (newmeta,irl)
517           ] @ !TexCicTextualParser0.metasenv ;
518          Cic.Name $2, ([], function _ -> Meta (newmeta+1,irl))
519     }
520 ;
521 lambdahead:
522    LAMBDA ID COLON expr DOT
523     { TexCicTextualParser0.binders :=
524        (Some (Name $2))::!TexCicTextualParser0.binders;
525       let dom,mk_expr = $4 in
526        Cic.Name $2, (dom, function interp -> mk_expr interp)
527     }
528  | LAMBDA ID DOT
529     { TexCicTextualParser0.binders :=
530        (Some (Name $2))::!TexCicTextualParser0.binders;
531       let newmeta = new_meta () in
532        let new_canonical_context = [] in
533         let irl =
534          identity_relocation_list_for_metavariable new_canonical_context
535         in
536          TexCicTextualParser0.metasenv :=
537           [newmeta, new_canonical_context, Sort Type ;
538            newmeta+1, new_canonical_context, Meta (newmeta,irl)
539           ] @ !TexCicTextualParser0.metasenv ;
540          Cic.Name $2, ([], function _ -> Meta (newmeta+1,irl))
541     }
542 ;
543 letinhead:
544   LAMBDA ID LETIN expr DOT
545    { TexCicTextualParser0.binders :=
546       (Some (Name $2))::!TexCicTextualParser0.binders ;
547      let dom,mk_expr = $4 in
548       Cic.Name $2, (dom, function interp -> mk_expr interp)
549    }
550 ;
551 branches:
552     { [], function _ -> [] }
553  | expr SEMICOLON branches
554     { let dom1,mk_expr = $1 in
555       let dom2,mk_branches = $3 in
556        let dom = union dom1 dom2 in
557         dom, function interp -> (mk_expr interp)::(mk_branches interp)
558     }
559  | expr
560     { let dom,mk_expr = $1 in
561        dom, function interp -> [mk_expr interp]
562     }
563 ;
564 exprlist:
565     
566     { 0, [], function _ -> [] }
567  | expr exprlist
568     { let dom1,mk_expr = $1 in
569       let length,dom2,mk_exprlist = $2 in
570        let dom = union dom1 dom2 in
571         length+1, dom, function interp -> (mk_expr interp)::(mk_exprlist interp)
572     }
573 ;
574 exprseplist:
575    expr
576     { let dom,mk_expr = $1 in
577        dom, function interp -> [mk_expr interp]
578     }
579  | expr SEMICOLON exprseplist
580     { let dom1,mk_expr = $1 in
581       let dom2,mk_exprseplist = $3 in
582        let dom = union dom1 dom2 in
583         dom, function interp -> (mk_expr interp)::(mk_exprseplist interp)
584     }
585 ;
586 substitutionlist:
587     { [], function _ -> [] }
588  | expr SEMICOLON substitutionlist
589     { let dom1,mk_expr = $1 in
590       let dom2,mk_substitutionlist = $3 in
591        let dom = union dom1 dom2 in
592         dom,
593          function interp ->(Some (mk_expr interp))::(mk_substitutionlist interp)
594     }
595  | NONE SEMICOLON substitutionlist
596     { let dom,mk_exprsubstitutionlist = $3 in
597        dom, function interp -> None::(mk_exprsubstitutionlist interp)
598     }