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 |