src/Pure/Syntax/parser.ML
changeset 15979 c81578ac2d31
parent 15752 8cdc6249044b
child 16668 fdb4992cf1d2
equal deleted inserted replaced
15978:f044579b147c 15979:c81578ac2d31
     1 (*  Title:      Pure/Syntax/parser.ML
     1 (*  Title:      Pure/Syntax/parser.ML
     2     ID:         $Id$
     2     ID:         $Id$
     3     Author:     Carsten Clasohm, Sonia Mahjoub, and Markus Wenzel, TU Muenchen
     3     Author:     Carsten Clasohm, Sonia Mahjoub, and Markus Wenzel, TU Muenchen
     4 
     4 
     5 Isabelle's main parser (used for terms and types).
     5 General context-free parser for the inner syntax of terms, types, etc.
     6 *)
     6 *)
     7 
     7 
     8 signature PARSER =
     8 signature PARSER =
     9 sig
     9 sig
    10   type gram
    10   type gram
    83         added_starts is used later to associate existing
    83         added_starts is used later to associate existing
    84         productions with new starting tokens*)
    84         productions with new starting tokens*)
    85       val (added_starts, lambdas') =
    85       val (added_starts, lambdas') =
    86         if is_none new_chain then ([], lambdas) else
    86         if is_none new_chain then ([], lambdas) else
    87         let (*lookahead of chain's source*)
    87         let (*lookahead of chain's source*)
    88             val ((from_nts, from_tks), _) = Array.sub (prods, valOf new_chain);
    88             val ((from_nts, from_tks), _) = Array.sub (prods, the new_chain);
    89 
    89 
    90             (*copy from's lookahead to chain's destinations*)
    90             (*copy from's lookahead to chain's destinations*)
    91             fun copy_lookahead [] added = added
    91             fun copy_lookahead [] added = added
    92               | copy_lookahead (to :: tos) added =
    92               | copy_lookahead (to :: tos) added =
    93                 let
    93                 let
   147                     in
   147                     in
   148                       if l mem nts then       (*update production's lookahead*)
   148                       if l mem nts then       (*update production's lookahead*)
   149                       let
   149                       let
   150                         val new_lambda = is_none tk andalso nts subset lambdas;
   150                         val new_lambda = is_none tk andalso nts subset lambdas;
   151 
   151 
   152                         val new_tks = (if isSome tk then [valOf tk] else []) @
   152                         val new_tks = (if is_some tk then [the tk] else []) @
   153                           Library.foldl token_union ([], map starts_for_nt nts) \\
   153                           Library.foldl token_union ([], map starts_for_nt nts) \\
   154                           l_starts;
   154                           l_starts;
   155 
   155 
   156                         val added_tks' = token_union (new_tks, added_tks);
   156                         val added_tks' = token_union (new_tks, added_tks);
   157 
   157 
   226               end;
   226               end;
   227         in propagate_lambda (lambdas' \\ lambdas) added_starts lambdas' end;
   227         in propagate_lambda (lambdas' \\ lambdas) added_starts lambdas' end;
   228 
   228 
   229       (*insert production into grammar*)
   229       (*insert production into grammar*)
   230       val (added_starts', prod_count') =
   230       val (added_starts', prod_count') =
   231         if isSome chain_from then (added_starts', prod_count)  (*don't store chain production*)
   231         if is_some chain_from then (added_starts', prod_count)  (*don't store chain production*)
   232         else let
   232         else let
   233           (*lookahead tokens of new production and on which
   233           (*lookahead tokens of new production and on which
   234             NTs lookahead depends*)
   234             NTs lookahead depends*)
   235           val (start_tk, start_nts) = lookahead_dependency lambdas' rhs [];
   235           val (start_tk, start_nts) = lookahead_dependency lambdas' rhs [];
   236 
   236 
   237           val start_tks = Library.foldl token_union
   237           val start_tks = Library.foldl token_union
   238                           (if isSome start_tk then [valOf start_tk] else [],
   238                           (if is_some start_tk then [the start_tk] else [],
   239                            map starts_for_nt start_nts);
   239                            map starts_for_nt start_nts);
   240 
   240 
   241           val opt_starts = (if new_lambda then [NONE]
   241           val opt_starts = (if new_lambda then [NONE]
   242                             else if null start_tks then [SOME UnknownStart]
   242                             else if null start_tks then [SOME UnknownStart]
   243                             else []) @ (map SOME start_tks);
   243                             else []) @ (map SOME start_tks);
   259 
   259 
   260                 val new_tks = gen_rems matching_tokens (start_tks, old_tks);
   260                 val new_tks = gen_rems matching_tokens (start_tks, old_tks);
   261 
   261 
   262                 (*store new production*)
   262                 (*store new production*)
   263                 fun store [] prods is_new =
   263                 fun store [] prods is_new =
   264                       (prods, if isSome prod_count andalso is_new then
   264                       (prods, if is_some prod_count andalso is_new then
   265                                 Option.map (fn x => x+1) prod_count
   265                                 Option.map (fn x => x+1) prod_count
   266                               else prod_count, is_new)
   266                               else prod_count, is_new)
   267                   | store (tk :: tks) prods is_new =
   267                   | store (tk :: tks) prods is_new =
   268                     let val tk_prods = assocs prods tk;
   268                     let val tk_prods = assocs prods tk;
   269 
   269 
   270                         (*if prod_count = NONE then we can assume that
   270                         (*if prod_count = NONE then we can assume that
   271                           grammar does not contain new production already*)
   271                           grammar does not contain new production already*)
   272                         val (tk_prods', is_new') =
   272                         val (tk_prods', is_new') =
   273                           if isSome prod_count then
   273                           if is_some prod_count then
   274                             if new_prod mem tk_prods then (tk_prods, false)
   274                             if new_prod mem tk_prods then (tk_prods, false)
   275                             else (new_prod :: tk_prods, true)
   275                             else (new_prod :: tk_prods, true)
   276                           else (new_prod :: tk_prods, true);
   276                           else (new_prod :: tk_prods, true);
   277 
   277 
   278                         val prods' = if is_new' then
   278                         val prods' = if is_new' then
   322                       val update = changed_nt mem depends;
   322                       val update = changed_nt mem depends;
   323 
   323 
   324                       (*test if production could already be associated with
   324                       (*test if production could already be associated with
   325                         a member of new_tks*)
   325                         a member of new_tks*)
   326                       val lambda = length depends > 1 orelse
   326                       val lambda = length depends > 1 orelse
   327                                    not (null depends) andalso isSome tk
   327                                    not (null depends) andalso is_some tk
   328                                    andalso valOf tk mem new_tks;
   328                                    andalso the tk mem new_tks;
   329 
   329 
   330                       (*associate production with new starting tokens*)
   330                       (*associate production with new starting tokens*)
   331                       fun copy [] nt_prods = nt_prods
   331                       fun copy [] nt_prods = nt_prods
   332                         | copy (tk :: tks) nt_prods =
   332                         | copy (tk :: tks) nt_prods =
   333                           let
   333                           let
   393     val taglist = Symtab.dest tags;
   393     val taglist = Symtab.dest tags;
   394 
   394 
   395     fun pretty_symb (Terminal (Token s)) = Pretty.quote (Pretty.str s)
   395     fun pretty_symb (Terminal (Token s)) = Pretty.quote (Pretty.str s)
   396       | pretty_symb (Terminal tok) = Pretty.str (str_of_token tok)
   396       | pretty_symb (Terminal tok) = Pretty.str (str_of_token tok)
   397       | pretty_symb (Nonterminal (tag, p)) =
   397       | pretty_symb (Nonterminal (tag, p)) =
   398         let val name = fst (valOf (find_first (fn (n, t) => t = tag) taglist));
   398         let val name = fst (the (find_first (fn (n, t) => t = tag) taglist));
   399         in Pretty.str (name ^ "[" ^ string_of_int p ^ "]") end;
   399         in Pretty.str (name ^ "[" ^ string_of_int p ^ "]") end;
   400 
   400 
   401     fun pretty_const "" = []
   401     fun pretty_const "" = []
   402       | pretty_const c = [Pretty.str ("=> " ^ Library.quote c)];
   402       | pretty_const c = [Pretty.str ("=> " ^ Library.quote c)];
   403 
   403 
   533 
   533 
   534           fun store_tag nt_count tags ~1 = (nt_count, tags)
   534           fun store_tag nt_count tags ~1 = (nt_count, tags)
   535             | store_tag nt_count tags tag =
   535             | store_tag nt_count tags tag =
   536               let val (nt_count', tags', tag') =
   536               let val (nt_count', tags', tag') =
   537                    get_tag nt_count tags
   537                    get_tag nt_count tags
   538                      (fst (valOf (find_first (fn (n, t) => t = tag) tag_list)));
   538                      (fst (the (find_first (fn (n, t) => t = tag) tag_list)));
   539               in Array.update (table, tag, tag');
   539               in Array.update (table, tag, tag');
   540                  store_tag nt_count' tags' (tag-1)
   540                  store_tag nt_count' tags' (tag-1)
   541               end;
   541               end;
   542       in (store_tag nt_count1 tags1 (nt_count2-1), table) end;
   542       in (store_tag nt_count1 tags1 (nt_count2-1), table) end;
   543 
   543 
   693 val branching_level = ref 600;                   (*trigger value for warnings*)
   693 val branching_level = ref 600;                   (*trigger value for warnings*)
   694 
   694 
   695 (*get all productions of a NT and NTs chained to it which can
   695 (*get all productions of a NT and NTs chained to it which can
   696   be started by specified token*)
   696   be started by specified token*)
   697 fun prods_for prods chains include_none tk nts =
   697 fun prods_for prods chains include_none tk nts =
   698 let (*similar to token_assoc but does not automatically include 'NONE' key*)
   698 let
   699     fun token_assoc2 (list, key) =
   699     fun token_assoc (list, key) =
   700       let fun assoc [] result = result
   700       let fun assoc [] result = result
   701             | assoc ((keyi, pi) :: pairs) result =
   701             | assoc ((keyi, pi) :: pairs) result =
   702                 if isSome keyi andalso matching_tokens (valOf keyi, key)
   702                 if is_some keyi andalso matching_tokens (the keyi, key)
   703                    orelse include_none andalso is_none keyi then
   703                    orelse include_none andalso is_none keyi then
   704                   assoc pairs (pi @ result)
   704                   assoc pairs (pi @ result)
   705                 else assoc pairs result;
   705                 else assoc pairs result;
   706       in assoc list [] end;
   706       in assoc list [] end;
   707 
   707 
   708     fun get_prods [] result = result
   708     fun get_prods [] result = result
   709       | get_prods (nt :: nts) result =
   709       | get_prods (nt :: nts) result =
   710         let val nt_prods = snd (Array.sub (prods, nt));
   710         let val nt_prods = snd (Array.sub (prods, nt));
   711         in get_prods nts ((token_assoc2 (nt_prods, tk)) @ result) end;
   711         in get_prods nts ((token_assoc (nt_prods, tk)) @ result) end;
   712 in get_prods (connected_with chains nts nts) [] end;
   712 in get_prods (connected_with chains nts nts) [] end;
   713 
   713 
   714 
   714 
   715 fun PROCESSS prods chains Estate i c states =
   715 fun PROCESSS prods chains Estate i c states =
   716 let
   716 let