|
|
1.1 root 1: (* ML-Yacc parser generator version 1.0
2: Copyright (c) 1989 by Andrew W. Appel, David R. Tarditi
3:
4: This software comes with ABSOLUTELY NO WARRANTY.
5: This software is subject only to the PRINCETON STANDARD ML SOFTWARE LIBRARY
6: COPYRIGHT NOTICE, LICENSE AND DISCLAIMER, (in the file "COPYRIGHT",
7: distributed with this software). You may copy and distribute this software;
8: see the COPYRIGHT NOTICE for details and restrictions.
9: *)
10: signature BASESET =
11: sig
12: type elem
13: type base_set
14: exception Select_arb
15: val empty: base_set
16: and insert: elem -> base_set -> base_set
17: and exists: elem -> base_set -> bool
18: and find: elem -> base_set -> elem option
19: and setfold: ((elem * 'b) -> 'b) -> base_set -> 'b -> 'b
20: and revsetfold: ((elem * 'b) -> 'b) -> base_set -> 'b -> 'b
21: and elem_gt: (elem * elem -> bool)
22: and elem_eq: (elem * elem -> bool)
23: and select_arb: base_set -> elem
24: and set_eq: (base_set * base_set) -> bool
25: and set_gt: (base_set * base_set) -> bool
26: and app : (elem -> 'a) -> base_set -> unit
27: end;
28:
29: signature FULLSET =
30: sig
31: type set
32: type elem
33: exception Select_arb
34: val card: set -> int
35: and app: (elem -> 'b) -> set -> unit
36: and set_eq: (set * set) -> bool
37: and set_gt: (set * set) -> bool
38: and find : elem -> set -> elem option
39: and exists: elem -> set -> bool
40: and contained: elem -> (set -> bool)
41: and difference: set * set -> set
42: and elem_eq: (elem * elem -> bool)
43: and elem_gt : (elem * elem -> bool)
44: and empty: set
45: and insert: elem -> set -> set
46: and is_empty: set -> bool
47: and make_list: set -> elem list
48: and make_set: (elem list -> set)
49: and remove: (elem * set) -> set
50: and same_set: set * set -> bool
51: and partition: (elem -> bool) -> (set -> set * set)
52: and revsetfold: ((elem * 'b) -> 'b) -> set -> 'b -> 'b
53: and setfold: ((elem * 'b) -> 'b) -> set -> 'b -> 'b
54: and select_arb: set -> elem
55: and singleton: (elem -> set)
56: and union: set * set -> set
57: and closure: set * (elem -> set) -> set
58: end;
59:
60: signature GRAPH =
61: sig
62:
63: type node
64: type edge
65: type graph
66:
67: val null_graph: graph
68: val nodes_of: graph -> node list
69: val num_nodes: graph -> int
70: val join: graph * node * edge * node -> graph
71:
72: (* drt(9/12/88) - new functions added because join is inefficient,
73: if one or both of the nodes already exist *)
74:
75: val add_edge : graph * node * edge * node -> graph
76: val add_node : graph * node -> graph
77:
78: (* set of graph edges: records of {From:node, Edge:edge, To:node} *)
79:
80:
81: structure EdgeSet : FULLSET
82:
83: val edges: graph * node -> EdgeSet.set (* all edges from a node *)
84: val all_edges : graph -> EdgeSet.set
85:
86: val find_node : graph * node -> node option
87:
88: end;
89:
90: signature BUSY =
91: sig
92: val dot: unit -> unit
93: val star: unit -> unit
94: val print: string -> unit
95: val println: string -> unit
96:
97: val withSpace: ('a -> unit) -> ('a -> unit)
98: val withNewline: ('a -> unit) -> ('a -> unit)
99:
100: val withDot: ('a -> 'b) -> 'a -> 'b
101:
102: val sendto_list : unit -> unit
103: val sendto_file : outstream -> unit
104:
105: val get_list : unit -> string list
106: end;
107:
108: signature MEMO =
109: sig
110: type Arg
111:
112: val memo_fn: ((Arg * Arg) -> bool) -> ((Arg -> '2a) -> (Arg -> '2a))
113:
114: exception Enum_memo_fn
115:
116: val enum_memo_fn: ((Arg -> int) * int) -> ((Arg -> '2a) -> (Arg -> '2a))
117:
118: exception Catalog
119:
120: val catalog: {tag: Arg -> 'tag,
121: ordOfTag: 'tag -> int,
122: items: Arg list
123: } -> ('tag -> Arg list)
124: end;
125: signature V2_LR_GRAMMAR =
126: sig
127: datatype Terminal = T of int
128: and Nonterminal = NT of int
129:
130: datatype Symbol = TERM of Terminal
131: | NONTERM of Nonterminal
132:
133: datatype Attribute = ATTRIB of {lhs: Nonterminal,
134: rhsLength: int,
135: num : int
136: }
137:
138: datatype Rule = RULE of {lhs: Nonterminal,
139: rhs: Symbol list,
140: attribute: Attribute,
141: precedence: int option
142: }
143:
144: val termHash: Terminal -> int
145: val nontermHash: Nonterminal -> int
146:
147: val eqTerminal: Terminal * Terminal -> bool
148: val eqNonterminal: Nonterminal * Nonterminal -> bool
149:
150: val gtTerminal: Terminal * Terminal -> bool
151: val gtNonterminal: Nonterminal * Nonterminal -> bool
152: end;
153: signature V2_LSET =
154: sig
155: structure G : V2_LR_GRAMMAR
156: type Lookahead
157: val emptylookahead : Lookahead
158:
159: (* Sets the bool ref to true if lookahead arg 1
160: set - lookahead arg 2 set <> null, i.e. if merging the 2 lookahead
161: sets adds something to lookahead arg 1 set
162: *)
163:
164: val mergelookahead : ((Lookahead * Lookahead) * bool ref) -> Lookahead
165:
166: (* returns true if any terminal in the terminal list is not in
167: was not already in the lookahead set
168: *)
169:
170: val addterms: Lookahead * G.Terminal list -> Lookahead
171: val makelookaheadlist : Lookahead -> G.Terminal list
172: end
173:
174: signature V2_LR_UTILS =
175: sig
176: structure G: V2_LR_GRAMMAR
177: structure CoreSet : FULLSET
178: structure Lset : V2_LSET
179:
180: datatype Core = CORE of { I : {coreLHS: G.Nonterminal,
181: corePrecedence: int option,
182: coreAttribute: G.Attribute},
183: coreRHSbefore: G.Symbol list,
184: coreRHSafter: G.Symbol list,
185: prop: bool ref,
186: lookaheads : Lset. Lookahead ref
187: }
188:
189: sharing type CoreSet.elem = Core
190:
191: val eqSymbol: G.Symbol * G.Symbol -> bool
192: val gtSymbol: G.Symbol * G.Symbol -> bool
193:
194: val eqCore: Core * Core -> bool
195: val gtCore: Core * Core -> bool
196:
197: val mkshowSymbol: {showTerminalClass : G.Terminal -> string,
198: showNonterminal : G.Nonterminal -> string } ->
199: G.Symbol -> string
200:
201: val printCore: {showSymbol : G.Symbol -> string,
202: showNonterminal : G.Nonterminal -> string,
203: showTerminalClass : G.Terminal -> string} -> Core -> unit
204: val printCoreSet: {printCore : Core -> unit} -> CoreSet.set -> unit
205:
206: val mkselectCores: {rules : G.Rule list,
207: numNonterminals : int }
208: -> G.Nonterminal -> CoreSet.set
209: val mkcoreClosure: {rules : G.Rule list,
210: numNonterminals : int,
211: selectCores : G.Nonterminal -> CoreSet.set
212: } -> CoreSet.set -> CoreSet.set
213:
214: val immediateSymbols: CoreSet.set -> G.Symbol list
215: val copyCoreSet : CoreSet.set -> CoreSet.set
216:
217: type true
218: val prop_f_to_c_a :
219: {first_string : G.Symbol list -> G.Terminal list,
220: selectCores : G.Nonterminal -> CoreSet.set} ->
221: (CoreSet.set -> unit)
222: val propagate_l_to_c_a :
223: {selectCores : G.Nonterminal -> CoreSet.set } ->
224: (CoreSet.set * bool ref) -> unit
225: val propagate_l_to_g_i : (Core -> Core) ->
226: (((CoreSet.set * G.Symbol * CoreSet.set) *
227: bool ref) -> unit)
228: val set_prop : (G.Symbol list -> bool) -> (CoreSet.set -> unit)
229: val hardwire_eof : (CoreSet.set * G.Terminal * G.Nonterminal) -> unit
230: end;
231:
232: signature V2_LR_GRAPH =
233: sig
234: structure G: V2_LR_GRAMMAR
235: structure Lr_Graph : GRAPH
236: val mkGraph : {rules : G.Rule list, verbose : bool,
237: eof : G.Terminal, start : G.Nonterminal,
238: termPrecedence : G.Terminal -> int option,
239: showTerminalClass : G.Terminal -> string,
240: showTerminalValue : G.Terminal -> string,
241: showNonterminal : G.Nonterminal -> string,
242: showAttribute : G.Attribute -> string,
243: numTerminals : int,
244: numNonterminals : int
245: } -> Lr_Graph.graph
246: end;
247:
248: signature V2_LOOKAHEAD =
249: sig
250: structure G: V2_LR_GRAMMAR
251: structure Utils : V2_LR_UTILS
252: val mkfunctions : {numNonterminals:int,
253: selectCores : G.Nonterminal -> Utils.CoreSet.set,
254: showNonterminal : G.Nonterminal -> string,
255: showTerminalClass : G.Terminal -> string
256: } -> {nullable_string : G.Symbol list -> bool,
257: first_string : G.Symbol list -> G.Terminal list}
258: end;
259: signature V2_LR_TABLE =
260: sig
261: structure G: V2_LR_GRAMMAR
262: val mktable :
263: outstream ->
264: {rules : G.Rule list, verbose : bool,
265: eof : G.Terminal, start : G.Nonterminal,
266: termPrecedence : G.Terminal -> int option,
267: showTerminalClass : G.Terminal -> string,
268: showTerminalValue : G.Terminal -> string,
269: showNonterminal : G.Nonterminal -> string,
270: showAttribute : G.Attribute -> string,
271: numTerminals : int,
272: numNonterminals : int
273: } -> unit
274: end;
275: structure Busy: BUSY =
276: struct
277: val len = ref 0
278: val file = ref std_out (* file to send output *)
279: val list = ref (nil : string list) (* or list to save output on *)
280: val to_file = ref true (* true = to file, false = to_list *)
281:
282: val sendto_list = fn () => (to_file := false; list := nil)
283: val sendto_file = fn f => (file := f; to_file := true)
284: val get_list = fn () => (!list)
285:
286: val dots = ref false
287:
288: val P = fn x => if (!to_file) then output (!file) x
289: else list := x :: (!list)
290:
291: fun sym s = (if !len = 75 then (P "\n"; len := 0) else ();
292: flush_out (!file);
293: P s;
294: len := !len + 1;
295: dots := true
296: )
297:
298: fun dot() = sym "."
299: fun star() = sym "*"
300:
301: fun print s = (if !dots then (P "\n"; len := 0) else ();
302: dots := false;
303: P s;
304: len := !len + size s
305: );
306:
307: fun println s = (print s; P "\n"; len := 0)
308:
309: fun withSpace pr = fn x => (pr x; print " ")
310: fun withNewline pr = fn x => (pr x; println " ")
311:
312: fun withDot f a = f a before dot()
313: end;
314:
315: functor Memo(type Arg): MEMO =
316: struct
317: type Arg = Arg
318: type 'a relation = 'a * 'a -> bool
319:
320: fun memo_fn (Eq: Arg relation) (F: Arg -> '2a) =
321: let val MemoSet = (ref nil): (Arg * '2a) list ref
322: fun MemoCall(Arg, (X, Y) :: XYRest, Eq) =
323: if Eq(Arg, X) then Y else MemoCall(Arg, XYRest, Eq) |
324: MemoCall(Arg, nil, _) =
325: let val Y = F(Arg)
326: in (MemoSet := (Arg, Y) :: !MemoSet; Y)
327: end
328:
329: in fn X => MemoCall(X, !MemoSet, Eq)
330: end
331:
332: exception Enum_memo_fn
333: fun enum_memo_fn (Enum: Arg -> int, Max: int) (F: Arg -> '2a) =
334: let val MemoArray = array(Max, NONE): '2a option array
335: in fn x =>
336: let val n = Enum(x)
337: in case MemoArray sub n of
338: NONE => let val y = F(x)
339: in update(MemoArray, n, SOME(y)); y
340: end |
341: SOME(y) => y
342: end
343: handle Subscript => raise Enum_memo_fn
344: end
345:
346: (* catalog: given a function Tag for getting the selector tag
347: from any object, bundle the objects to give an efficient selector
348: function *)
349:
350: exception Catalog
351: fun catalog{tag, ordOfTag, items}: ('tag -> Arg list) =
352: let val OrdOfThing = ordOfTag o tag
353:
354: fun MaxOrdOfTag(Item :: IRest, Result): int =
355: (Busy.dot();
356: let val ThisOrd = OrdOfThing(Item)
357: in if ThisOrd > Result then MaxOrdOfTag(IRest, ThisOrd)
358: else MaxOrdOfTag(IRest, Result)
359: end
360: ) |
361: MaxOrdOfTag(nil, Result) = Result
362:
363: val MaxOrdOfTags =
364: (Busy.print "MaxOrdOfTags"; MaxOrdOfTag(items, 0))
365:
366: val TheCatalog =
367: array(MaxOrdOfTags + 1, NONE): Arg list option array
368:
369: fun InsertItem(Item) =
370: let val ord = OrdOfThing(Item)
371: in (case TheCatalog sub ord of
372: SOME(L) =>
373: update(TheCatalog, ord, SOME(Item :: L)) |
374:
375: NONE =>
376: update(TheCatalog, ord, SOME [Item])
377: ) before Busy.dot()
378: end
379:
380: val _ = (Busy.print "catalog"; map InsertItem items)
381:
382: in fn Tag => (case TheCatalog sub ordOfTag(Tag) of
383: SOME(L) => L |
384: NONE => raise Catalog
385: ) handle Subscript => raise Catalog
386: end
387: end;
388:
389: functor BaseSet(B : sig type elem
390: val gt : elem * elem -> bool
391: val eq : elem * elem -> bool
392: end ) : BASESET =
393:
394: struct
395:
396: type elem = B.elem
397: val elem_gt = B.gt
398: val elem_eq = B.eq
399:
400: datatype Color = RED | BLACK
401:
402: datatype base_set = EMPTY | TREE of (B.elem * Color * base_set * base_set)
403: exception Select_arb
404: val empty = EMPTY
405:
406: fun insert key t =
407: let fun f EMPTY = TREE(key,RED,EMPTY,EMPTY)
408: | f (TREE(k,BLACK,l,r)) =
409: if elem_gt (key,k)
410: then case f r
411: of r as TREE(rk,RED, rl as TREE(rlk,RED,rll,rlr),rr) =>
412: (case l
413: of TREE(lk,RED,ll,lr) =>
414: TREE(k,RED,TREE(lk,BLACK,ll,lr),
415: TREE(rk,BLACK,rl,rr))
416: | _ => TREE(rlk,BLACK,TREE(k,RED,l,rll),
417: TREE(rk,RED,rlr,rr)))
418: | r as TREE(rk,RED,rl, rr as TREE(rrk,RED,rrl,rrr)) =>
419: (case l
420: of TREE(lk,RED,ll,lr) =>
421: TREE(k,RED,TREE(lk,BLACK,ll,lr),
422: TREE(rk,BLACK,rl,rr))
423: | _ => TREE(rk,BLACK,TREE(k,RED,l,rl),rr))
424: | r => TREE(k,BLACK,l,r)
425: else if elem_gt(k,key)
426: then case f l
427: of l as TREE(lk,RED,ll, lr as TREE(lrk,RED,lrl,lrr)) =>
428: (case r
429: of TREE(rk,RED,rl,rr) =>
430: TREE(k,RED,TREE(lk,BLACK,ll,lr),
431: TREE(rk,BLACK,rl,rr))
432: | _ => TREE(lrk,BLACK,TREE(lk,RED,ll,lrl),
433: TREE(k,RED,lrr,r)))
434: | l as TREE(lk,RED, ll as TREE(llk,RED,lll,llr), lr) =>
435: (case r
436: of TREE(rk,RED,rl,rr) =>
437: TREE(k,RED,TREE(lk,BLACK,ll,lr),
438: TREE(rk,BLACK,rl,rr))
439: | _ => TREE(lk,BLACK,ll,TREE(k,RED,lr,r)))
440: | l => TREE(k,BLACK,l,r)
441: else TREE(key,BLACK,l,r)
442: | f (TREE(k,RED,l,r)) =
443: if elem_gt(key,k) then TREE(k,RED,l, f r)
444: else if elem_gt(k,key) then TREE(k,RED, f l, r)
445: else TREE(key,RED,l,r)
446: in case f t
447: of TREE(k,RED, l as TREE(_,RED,_,_), r) => TREE(k,BLACK,l,r)
448: | TREE(k,RED, l, r as TREE(_,RED,_,_)) => TREE(k,BLACK,l,r)
449: | t => t
450: end
451:
452: fun select_arb (TREE(k,_,l,r)) = k
453: | select_arb EMPTY = raise Select_arb
454:
455: fun exists key t =
456: let fun look EMPTY = false
457: | look (TREE(k,_,l,r)) =
458: if elem_gt(k,key) then look l
459: else if elem_gt(key,k) then look r
460: else true
461: in look t
462: end
463:
464: fun find key t =
465: let fun look EMPTY = NONE
466: | look (TREE(k,_,l,r)) =
467: if elem_gt(k,key) then look l
468: else if elem_gt(key,k) then look r
469: else SOME k
470: in look t
471: end
472:
473: fun revsetfold f t start =
474: let fun scan (EMPTY,value) = value
475: | scan (TREE(k,_,l,r),value) = scan(r,f(k,scan(l,value)))
476: in scan(t,start)
477: end
478:
479: fun setfold f t start =
480: let fun scan(EMPTY,value) = value
481: | scan(TREE(k,_,l,r),value) = scan(l,f(k,scan(r,value)))
482: in scan(t,start)
483: end
484:
485: fun app f t =
486: let fun scan EMPTY = ()
487: | scan(TREE(k,_,l,r)) = (scan l; f k; scan r)
488: in scan t
489: end
490:
491: (* equal_tree : test if two trees are equal. Two trees are equal if
492: the set of leaves are equal *)
493:
494: fun set_eq (tree1 as (TREE _),tree2 as (TREE _)) =
495: let datatype pos = L | R | M
496: exception Done
497: fun getvalue(stack as ((a,position)::b)) =
498: (case a
499: of (TREE(k,_,l,r)) =>
500: (case position
501: of L => getvalue ((l,L)::(a,M)::b)
502: | M => (k,case r of EMPTY => b | _ => (a,R)::b)
503: | R => getvalue ((r,L)::b)
504: )
505: | EMPTY => getvalue b
506: )
507: | getvalue(nil) = raise Done
508: fun f (nil,nil) = true
509: | f (s1 as (_ :: _),s2 as (_ :: _ )) =
510: let val (v1,news1) = getvalue s1
511: and (v2,news2) = getvalue s2
512: in (elem_eq(v1,v2)) andalso f(news1,news2)
513: end
514: | f _ = false
515: in f ((tree1,L)::nil,(tree2,L)::nil) handle Done => false
516: end
517: | set_eq (EMPTY,EMPTY) = true
518: | set_eq _ = false
519:
520: (* gt_tree : Test if tree1 is greater than tree 2 *)
521:
522: fun set_gt (tree1,tree2) =
523: let datatype pos = L | R | M
524: exception Done
525: fun getvalue(stack as ((a,position)::b)) =
526: (case a
527: of (TREE(k,_,l,r)) =>
528: (case position
529: of L => getvalue ((l,L)::(a,M)::b)
530: | M => (k,case r of EMPTY => b | _ => (a,R)::b)
531: | R => getvalue ((r,L)::b)
532: )
533: | EMPTY => getvalue b
534: )
535: | getvalue(nil) = raise Done
536: fun f (nil,nil) = false
537: | f (s1 as (_ :: _),s2 as (_ :: _ )) =
538: let val (v1,news1) = getvalue s1
539: and (v2,news2) = getvalue s2
540: in (elem_gt(v1,v2)) orelse (elem_eq(v1,v2) andalso f(news1,news2))
541: end
542: | f (_,nil) = true
543: | f (nil,_) = false
544: in f ((tree1,L)::nil,(tree2,L)::nil) handle Done => false
545: end
546: end
547:
548: functor FullSet (B : sig type elem
549: val eq : (elem*elem) -> bool
550: val gt : (elem*elem) -> bool
551: end
552: ) : FULLSET =
553: struct
554: structure C = BaseSet(B)
555: open C
556: type set = base_set
557:
558: fun is_empty(S) = (let val (_) = select_arb(S) in false end
559: handle Select_arb => true)
560:
561: fun make_list(S) = setfold (fn (a,r) => a::r) S nil
562:
563: val contained = exists
564:
565: fun make_set l =
566: List.fold (fn (a,NewSet) => insert a NewSet) l empty
567:
568: fun partition F S = setfold (fn (a,(Yes,No)) =>
569: if F(a) then (insert a Yes,No)
570: else (Yes,insert a No))
571: S (empty,empty)
572:
573: fun remove(X, XSet) =
574: let val (YSet, _) =
575: partition (fn a => not (elem_eq (X, a))) XSet
576: in YSet
577: end
578:
579: fun difference(Xs, Ys) =
580: setfold (fn (a,Xs') => if exists a Ys then Xs' else insert a Xs') Xs
581: empty
582:
583: fun singleton X = insert X empty
584:
585: fun card(S) = setfold (fn (a,count) => count+1) S 0
586:
587: val same_set = set_eq
588:
589: fun union(Xs,Ys)= setfold (fn (a,Xs) => insert a Xs) Ys Xs
590:
591: local
592: fun closure'(from, f, result) =
593: if is_empty from then result
594: else
595: let val (more,result) =
596: setfold (fn (a,(more',result')) =>
597: let val more = f a
598: val new = difference(more,result)
599: in (union(more',new),union(result',new))
600: end) from
601: (empty,result)
602: in closure'(more,f,result)
603: end
604: in
605: fun closure(start, f) = closure'(start, f, start)
606: end
607: end;
608:
609: functor Graph (B :
610: sig
611: type node
612: type edge
613: val eq_node : node * node -> bool
614: val gt_node : node * node -> bool
615: val eq_edge : edge * edge -> bool
616: val gt_edge : edge * edge -> bool
617: end
618: ) : GRAPH =
619: struct
620:
621: open B
622:
623: type graph_edge = {From : node, Edge : edge, To :node }
624:
625: fun EqEdge ({From=F1,Edge=E1, To = T1},{From=F2,Edge=E2,To=T2}) =
626: eq_node (F1,F2) andalso eq_node (T1,T2) andalso eq_edge(E1,E2)
627:
628: fun GtEdge ({From=F1,Edge=E1, To = T1},{From=F2,Edge=E2,To=T2}) =
629: gt_node(F1,F2) orelse (eq_node(F1,F2) andalso
630: (gt_node(T1,T2) orelse (eq_node(T1,T2) andalso gt_edge(E1,E2))))
631:
632: structure N = FullSet (struct
633: type elem = node
634: val eq = eq_node
635: val gt = gt_node
636: end
637: )
638:
639: structure EdgeSet = FullSet (struct
640: type elem = graph_edge
641: val eq = EqEdge
642: val gt= GtEdge
643: end
644: )
645:
646:
647: datatype graph = GRAPH of {TheNodes : N.set, TheEdges : EdgeSet.set}
648:
649: fun find_node (GRAPH {TheNodes, ...},n) = N.find n TheNodes
650:
651: val null_graph = GRAPH {TheNodes = N.empty, TheEdges = EdgeSet.empty}
652:
653: fun nodes_of(GRAPH{TheNodes, ...}) = N.make_list TheNodes
654:
655: fun num_nodes(GRAPH{TheNodes, ...}) = N.card(TheNodes)
656:
657: fun add_node (GRAPH {TheNodes, TheEdges} , n1) =
658: GRAPH{TheNodes=N.insert n1 TheNodes, TheEdges=TheEdges}
659:
660: fun add_edge (GRAPH {TheNodes, TheEdges}, n1, Edge, n2) =
661: let val NewEdges =
662: EdgeSet.insert {From=n1, Edge=Edge, To=n2} TheEdges
663: in GRAPH {TheNodes=TheNodes, TheEdges=NewEdges}
664: end
665:
666: fun join (GRAPH{TheNodes, TheEdges},n1, Edge, n2) =
667: GRAPH {TheNodes=N.insert n1 (N.insert n2 TheNodes),
668: TheEdges= EdgeSet.insert {From=n1,Edge=Edge,
669: To=n2} TheEdges }
670:
671: fun edges ( GRAPH {TheNodes, TheEdges }, n) =
672: let fun match {From, Edge,To} = eq_node (From, n)
673: in EdgeSet.setfold (fn (e,r) =>
674: if match e then EdgeSet.insert e r else r)
675: TheEdges EdgeSet.empty
676: end
677:
678: fun all_edges(GRAPH{TheEdges, ...}) = TheEdges
679:
680: end;
681: functor V2_Lset (G : V2_LR_GRAMMAR) : V2_LSET =
682: struct
683: open G
684: structure G = G
685: abstype Lookahead = LS of (G.Terminal*int) list
686: with val emptylookahead = LS nil
687:
688: (* mergelookahead - return true as the second element of the
689: pair if lookahead set 2 contains some elements lookahead
690: set 1 does not
691: *)
692:
693: fun mergelookahead (p,flag : bool ref) : Lookahead =
694: let fun f(nil,nil,r) = rev r
695: | f(a::a',nil,r) = f(a',nil,a::r)
696: | f(nil,b::b',r) = f(b',nil,b::r)
697: | f(x as ((a as (_,hash_a))::a'),
698: y as ((b as (_,hash_b))::b'),r) =
699: if ((hash_a : int ) < hash_b) then
700: f(a',y,a::r)
701: else if (hash_a>hash_b) then
702: f(x,b',b::r)
703: else f(a',b',a::r)
704: in case p of
705: (LS a,LS b) =>
706: let val r = f(a,b,nil)
707: in (if (length a) < (length r) then
708: flag := true
709: else (); LS r)
710: end
711: end
712:
713: (* addterms - adds terminals to a lookahead set *)
714:
715: fun addterms(LS a,l) =
716: let fun g(l,e) =
717: let val hash_e = termHash e
718: fun insert(nil,e) = [(e,hash_e)]
719: | insert(t as ((a' as (_,hash_a))::a),e) =
720: if (hash_a<hash_e) then a'::(insert(a,e))
721: else if (hash_a=hash_e) then t
722: else (e,hash_e)::a'::a
723: in insert(l,e)
724: end
725: val r=List.fold (fn (e,r) => g(r,e)) l a
726: in LS r
727: end
728:
729: fun makelookaheadlist (LS a) = List.map (fn (t,_) => t) a
730: end
731: end;
732:
733: functor V2_LrUtils(structure G : V2_LR_GRAMMAR): V2_LR_UTILS =
734: struct
735:
736: structure G = G
737: structure Lset = V2_Lset(G)
738: structure Memo = Memo(type Arg = G.Nonterminal)
739:
740: open G
741:
742: val DEBUG = false
743: val print = if DEBUG then output std_out
744: else Busy.print
745: val println = if DEBUG then fn x => (print x; print "\n")
746: else Busy.println
747: val withNewline = if DEBUG then (fn pr => fn x => (pr x; print "\n"))
748: else Busy.withNewline
749:
750: (* diagnostics *)
751: val mkshowSymbol =
752: fn {showTerminalClass = showTerminalClass : G.Terminal -> string,
753: showNonterminal = showNonterminal : G.Nonterminal -> string
754: } => fn (TERM t) => showTerminalClass t
755: | (NONTERM nt) => showNonterminal nt
756:
757: fun showSpaced f lst = fold (fn (x, y) => x ^ " " ^ y) (map f lst) ""
758:
759: datatype Core = CORE of { I : {coreLHS: G.Nonterminal,
760: corePrecedence: int option,
761: coreAttribute: G.Attribute},
762: coreRHSbefore: G.Symbol list,
763: coreRHSafter: G.Symbol list,
764: prop : bool ref,
765: lookaheads : Lset.Lookahead ref
766: }
767:
768:
769: val printCore =
770: fn {showSymbol=showSymbol: G.Symbol -> string,
771: showNonterminal=showNonterminal : G.Nonterminal -> string,
772: showTerminalClass=showTerminalClass : G.Terminal -> string } =>
773: fn (CORE c) =>
774: let val {I = {coreLHS=coreLHS, ...}, coreRHSbefore, coreRHSafter,
775: prop, lookaheads} = c
776: in (
777: print(showNonterminal coreLHS ^ " : "
778: ^ showSpaced showSymbol (rev coreRHSbefore)
779: ^ "_"
780: ^ showSpaced showSymbol coreRHSafter
781: );
782: if DEBUG then
783: print(" lookaheads: " ^ showSpaced showTerminalClass
784: (Lset.makelookaheadlist (!lookaheads))
785: )
786: else ()
787: )
788: end
789:
790: fun gtSymbol(TERM t1, TERM t2) = gtTerminal(t1,t2)
791: | gtSymbol(NONTERM nt1, NONTERM nt2) = gtNonterminal(nt1,nt2)
792: | gtSymbol (TERM _,NONTERM _) = true
793: | gtSymbol _ = false
794:
795: fun eqSymbol(TERM t1, TERM t2) = eqTerminal(t1,t2)
796: | eqSymbol(NONTERM nt1, NONTERM nt2) =eqNonterminal(nt1,nt2)
797: | eqSymbol _ = false
798:
799: fun eqCore(CORE {I = {coreAttribute = G.ATTRIB {num=n1,...}, ...},
800: coreRHSbefore=b1, ...},
801: CORE {I = {coreAttribute = G.ATTRIB {num=n2,...}, ...},
802: coreRHSbefore = b2, ...}
803: ) =
804: (n1 = n2) andalso (length b1 = length b2)
805:
806: fun gtCore(CORE {I = {coreAttribute = G.ATTRIB {num=n1,...}, ...},
807: coreRHSbefore=b1, ...},
808: CORE {I = {coreAttribute = G.ATTRIB {num=n2,...}, ...},
809: coreRHSbefore = b2, ...}
810: ) =
811: (n1>n2) orelse (n1=n2 andalso (length b1) > length (b2))
812:
813: structure CoreSet = FullSet (struct
814: type elem = Core
815: val gt = gtCore
816: val eq = eqCore
817: end)
818:
819: fun filter f (x :: xs) = if f x then x :: filter f xs else filter f xs
820: | filter f nil = nil
821:
822: fun buildCore(RULE{lhs, rhs, attribute, precedence}) =
823: CORE({I = {coreLHS=lhs,
824: corePrecedence=precedence,
825: coreAttribute=attribute},
826: coreRHSbefore=nil,
827: coreRHSafter=rhs,
828: prop=ref false,
829: lookaheads=ref Lset.emptylookahead
830: }
831: )
832:
833: fun copyCore(a as (CORE c)) =
834: case c
835: of {I,coreRHSbefore, coreRHSafter, ...} =>
836: CORE({I=I,
837: coreRHSbefore=coreRHSbefore,
838: coreRHSafter=coreRHSafter,
839: prop=ref false,
840: lookaheads = ref Lset.emptylookahead
841: })
842:
843: val copyCoreSet = fn s =>
844: CoreSet.setfold (fn (a,r)=> CoreSet.insert (copyCore a) r) s
845: CoreSet.empty
846:
847: val printCoreSet = fn {printCore = printCore : Core -> unit} =>
848: let val printCoreIndented = fn core =>
849: (print " "; withNewline printCore core)
850: in fn cores => CoreSet.app printCoreIndented cores
851: end
852:
853: val buildCores = fn rules => fn nt =>
854: let val matchingProds =
855: filter (fn RULE{lhs, ...} => eqNonterminal(lhs, nt))
856: rules
857:
858: val cores = CoreSet.make_set (map buildCore matchingProds)
859: in
860: (*
861: if DEBUG then
862: (println("buildCores " ^ showNonterminal nt);
863: printCoreSet cores
864: )
865: else
866: *) ();
867:
868: cores
869: end
870:
871: val mkselectCores =
872: fn {rules=rules : G.Rule list,numNonterminals=n : int} =>
873: (Memo.enum_memo_fn (G.nontermHash, n))
874: (buildCores rules)
875:
876: fun immediateSymbols cores =
877: CoreSet.setfold
878: (fn (CORE {coreRHSafter,...},result) =>
879: case coreRHSafter
880: of sym :: _ =>
881: if (exists (fn a => eqSymbol(a,sym)) result)
882: then result
883: else sym::result
884: | nil => result
885: ) cores nil
886:
887:
888: datatype true = T of Nonterminal | F
889:
890: (* Transitive closure : assumes array is an array of row arrays,
891: where entry a(i,j) is true if the ith item is connected to the
892: jth item, i.e. if the nonterminal with hash # i will cause all
893: the productions of the nonterminal with hash # j to be added to a
894: core set when
895: a production of the form 'a . B 'b, where hash B = i is
896: encountered *)
897:
898: val transitive_closure = fn (a : true array array) =>
899: let val size = Array.length a
900: val i = ref 0
901: val j = ref 0
902: val k = ref 0
903: in while (!i < size) do
904: (j := 0; while (!j < size) do
905:
906: (* check if jth nonterm derives ith nonterm *)
907:
908: (case ((a sub !j) sub !i) of
909: (T _) =>
910:
911: (* if so then connect jth nonterm w/ everything the
912: ith derives
913: *)
914: (k := 0;
915: while (!k < size) do
916: (case ((a sub !i) sub !k)
917: of (d as (T x)) => update(a sub !j,!k,d)
918: | _ => ();
919: if DEBUG then (
920: print ("doing " ^ (makestring (!i)) ^ " " ^
921: (makestring (!j)) ^ " " ^ (makestring (!k)) ^
922: "\n")
923: )
924: else ();
925: k := !k +1
926: )
927: )
928: | F => (); j := !j+1
929: );
930: i := !i + 1
931: )
932: end
933:
934: (* ComputeClosureAdditions - compute the nonterminals which must
935: be added when one nonterminal with a dot before it is added to
936: the core set. Do this by constructing an array indexed by
937: nonterminal hash #. Each a[i,j] entry is set to true when
938: nonterminal i derives nonterminal j. Then take the closure
939: of the array. (Clearly, if A -> .B, and B -> .C, then A -> .C,
940: also. *)
941:
942: fun ComputeClosureAdditions(rules,max) =
943: let val a = array(max,array(max,F)) (* re: same subarray, always *)
944: val _ = let val i = ref 0 (* re: make them different *)
945: in while (!i<max) do (* arrays *)
946: (update(a,!i,array(max,F)); i := !i + 1)
947: end
948: val g = fn (RULE {lhs,rhs=(NONTERM n)::_,...}) =>
949: update(a sub (nontermHash lhs),nontermHash n,T n)
950: | _ => ()
951: in (app g rules; transitive_closure(a); a)
952: end
953:
954: val ComputeClosureAdditions =
955: (*
956: if DEBUG then
957: fn (rules,max) =>
958: let val a = ComputeClosureAdditions(rules,max)
959: val i = ref 0
960: in (while (!i < max) do
961: (let val j = ref 0
962: in while (!j < max) do
963: (case ((a sub !i) sub !j) of
964: T i => print ((showNonterminal i) ^ " ")
965: | F => ();
966: j := !j+1)
967: end; println ""; i := !i+1
968: ); a)
969: end
970: else
971: *) ComputeClosureAdditions
972:
973: (* ComputeCoreSetClosure:
974:
975: Takes the closure of a core set. This consists of adding for
976: each item with a nonterminal immediately after the dot all
977: productions for which the nonterminal is the lhs. This process
978: is then repeated for the new production.
979:
980: We can compute the set of all nonterminals whose productions
981: must be added when a nonterminal is added using ComputeClosure-
982: Additions.
983:
984: We keep a boolean array indexed by nonterminal hash #'s. We look
985: at all the items in the core set. When we find an item with a non-
986: terminal immediately after the ., we set the corresponding element
987: in the bool array to true,s ince we must add all the productions for
988: that terminal. We also set the entries for all the nonterminals
989: which must be added when that nonterminal is added. This uses the
990: information from ComputeClosureAdditions.
991:
992: Note that we can check the entry for the nonterminal with the dot
993: before it before doing any of this. If it is true, since the
994: relation defined by ComputeClosureAdditions is transitive, all non-
995: terminals which would need to be added for this nonterminal have
996: already been added when it was added
997:
998: We then take the boolean array, and add all productions for
999: all nonterminals whose have been set to true.
1000: *)
1001:
1002: fun ComputeCoreSetClosure(cores,a,max,selectCores) =
1003: (* cores = core set, a = array from ComputeClosureAdditions,
1004: max = # of nonterminals *)
1005:
1006: let val b = array(max,F)
1007: fun g (CORE c) =
1008: let val {coreRHSafter,...} = c
1009: in case coreRHSafter of
1010: ((NONTERM n) :: _) =>
1011: let val num = nontermHash n
1012: in case (b sub num) of
1013: F => (update(b,num,T n);
1014: let val i = ref 0
1015: in while (!i < max) do
1016: (case ((a sub num) sub !i)
1017: of F => ()
1018: | (m as (T _)) =>
1019: update(b,!i,m);
1020: i := !i + 1
1021: )
1022: end
1023: )
1024: | (T _ ) => ()
1025: end
1026: | _ => ()
1027: end
1028: fun add_cores(cores) =
1029: let fun g (i,cores) =
1030: case (b sub i) of
1031: (T k) => CoreSet.union(cores,
1032: (selectCores k))
1033: | F => cores
1034: fun f(i,r) =
1035: if (i < max) then f(i+1,g(i,r))
1036: else r
1037: in f(0,cores)
1038: end
1039: in ((CoreSet.app g cores); add_cores cores)
1040: end
1041:
1042: val mkcoreClosure=
1043: fn {rules=rules:G.Rule list,
1044: numNonterminals=numNonterminals:int,
1045: selectCores=selectCores:G.Nonterminal->CoreSet.set
1046: } =>
1047: let val a = ComputeClosureAdditions (rules,numNonterminals)
1048: in fn cores =>
1049: ComputeCoreSetClosure(cores,a,numNonterminals,selectCores)
1050: end
1051:
1052: (* undefined now : printCoreSet, coreClosure
1053:
1054: val coreClosure =
1055: if DEBUG then
1056: fn cores =>
1057: (println "coreClosure of";
1058: printCoreSet cores;
1059: println "yields";
1060: let val cores' = coreClosure cores
1061: in
1062: printCoreSet cores';
1063: cores'
1064: end
1065: )
1066: else coreClosure
1067: *)
1068:
1069: (* prop_f_to_c_a: Propagate firsts to closure additions.
1070:
1071: For each item in a core of the form A -> 'a . B 'b, where
1072: B is a nonterminal, all B productions will contain first_string
1073: 'b in their lookahead set
1074: *)
1075:
1076: val prop_f_to_c_a : {first_string : G.Symbol list -> G.Terminal list,
1077: selectCores : G.Nonterminal -> CoreSet.set} ->
1078: (CoreSet.set -> unit) =
1079: fn {first_string = first_string : G.Symbol list -> G.Terminal list,
1080: selectCores = selectCores : G.Nonterminal -> CoreSet.set}
1081: => fn (cores : CoreSet.set) =>
1082:
1083: (* f : check if a core has a . before a nonterminal.
1084: If so, propagate the first set of the string
1085: following the nonterminal to all the productions
1086: derived from the nonterminal
1087: *)
1088:
1089: let val f = fn (CORE {coreRHSafter=(NONTERM b)::r, ...}) =>
1090: let val firsts = first_string r
1091: exception ClosureError
1092: val g = fn a =>
1093: case (CoreSet.find a cores) of
1094: NONE => raise ClosureError
1095: | SOME (CORE {lookaheads=l1, ...}) =>
1096: l1 := Lset.addterms(!l1,firsts)
1097: in CoreSet.app g (selectCores b)
1098: end
1099: | _ => ()
1100:
1101: in (CoreSet.app f cores)
1102: end
1103:
1104: (* set_prop: Prop is a boolean variable which is set to true
1105: for items which propagate their lookaheads to items derived
1106: from them. These items have the form 'a .B 'c, where
1107: 'c derives epsilon. The lookaheads propagate to those items
1108: derived from B through the closure operation, and to the
1109: item GOTO('a .B 'c, B). This function sets prop for all items
1110: in a core set.
1111:
1112: *)
1113:
1114: val set_prop =
1115: fn (nullable_string : G.Symbol list -> bool) =>
1116: let val g = fn (CORE c) =>
1117: let val c' = c
1118: in case c'
1119: of {coreRHSafter=(NONTERM _):: t,prop,...} =>
1120: if (nullable_string t) then prop := true
1121: else ()
1122: | _ => ()
1123: end
1124: in CoreSet.app g (* must be applied to a core set now *)
1125: end
1126:
1127: val hardwire_eof = fn (cores,eof,start) =>
1128: let val f = fn (CORE c) =>
1129: let val {I={coreLHS=lhs,...},lookaheads,...} = c
1130: in if (eqNonterminal(lhs,start)) then
1131: lookaheads := Lset.addterms(!lookaheads,[eof])
1132: else ()
1133: end
1134: in CoreSet.app f cores
1135: end
1136:
1137: (* propagate_l_to_c_a: Propagate lookaheads to closure additions.
1138: If an item in a core has the form A-> 'a .B 'b where B is a
1139: nonterminal, and 'b derives epsilon, then all productions of
1140: B get A's lookahead. Returns true if any change to a
1141: B productions lookahead occurs.
1142: *)
1143:
1144: val propagate_l_to_c_a =
1145: fn {selectCores=selectCores : G.Nonterminal -> CoreSet.set} =>
1146: fn (cores: CoreSet.set, result : bool ref) =>
1147: let val f = fn (CORE c) =>
1148: case c
1149:
1150: (* Check that a core item has the correct form *)
1151:
1152: of {prop=ref true,coreRHSafter=NONTERM n::_,
1153: lookaheads,...}=>
1154: let exception PropClosureError
1155:
1156: (* g: Takes an item whose lookahead depends on the
1157: above item, and merges the above item's
1158: lookahead into the item's lookahead
1159: *)
1160: exception PropClosureError
1161:
1162: val g = fn c =>
1163: case (CoreSet.find c cores) of
1164: (SOME (CORE {lookaheads=l, ...})) =>
1165: l := Lset.mergelookahead
1166: ((!l,!lookaheads),result)
1167: | NONE => raise PropClosureError
1168:
1169: (* apply g to the items directly derived from
1170: NONTERM n.
1171: *)
1172:
1173: in CoreSet.app g (selectCores n)
1174: end
1175: | _ => ()
1176: in CoreSet.app f cores
1177: end
1178:
1179: (* propagate_l_to_g_i: Propagate lookaheads to goto items *)
1180:
1181: val propagate_l_to_g_i =
1182:
1183:
1184: fn (shiftCore : Core -> Core) =>
1185:
1186: (* takes an edge from n1 to n2 *)
1187:
1188: fn ((n1: CoreSet.set, e: G.Symbol, n2 : CoreSet.set),result) =>
1189:
1190: let
1191:
1192: (* match: merge lookaheads of an item into the items
1193: which result from a shift
1194: *)
1195:
1196: val match=
1197: fn (a as (CORE {coreRHSafter=b::_,lookaheads=l1,...})) =>
1198: if eqSymbol(b,e) then
1199: case (CoreSet.find (shiftCore a) n2)
1200: of SOME (CORE {lookaheads=l2,...}) =>
1201: l2 := Lset.mergelookahead((!l2,!l1),result)
1202: | NONE => ()
1203: else ()
1204: | _ => ()
1205: in (CoreSet.app match n1)
1206: end
1207: end;
1208:
1209: functor V2_Lookahead(structure G : V2_LR_GRAMMAR
1210: structure Utils: V2_LR_UTILS
1211: sharing Utils.G = G
1212: ): V2_LOOKAHEAD =
1213: struct
1214: structure NontermMemo = Memo(type Arg = G.Nonterminal)
1215:
1216: structure G = G
1217: structure Utils = Utils
1218: open G Utils
1219:
1220: structure TermSet = FullSet(type elem = Terminal
1221: val gt = gtTerminal
1222: val eq = eqTerminal)
1223:
1224: structure NontermSet = FullSet(type elem = Nonterminal
1225: val gt = gtNonterminal
1226: val eq = eqNonterminal)
1227:
1228: val DEBUG = false
1229:
1230: (* build an enumerated memo-fn over nonterminals *)
1231:
1232: val mkfunctions =
1233: fn {numNonterminals,selectCores,showNonterminal,showTerminalClass} =>
1234: let
1235: val nontermMemo = NontermMemo.enum_memo_fn(nontermHash, numNonterminals)
1236:
1237: (* actual print functions (rather than string generators) *)
1238:
1239: val printTerminalClass = Busy.print o showTerminalClass
1240: val printNonterminal = Busy.print o showNonterminal
1241:
1242: (* The FIRST set construction functions *)
1243:
1244: (* nullable: true if nonterminal "nt" has some null rhs production *)
1245: fun nullable(nt, cores) =
1246: CoreSet.setfold (fn (CORE c,rest) =>
1247: let val {coreRHSafter, ...} = c
1248: in rest orelse (null coreRHSafter)
1249: end) cores false
1250:
1251:
1252: (* memo-ise "nullable", add diags *)
1253: fun prNullable(nt, b) =
1254: (Busy.println("Nullable " ^ showNonterminal nt ^ "? "
1255: ^ case b of true => "YES" | false => "NO"
1256: );
1257: b
1258: )
1259:
1260: val nullable =
1261: nontermMemo(if DEBUG then
1262: fn nt => prNullable(nt, nullable(nt, selectCores nt))
1263: else
1264: fn nt => nullable(nt, selectCores nt)
1265: )
1266:
1267: (* nullable_string: check if a string of terminals and variables is nullable *)
1268:
1269: fun nullable_string (TERM t :: _ ) = false
1270: | nullable_string (NONTERM t :: r ) =
1271: (if nullable t then (nullable_string r) else false)
1272: | nullable_string nil = true
1273:
1274: (* accumulate: look at the start of core right-hand-sides, looking past
1275: nullable nts, applying addObj to the visible symbols. *)
1276: fun accumulate(cores, empty, addObj) =
1277: let
1278: fun accumAlongSymbols(symbols, result) =
1279: case symbols
1280: of (sym as NONTERM nt) :: rest =>
1281: if nullable nt then
1282: accumAlongSymbols(rest, addObj(sym, result))
1283: else
1284: addObj(sym, result)
1285:
1286: | (sym as TERM _) :: _ => addObj(sym, result)
1287:
1288: | nil => result
1289:
1290: fun accumAlongCores(cores, result) =
1291: CoreSet.setfold (fn (CORE c,result) =>
1292: let val {coreRHSafter, ...} = c
1293: in accumAlongSymbols(coreRHSafter, result)
1294: end) cores result
1295: in
1296: accumAlongCores(cores, empty)
1297: end
1298:
1299:
1300: (* first1: the FIRST set of a nonterminal in the grammar. Only looks
1301: at other terminals, but it *is* clever enough to move past nullable
1302: nonterminals at the start of a production. *)
1303: fun first1 nt = accumulate(selectCores nt,
1304: TermSet.empty,
1305: fn (TERM t, set) => TermSet.insert t set
1306: | (_, set) => set
1307: )
1308:
1309: (* memo-ise first1, add diags *)
1310: fun prFirst1(nt, termSet) =
1311: (Busy.print("First1 set of " ^ showNonterminal nt ^ " = { ");
1312: TermSet.app (Busy.withSpace printTerminalClass) termSet;
1313: Busy.println "}";
1314: termSet)
1315: val first1 = nontermMemo(if DEBUG then fn nt => prFirst1(nt, first1 nt)
1316: else first1
1317: )
1318:
1319: (* starters1: given a nonterminal "nt", return the set of nonterminals
1320: which can start its productions. Looks past nullables, but doesn't
1321: recurse *)
1322: fun starters1 nt = accumulate(selectCores nt,
1323: NontermSet.empty,
1324: fn (NONTERM nt, set) =>
1325: NontermSet.insert nt set
1326: | (_, set) => set
1327: )
1328:
1329: (* memo-ise starters1, add diags *)
1330: fun prStarters1(nt, nontermSet) =
1331: (Busy.print("Starters1 set of " ^ showNonterminal nt ^ " = { ");
1332: NontermSet.app (Busy.withSpace printNonterminal) nontermSet;
1333: Busy.println "}";
1334: nontermSet
1335: )
1336:
1337: val starters1 =
1338: nontermMemo(if DEBUG then fn nt => prStarters1(nt, starters1 nt)
1339: else starters1
1340: )
1341:
1342: (* starters: a closure over starters1 *)
1343: fun starters nt = NontermSet.closure(NontermSet.singleton nt, starters1)
1344:
1345: (* memo-ise starters, add diags *)
1346: fun prStarters(nt, nontermSet) =
1347: (Busy.print("Starters set of " ^ showNonterminal nt ^ " = { ");
1348: NontermSet.app (Busy.withSpace printNonterminal) nontermSet;
1349: Busy.println "}";
1350: nontermSet
1351: )
1352:
1353: val starters =
1354: nontermMemo(if DEBUG then fn nt => prStarters(nt, starters nt)
1355: else starters
1356: )
1357:
1358: (* first: maps a nonterminal to its first-set. Get all the starters of
1359: the nonterminal, get the first1 terminal set of each of these,
1360: union the whole lot together *)
1361: fun first nt =
1362: let val startersSet = starters nt
1363: val startersList = startersSet
1364: in
1365: NontermSet.setfold (fn (a,r) => TermSet.union(r,first1 a))
1366: startersList TermSet.empty
1367: end
1368:
1369: (* memo-ise first, add diags *)
1370: fun prFirst(nt, termSet) =
1371: (Busy.print("First set of " ^ showNonterminal nt ^ " = { ");
1372: TermSet.app (Busy.withSpace printTerminalClass) termSet;
1373: Busy.println "}";
1374: termSet
1375: )
1376:
1377: val first =
1378: nontermMemo(if DEBUG then fn nt => prFirst(nt, first nt)
1379: else first
1380: )
1381:
1382:
1383:
1384: (* prefix: all possible terminals starting a symbol list *)
1385: fun prefix symbols =
1386: case symbols
1387: of TERM t :: _ => TermSet.singleton t
1388: | NONTERM nt :: rest =>
1389: if nullable nt then
1390: TermSet.union(first nt, prefix rest)
1391: else
1392: first nt
1393: | nil => TermSet.empty
1394:
1395: in {first_string = fn n => TermSet.make_list (prefix n),
1396: nullable_string = nullable_string}
1397: end
1398: end
1399:
1400: functor V2_LrGraph(structure G: V2_LR_GRAMMAR
1401: structure Utils: V2_LR_UTILS
1402: structure Lookahead: V2_LOOKAHEAD
1403: sharing Lookahead.Utils = Utils
1404: sharing Lookahead.G = Utils.G = G
1405: ) : V2_LR_GRAPH =
1406: struct
1407:
1408: open G Lookahead Utils
1409:
1410: val DEBUG = false
1411:
1412: (* type abbrevs for the type of graph we're generating *)
1413: type State = {state: int, cores: CoreSet.set}
1414:
1415: structure Lr_Graph = Graph
1416: (struct
1417: type node = {state : int, cores : CoreSet.set }
1418: type edge = Symbol
1419: val gt_node = fn ({cores,...}:State,{cores=cores',...}:State) =>
1420: CoreSet.set_gt(cores,cores')
1421: val eq_node = fn ({cores,...}:State,{cores=cores',...}:State) =>
1422: CoreSet.set_eq(cores,cores')
1423: val eq_edge = eqSymbol
1424: val gt_edge = gtSymbol
1425: end)
1426:
1427: type Graph = Lr_Graph.graph
1428:
1429: (* the goto function from State * Symbol to State list *)
1430: fun coreMatch(CORE c, symbol) =
1431: let val {coreRHSafter, ...} = c
1432: in
1433: case coreRHSafter
1434: of (symbol' :: _) => eqSymbol(symbol, symbol')
1435: | _ => false
1436: end
1437:
1438: exception ShiftCore
1439: fun shiftCore (a as (CORE c)) =
1440: case c
1441: of {I, coreRHSbefore, coreRHSafter=hd :: tl, prop,lookaheads} =>
1442: CORE({I=I,
1443: coreRHSbefore=hd :: coreRHSbefore,
1444: coreRHSafter=tl,
1445: prop=prop,
1446: lookaheads = lookaheads
1447: }
1448: )
1449: | _ => raise ShiftCore
1450:
1451: val mkGraph = fn {rules = rules : G.Rule list, verbose = verbose : bool,
1452: eof = eof: G.Terminal,start = start: G.Nonterminal,
1453: termPrecedence = termPrecedence: G.Terminal -> int option,
1454: showTerminalClass=showTerminalClass: G.Terminal -> string,
1455: showTerminalValue=showTerminalValue : G.Terminal -> string,
1456: showNonterminal=showNonterminal : G.Nonterminal -> string,
1457: showAttribute=showAttribute : G.Attribute -> string,
1458: numTerminals=numTerminals : int,
1459: numNonterminals=numNonterminals : int
1460: } =>
1461: let val showSymbol = mkshowSymbol {showTerminalClass=showTerminalClass,
1462: showNonterminal=showNonterminal}
1463: val printCore = printCore {showSymbol = showSymbol,
1464: showNonterminal = showNonterminal,
1465: showTerminalClass = showTerminalClass}
1466: val printCoreSet = printCoreSet {printCore=printCore}
1467: val selectCores = mkselectCores
1468: {rules=rules,numNonterminals=numNonterminals}
1469: val coreClosure = mkcoreClosure {rules=rules,
1470: numNonterminals = numNonterminals,
1471: selectCores = selectCores}
1472:
1473: val {first_string,nullable_string} =
1474: mkfunctions {numNonterminals = numNonterminals,
1475: selectCores = selectCores,
1476: showNonterminal = showNonterminal,
1477: showTerminalClass = showTerminalClass
1478: }
1479: (* the traversal of a set of cores which can shift on "symbol" *)
1480: fun traversal'(cores, symbol, result) =
1481: coreClosure(
1482: CoreSet.setfold (fn (a,result) =>
1483: if coreMatch(a,symbol) then CoreSet.insert (shiftCore a) result
1484: else result) cores result
1485: )
1486:
1487: (* include the symbol itself as well, for convenience in graph
1488: generation *)
1489: fun traversal cores symbol =
1490: (symbol, traversal'(cores, symbol, CoreSet.empty))
1491:
1492: val NextStateNum = ref 0
1493:
1494: val traversal =
1495: if DEBUG then
1496: fn cores =>
1497: fn symbol =>
1498: (Busy.println("Traversal by " ^ showSymbol symbol
1499: ^ " gives"
1500: );
1501: let val (_, cores') = traversal cores symbol
1502: in
1503: printCoreSet cores';
1504: (symbol, cores')
1505: end
1506: )
1507: else
1508: traversal
1509:
1510: (* incorporate1: incorporate a traversal from->symbol->cores into
1511: "graph". Return new graph, and optionally the `to' node, if
1512: it wasn't already present.
1513: *)
1514: fun incorporate1(graph, from: Lr_Graph.node,
1515: (symbol, cores : CoreSet.set)) =
1516: case (Lr_Graph.find_node(graph,{state=0,cores=cores})) of
1517: SOME existingNode =>
1518: (if DEBUG then
1519: (Busy.println "*Existing node found:";
1520: printCoreSet(#cores(existingNode))
1521: )
1522: else ();
1523: (Lr_Graph.add_edge (graph, from, symbol,existingNode),
1524: NONE)
1525: )
1526: | NONE =>
1527: let val _ =
1528: if DEBUG then
1529: (Busy.println("*New state "
1530: ^ makestring (!NextStateNum));
1531: printCoreSet cores
1532: )
1533: else
1534: Busy.dot()
1535:
1536: (* make sure every graph node has * UNIQUE * reference
1537: variables
1538: *)
1539:
1540: val newNode = {cores=copyCoreSet cores,
1541: state=(!NextStateNum)}
1542: val _ = NextStateNum := (!NextStateNum)+1
1543: in (Lr_Graph.add_edge (Lr_Graph.add_node (graph,newNode) , from, symbol,
1544: newNode), SOME newNode)
1545: end
1546:
1547: (* incorporate': takes a graph, a from-node, and a list of traversals
1548: ((symbol*Core set) list). adds any new nodes to the front of "newNodes"
1549: *)
1550: fun incorporate'(graph, from: Lr_Graph.node , traversals, newNodes) =
1551:
1552: case traversals
1553: of this :: rest =>
1554: let val (graph', to) = incorporate1(graph, from, this)
1555: in case to
1556: of SOME node =>
1557: incorporate'(graph', from, rest, node :: newNodes)
1558: | NONE => incorporate'(graph', from, rest, newNodes)
1559: end
1560: | nil => (graph, newNodes)
1561:
1562: fun generateGraph(events, graph) =
1563: case events
1564: of (thisEvent :: restEvents) =>
1565: let
1566: val {state, cores}: State = thisEvent
1567:
1568: val closuredCores = cores
1569: val _ =
1570: if DEBUG then
1571: (Busy.println("*Collecting on event: "
1572: ^ makestring state
1573: );
1574: printCoreSet closuredCores
1575: )
1576: else ()
1577:
1578: val immedSymbols = immediateSymbols closuredCores
1579:
1580: val prSymbol = (Busy.withSpace Busy.print) o showSymbol
1581: val _ =
1582: if DEBUG then
1583: (Busy.print "*Immediate symbols: { ";
1584: map prSymbol immedSymbols;
1585: Busy.println "}"
1586: )
1587: else ()
1588:
1589: val traversals =
1590: List.fold (fn (immed_symbol,r) =>
1591: (traversal closuredCores immed_symbol) :: r)
1592: immedSymbols nil
1593:
1594: val (newGraph, newEvents) =
1595: incorporate'(graph, thisEvent, traversals,restEvents)
1596: in
1597: generateGraph(newEvents, newGraph)
1598: end
1599:
1600: | _ => graph
1601:
1602: (* propagate lookaheads : propagate lookaheads throughout the
1603: graph
1604: *)
1605:
1606: val propagatelookaheads = fn (g : Lr_Graph.graph) =>
1607: let val cores = Lr_Graph.nodes_of g
1608: val cores = List.map (fn c => #cores c) cores
1609: val edges = List.map (fn {From,Edge,To} =>
1610: (#cores(From),Edge,#cores(To)))
1611: (Lr_Graph.EdgeSet.make_list (Lr_Graph.all_edges g))
1612: val gp = ref true;
1613: val cp = ref true;
1614: val _ = List.app (set_prop nullable_string) cores
1615: val _ = List.app (prop_f_to_c_a {first_string=first_string,
1616: selectCores=selectCores}) cores
1617: val closure_prop = fn c =>
1618: propagate_l_to_c_a {selectCores=selectCores} (c,cp)
1619: val goto_prop =
1620: let val goto_prop' = propagate_l_to_g_i shiftCore
1621: in fn e => goto_prop'(e,gp)
1622: end
1623: in while (!gp = true orelse !cp = true) do
1624: (gp := false; cp := false;
1625: output std_out "Propagating lookaheads ...\n";
1626: List.app closure_prop cores;
1627: List.app goto_prop edges
1628: )
1629: end
1630:
1631: (* generate the graph *)
1632: val startCores = copyCoreSet(coreClosure(selectCores start))
1633: val startEvent = {cores=startCores, state=0}
1634:
1635: val _ = if DEBUG then () else Busy.print "Generating State Graph"
1636:
1637: val _ = NextStateNum := 1
1638: val graph = generateGraph([startEvent],
1639: Lr_Graph.add_node(Lr_Graph.null_graph,startEvent))
1640:
1641: val _ = hardwire_eof(startCores,eof,start)
1642: val _ = propagatelookaheads graph
1643: in graph
1644: end
1645: end;
1646: functor V2_TableGen(structure G: V2_LR_GRAMMAR): V2_LR_TABLE =
1647: struct
1648:
1649: structure G = G
1650:
1651: structure Utils =
1652: V2_LrUtils(structure G = G)
1653:
1654: structure Lookahead =
1655: V2_Lookahead(structure G = G
1656: structure Utils = Utils
1657: )
1658:
1659: structure Graph =
1660: V2_LrGraph (
1661: structure G = G
1662: structure Utils = Utils
1663: structure Lookahead = Lookahead
1664: )
1665:
1666: type 'entry Table = 'entry array array
1667:
1668: fun PrTable ((pr : string->unit),
1669: (T : 'entry Table),
1670: (Str: (int * 'entry) -> string),
1671: (EncaseRow : ('entry array -> unit) * (string->unit) ->
1672: 'entry array -> unit)) =
1673: let
1674: val PrintRow = fn (R : 'entry array) =>
1675: let fun f(i,cnt) =
1676: if i<Array.length(R) then
1677: let val s = Str (i,(R sub i))
1678: val cnt =
1679: let val newcount = cnt + size s
1680: in if newcount > 73 then (pr "\\\n\\"; size s)
1681: else newcount
1682: end
1683: in (pr s; f (i+1,cnt))
1684: end
1685: else ()
1686: in f(0,0)
1687: end
1688: fun PrintRows i =
1689: if i < (Array.length T) then
1690: (EncaseRow (PrintRow,pr) (T sub i); PrintRows(i+1))
1691: else ()
1692: in PrintRows 0
1693: end
1694:
1695: fun access(tab, row, col) = (tab sub row) sub col
1696:
1697: (* Generate a table from an initialisation value. Won't work if the
1698: actual value contains references *)
1699: fun genTable(value, r, c) =
1700: let
1701: fun rows 0 = nil
1702: | rows m = array(c, value) :: rows(m - 1)
1703: in
1704: arrayoflist(rows r)
1705: end
1706:
1707: (* assign a table entry, using "resolve" to check it against the existing
1708: entry *)
1709: fun assign(resolve: ('entry * 'entry) -> 'entry,
1710: T: 'entry Table,
1711: Row: int, Col: int,
1712: newEntry: 'entry) =
1713: let val R = T sub Row
1714: val oldEntry = R sub Col
1715:
1716: in update(R, Col, resolve(oldEntry, newEntry))
1717: end
1718:
1719: type State = int
1720: fun showState(state: State) = makestring state
1721:
1722: (* Specific table stuff *)
1723: datatype Action = SHIFT of State
1724: | REDUCE of G.Attribute
1725: | ERROR
1726:
1727: type Prec = int option
1728: type ActionEntry = {action: Action, prec: Prec}
1729: datatype Goto = GOTO of int option
1730:
1731: exception AssignAction (* of ActionEntry * ActionEntry *)
1732: exception AssignGoto of Goto (* Returns the current entry *)
1733:
1734: (* convert integer between 0 and 65535 to a a 2 byte character
1735: string representing the integer, with low byte first *)
1736:
1737: val convert_int = fn (i:int) =>
1738: if i>(256*256-1) then
1739: let exception Convert_int in raise Convert_int end
1740: else
1741: let val make_char = fn (i:int) =>
1742: let val s = makestring i
1743: in (substring("\\000",0,1+3 + (~(size s)))) ^ s
1744: end
1745: in (make_char (i mod 256)) ^ (make_char (i div 256))
1746: end
1747:
1748: local
1749: val make_entry = fn (i,s) => (convert_int (i+1)) ^ s
1750: val showAction = fn states => fn (n : int,{action, prec}) =>
1751: case action
1752: of (REDUCE (G.ATTRIB {num,...})) =>
1753: make_entry(n,convert_int(states+num))
1754: | (SHIFT i) =>
1755: make_entry(n,convert_int(i))
1756: | ERROR => ""
1757: val showGoto =
1758: fn (n:int,(GOTO(SOME j))) =>
1759: make_entry(n,convert_int(j))
1760: | _ => ""
1761: in
1762: val printLr_Table = fn (file : outstream, gotos, actions,
1763: DisplayAttributes,states) =>
1764: let val pr = output file
1765: val prln = fn s => (pr s; pr "\n");
1766: val EncaseRow = fn (PrintRow,pr) => fn r =>
1767: (PrintRow r; pr (convert_int 0); pr "\\\n\\")
1768: val PrintTable = fn (table,entry_print) =>
1769: (pr "\"\\\n\\";
1770: PrTable (pr,table,entry_print,EncaseRow);
1771: prln "\"")
1772: in (pr "\
1773: \structure Lr_Table : MLY_LR_TABLE = \n\
1774: \ struct\n\
1775: \ structure G = G\n\
1776: \ open G\n\
1777: \\n\
1778: \ type State = int \n\
1779: \ val initialState = 0 \n\
1780: \ fun showState(state: State) = makestring state \n\
1781: \\n\
1782: \ (* Specific table stuff *) \n\
1783: \ datatype Action = SHIFT of State \n\
1784: \ | REDUCE of Attribute \n\
1785: \ | ERROR \n\
1786: \ datatype Goto = GOTO of State\n";
1787: pr "local\n\
1788: \ val string_to_int = fn(s,index) => (ordof(s,index) + \n\
1789: \ ordof(s,index+1)*256,index+2)\n";
1790: DisplayAttributes(file);
1791: pr "val numStates =";
1792: prln (makestring states);
1793: pr "\
1794: \ val convert_string_to_list = fn conv_func => fn(s,index) =>\n\
1795: \ let fun f (r,index) =\n\
1796: \ let val (num,index) = string_to_int(s,index)\n\
1797: \ in if num=0 then (rev r,index)\n\
1798: \ else let val (i,index) = string_to_int(s,index)\n\
1799: \ in f((num-1,(conv_func i))::r,index)\n\
1800: \ end\n\
1801: \ end\n\
1802: \ in f(nil,index)\n\
1803: \ end\n\
1804: \ val convert_string_to_array = fn conv_func => fn s =>\n\
1805: \ let val convert_row =convert_string_to_list conv_func\n\
1806: \ fun f(r,index) =\n\
1807: \ if (index < size s) then\n\
1808: \ let val (newlist,index) = convert_row (s,index)\n\
1809: \ in f(newlist::r,index)\n\
1810: \ end\n\
1811: \ else arrayoflist(rev r)\n\
1812: \ in f(nil,0)\n\
1813: \ end\n\
1814: \ val int_to_goto = fn i => GOTO i\n\
1815: \\n\
1816: \ val int_to_action = fn i =>\n\
1817: \ if i >= numStates then\n\
1818: \ get_attribute(i-numStates)\n\
1819: \ else SHIFT i\n\
1820: \ val make_goto_table = convert_string_to_array int_to_goto\n\
1821: \ val make_action_table=convert_string_to_array int_to_action\n";
1822: prln "in";
1823: prln "val actionT = make_action_table";
1824: PrintTable(actions,showAction states);
1825: prln "val gotoT = make_goto_table";
1826: PrintTable(gotos,showGoto);
1827: pr "\
1828: \ exception NotThere\n\
1829: \ fun find(((key:int),data)::b,i) =\n\
1830: \ if (i>key) then find(b,i)\n\
1831: \ else if (i<key) then raise NotThere\n\
1832: \ else data\n\
1833: \ | find (nil,i) = raise NotThere\n\
1834: \ fun action(state,T t) =\n\
1835: \ find(actionT sub state,t) handle NotThere => ERROR\n\
1836: \ exception Goto\n\
1837: \ fun goto(state,NT t) =\n\
1838: \ (case find(gotoT sub state,t)\n\
1839: \ of (GOTO i) => i)\n\
1840: \ handle NotThere => raise Goto\n\
1841: \ end\nend\n")
1842: end
1843: end
1844:
1845: val mktable = fn dest => fn (ALL as
1846: {rules = rules : G.Rule list, verbose=verbose : bool,
1847: eof = eof : G.Terminal, start = start: G.Nonterminal,
1848: termPrecedence = termPrecedence: G.Terminal -> int option,
1849: showTerminalClass= showTerminalClass: G.Terminal -> string,
1850: showTerminalValue=showTerminalValue : G.Terminal -> string,
1851: showNonterminal=showNonterminal : G.Nonterminal -> string,
1852: showAttribute=showAttribute : G.Attribute -> string,
1853: numTerminals=numTerminals : int,
1854: numNonterminals=numNonterminals : int
1855: }) =>
1856: let
1857: val rr_error = ref false
1858:
1859: (* DisplayAttributes: print values for the attributes of the rules,
1860: of the form a{rule #} = ATTRIB ... These values are used in
1861: the printed out version of the Action table. *)
1862:
1863: fun DisplayAttributes (f) =
1864: let val pr = (output f)
1865: in (pr
1866: "val get_attribute= \n\
1867: \ let val convert_back = fn (s,i) =>\n\
1868: \ let val (lhs,ni) = string_to_int(s,i)\n\
1869: \ val (rhsLength,ni) = string_to_int(s,ni)\n\
1870: \ val (num,ni) = string_to_int(s,ni)\n\
1871: \ in (REDUCE(G.ATTRIB{lhs=G.NT lhs,rhsLength=rhsLength,\n\
1872: \ num=num}),ni,num)\n\
1873: \ end\n\
1874: \ val numRules =";
1875: pr (makestring (List.length rules));
1876: pr "\nval attrib_data =\n\"";
1877: app(fn (G.RULE {attribute=G.ATTRIB {lhs,rhsLength,num},...}) =>
1878: (
1879: (* nonterminal number *)
1880:
1881: pr (convert_int (G.nontermHash lhs));
1882:
1883: (* rhs length *)
1884:
1885: pr (convert_int rhsLength);
1886:
1887: (* num *)
1888:
1889: pr (convert_int num);
1890: pr "\\\n\\"
1891: )) rules;
1892:
1893: pr "\"\n\
1894: \ val attrib_array = array(numRules,ERROR)\n\
1895: \ fun convert_string(s,index) =\n\
1896: \ if (index < (size s)) then\n\
1897: \ let val (result,newindex,num)=convert_back(s,index)\n\
1898: \ in (update(attrib_array,num,result);\n\
1899: \ convert_string(s,newindex))\n\
1900: \ end\n\
1901: \ else ()\n\
1902: \ in (convert_string(attrib_data,0); fn i => attrib_array sub i)\n\
1903: \ end\n";
1904: ())
1905: end
1906:
1907: val printTerminalClass = Busy.print o showTerminalClass
1908: val printNonterminal = Busy.print o showNonterminal
1909:
1910: fun srConflict(state, attrib, terminal) =
1911: (Busy.println(showState state ^ ": " ^ "shift/reduce conflict " ^
1912: "(shift " ^ (showTerminalClass terminal) ^ ",reduce " ^
1913: showAttribute attrib ^ ")")
1914: )
1915:
1916: fun precConflict(state, attrib, terminal) =
1917: (Busy.println ((showState state) ^
1918: ": terminal and rule have the same precedence for the");
1919: Busy.println ("shift/reduce conflict " ^
1920: "(shift " ^ (showTerminalClass terminal) ^ ",reduce " ^
1921: showAttribute attrib ^ ")")
1922: )
1923:
1924: fun rrConflict(a1, a2) =
1925: Busy.println("reduce/reduce conflict between "
1926: ^ showAttribute a1 ^ " and " ^ showAttribute a2
1927: )
1928: (* assign an action table entry for state on encountering terminal *)
1929:
1930: (* resolve: precedence handling was modified for nonassociative
1931: terminals. Before, if a rule's precedence was greater than a
1932: terminal's a precedence in a s/r conflict, a reduce was planted.
1933: Otherwise a shift occurred. If a rule's precedence was equal to
1934: a terminal's precedence, a shift was planted, but no warning message
1935: was printed. This does not allow for proper handling of
1936: associativities and precedence in a yacc-like parser generator.
1937:
1938: In yacc, each terminal may have a precedence and an associativity.
1939: A terminal may be left associative, right associative,
1940: or nonassociative. A rule is usually given the precedence of its
1941: rightmost terminal. We want to reduce if the precedence of the
1942: rule is > the terminal, or if the precedences are = and the terminal
1943: is left associative. We want to shift the terminal if the
1944: precedence of the terminal is higher than the rule's precedence,
1945: or if the precedences are equal and the terminal is right associative.
1946: If the precedences are equal and the terminal is nonassociative
1947: this is an error condition.
1948:
1949: We need to print a diagnostic indicating to the user when the
1950: precedences of the rule and the terminal are equal. Then we
1951: can give the rule precedence x, right associative terminals
1952: precedence x+1, left associative terminals precedence x-1, and
1953: nonassociative terminals precedence. x.
1954: *)
1955:
1956:
1957: fun assignAction(actions, state, terminal, entry) =
1958: let fun resolve ({action=ERROR, ...}, x) = x
1959: | resolve (s as {action=SHIFT _, prec=shiftPrec},
1960: r as {action=REDUCE a, prec=redPrec}) =
1961: (case (shiftPrec,redPrec)
1962: of (NONE,_) => (srConflict(state, a, terminal); s)
1963: | (_,NONE) => (srConflict(state, a, terminal); s)
1964: | (SOME (i:int),SOME j) =>
1965: if i = j then (precConflict(state, a, terminal); s)
1966: else if i > j then s
1967: else r
1968: )
1969: | resolve (r as {action=REDUCE _, ...},s as {action=SHIFT _, ...})=
1970: resolve(s,r)
1971: | resolve (r1 as {action=REDUCE a1, ...},
1972: r2 as {action=REDUCE a2, ...}) =
1973: (rrConflict(a1,a2); rr_error := true; r1)
1974: | resolve _ = let exception Resolve in raise Resolve end
1975: in assign(resolve, actions, state, G.termHash terminal, entry)
1976: end
1977:
1978: (* assign a goto entry for a state * nonterminal *)
1979: fun assignGoto(gotos, state, Nonterminal, Entry) =
1980: let fun resolve(GOTO NONE, x) = x |
1981: resolve(Old, _) = raise AssignGoto Old
1982: in
1983: assign(resolve, gotos, state, G.nontermHash Nonterminal, Entry)
1984: end
1985:
1986: (* make table entries for all the graph's edges *)
1987: fun plantEdgeMoves(actions, gotos, allEdges) =
1988: let val f =
1989: fn ({From={state=from,...},Edge,To={state=to,...}}
1990: : Graph.Lr_Graph.EdgeSet.elem) =>
1991: case Edge
1992: of G.TERM t =>
1993: assignAction(actions, from, t,
1994: {action=SHIFT to, prec=termPrecedence t})
1995: | G.NONTERM nt =>
1996: assignGoto(gotos, from, nt, GOTO(SOME to))
1997: in Graph.Lr_Graph.EdgeSet.app f allEdges
1998: end
1999:
2000: (* plant all reductions from a particular state *)
2001: fun plantReductions actions (state,r) =
2002: let val {cores, state} = state
2003:
2004: (* plant a reduction for a core item if the dot is at the end of
2005: the item *)
2006:
2007: val plantReduction =
2008: fn Utils.CORE {coreRHSafter=nil,lookaheads,
2009: I={corePrecedence, coreAttribute, ...},
2010: ...} =>
2011:
2012: (* plant a reduction for each terminal in the
2013: lookahead set *)
2014:
2015: List.app (fn lookahead =>
2016: assignAction(actions,state,lookahead,
2017: {action=REDUCE coreAttribute,
2018: prec=corePrecedence})
2019: ) (Utils.Lset.makelookaheadlist (!lookaheads))
2020:
2021: | _ => ()
2022: val closuredCores = (* coreClosure *) cores
2023:
2024: in (Busy.sendto_list();
2025: Utils.CoreSet.app plantReduction closuredCores;
2026: case Busy.get_list()
2027: of nil => r
2028: | l => (state,l)::r)
2029: end
2030:
2031: (* plant all reductions for all states *)
2032:
2033: fun plantStates(actions: ActionEntry Table,
2034: states: Graph.Lr_Graph.node list) =
2035: List.fold (fn (state,r) => (plantReductions actions) (state,r))
2036: states nil;
2037:
2038: (* Generate graph *)
2039:
2040: val graph = Graph.mkGraph ALL;
2041: val theNodes = Graph.Lr_Graph.nodes_of graph
2042: val theEdges = Graph.Lr_Graph.all_edges graph
2043: val numNodes = Graph.Lr_Graph.num_nodes graph
2044:
2045: val actions=genTable({action=ERROR,prec=NONE},numNodes, numTerminals)
2046: val gotos = genTable(GOTO NONE, numNodes, numNonterminals)
2047:
2048: in (Busy.println "Filling Tables";
2049: if verbose then
2050: (let val outfile = open_out "y.output"
2051: val allerrs = (plantEdgeMoves(actions,gotos,theEdges);
2052: plantStates(actions,theNodes))
2053: val errmsgs = fn state =>
2054: fold (fn ((s,l),r) => if s=state then l::r else r) allerrs
2055: nil
2056: val _ = Busy.sendto_file outfile
2057: val printCore = Utils.printCore
2058: {showSymbol = (Utils.mkshowSymbol
2059: ({showTerminalClass=showTerminalClass,
2060: showNonterminal=showNonterminal})
2061: ),
2062: showTerminalClass = showTerminalClass,
2063: showNonterminal = showNonterminal
2064: }
2065: val printCores = fn (state : int,cores) =>
2066: Utils.CoreSet.app (fn a =>
2067: let val (Utils.CORE c) = a
2068: val {coreRHSafter,
2069: I = {coreLHS,
2070: coreAttribute=Utils.G.ATTRIB {num, ...},
2071: ...},
2072: ...
2073: } = c
2074: in (Busy.print "\t";
2075: printCore a;
2076: case coreRHSafter
2077: of nil => Busy.println (" (reduce by rule "^
2078: (makestring num) ^ ")")
2079: | _ => Busy.println ""
2080: )
2081: end) cores
2082:
2083: val printActions = fn (state : int) =>
2084: let fun f i =
2085: if i < numTerminals then
2086: (case (#action(access(actions,state, i)))
2087: of SHIFT s =>
2088: Busy.println ("\t" ^
2089: (showTerminalClass (G.T i)) ^
2090: "\tshift " ^ (showState s))
2091: | REDUCE (G.ATTRIB {lhs,num,...}) =>
2092: Busy.println ("\t" ^ (showTerminalClass (G.T i))^
2093: "\treduce by rule " ^
2094: (makestring num))
2095: | ERROR => ();
2096: f (i+1))
2097: else ()
2098: fun g i =
2099: if i < numNonterminals then
2100: (case access(gotos, state, i)
2101: of GOTO(SOME s) =>
2102: Busy.println("\t" ^(showNonterminal (G.NT i))^
2103: "\tgoto " ^ (showState s))
2104: | _ => ();
2105: g (i+1))
2106: else ()
2107: in (f 0; g 0)
2108: end
2109: fun print_state a =
2110: let val {state,cores} = a
2111: val cores = (* coreClosure *) cores
2112: in
2113: (Busy.println "";
2114: revapp (revapp Busy.print) (errmsgs state);
2115: Busy.println "";
2116: Busy.println(" state " ^ (makestring state) ^
2117: ":");
2118: Busy.println "";
2119: printCores(state,cores);
2120: Busy.println "";
2121: printActions(state)
2122: )
2123: end
2124:
2125: fun find_state n =
2126: let fun f(a::b) =
2127: let val {state,cores} = a
2128: in if state=n then a else f b
2129: end
2130: in f theNodes
2131: end
2132: fun all_states () =
2133: let fun f i = if i<numNodes then
2134: (print_state (find_state i); f (i+1))
2135: else ()
2136: in f 0
2137: end
2138: in all_states();
2139: Busy.sendto_file std_out;
2140: close_out outfile
2141: end)
2142: else(plantEdgeMoves(actions, gotos,theEdges);
2143: let val errs = (plantStates(actions,theNodes))
2144: in (Busy.sendto_file std_out;
2145: revapp (fn (_,s) => map Busy.print s) errs)
2146: end
2147: );
2148:
2149: if (!rr_error) then raise AssignAction
2150: else printLr_Table(dest,gotos,actions,DisplayAttributes,numNodes)
2151: )
2152: end
2153: end;
2154: structure MLY_MAKE_PARSER =
2155: struct
2156: val print_parser = fn pr => pr
2157: "\
2158: \\n\
2159: \\n\
2160: \signature MLY_GRAMMAR =\n\
2161: \ sig\n\
2162: \ type Terminal\n\
2163: \ type Nonterminal\n\
2164: \ datatype Symbol = TERM of Terminal | NONTERM of Nonterminal\n\
2165: \\n\
2166: \ datatype Attribute = ATTRIB of {lhs:Nonterminal,rhsLength:int,num: int }\n\
2167: \\n\
2168: \ val showTerminalClass : Terminal -> string\n\
2169: \ val showTerminalValue: Terminal -> string\n\
2170: \ val showNonterminal : Nonterminal -> string\n\
2171: \ val eqNonterminal : Nonterminal * Nonterminal -> bool\n\
2172: \ val eqTerminal : Terminal * Terminal -> bool\n\
2173: \\n\
2174: \ type Lineno\n\
2175: \ val lineno : Lineno ref\n\
2176: \ val error: string -> Lineno -> unit\n\
2177: \\n\
2178: \ val ErrTermList : Terminal list\n\
2179: \ val preferred_subst : Terminal -> Terminal list\n\
2180: \ val is_keyword : Terminal -> bool\n\
2181: \ val preferred_insert : Terminal -> bool\n\
2182: \ val eof : Terminal\n\
2183: \ val start : Nonterminal\n\
2184: \ end\n\
2185: \\n\
2186: \signature MLY_LR_TABLE =\n\
2187: \ sig\n\
2188: \ structure G : MLY_GRAMMAR\n\
2189: \ \n\
2190: \ type State\n\
2191: \ val initialState: State\n\
2192: \ val showState: State -> string\n\
2193: \\n\
2194: \ datatype Action = SHIFT of State | REDUCE of G.Attribute | ERROR\n\
2195: \ val action: State * G.Terminal -> Action\n\
2196: \ val actionT : (int * Action) list array\n\
2197: \ val goto: State * G.Nonterminal -> State\n\
2198: \ end\n\
2199: \\n\
2200: \signature MLY_ACTIONS = \n\
2201: \ sig \n\
2202: \ type Value\n\
2203: \ val ErrValList : Value list\n\
2204: \ val VOID : Value\n\
2205: \ val rule : (int * Value list) -> (Value * Value list)\n\
2206: \ end\n\
2207: \\n\
2208: \\n\
2209: \signature MLY_PARSER =\n\
2210: \ sig\n\
2211: \ structure A: MLY_GRAMMAR\n\
2212: \ structure B: MLY_ACTIONS\n\
2213: \ val parse: (unit -> A.Terminal * B.Value) -> (int*int) -> B.Value\n\
2214: \ end;\n\
2215: \\n\
2216: \functor ParserGen(structure Lr_Table : MLY_LR_TABLE\n\
2217: \ structure RuleAction: MLY_ACTIONS\n\
2218: \ ) : MLY_PARSER =\n\
2219: \ struct\n\
2220: \ structure A = Lr_Table.G\n\
2221: \ structure B = RuleAction\n\
2222: \ open Lr_Table RuleAction Lr_Table.G\n\
2223: \ exception Error\n\
2224: \ val DEBUG = false\n\
2225: \\n\
2226: \ \n\
2227: \\n\
2228: \ exception Joinlists\n\
2229: \\n\
2230: \ val TestLexVList = \n\
2231: \ let fun f(a::a',b::b',r) = f(a',b',(a,b)::r)\n\
2232: \ | f(nil,nil,r) = rev r\n\
2233: \ | f _ = raise Joinlists\n\
2234: \ in f(ErrTermList,ErrValList,nil)\n\
2235: \ end\n\
2236: \\n\
2237: \ type Element = { term : G.Terminal, value : Value, stack : State list,\n\
2238: \ def_reduces : G.Attribute list, lineno : G.Lineno}\n\
2239: \\n\
2240: \ local \n\
2241: \ val print = output std_out\n\
2242: \ val println = fn s => (print s; print \"\\n\")\n\
2243: \ in\n\
2244: \ fun printStack(stack: State list, n: int) =\n\
2245: \ case stack\n\
2246: \ of (state) :: rest =>\n\
2247: \ (print(\" \" ^ makestring n ^ \": \");\n\
2248: \ println(showState state);\n\
2249: \ printStack(rest, n+1)\n\
2250: \ )\n\
2251: \ | nil => ()\n\
2252: \ \n\
2253: \ fun prAction(stack as (state) :: _, next, action) =\n\
2254: \ (println \"Parse: state stack:\";\n\
2255: \ printStack(stack, 0);\n\
2256: \ print(\" state=\"\n\
2257: \ ^ showState state \n\
2258: \ ^ \" next=\"\n\
2259: \ ^ showTerminalClass next\n\
2260: \ ^ \" action=\"\n\
2261: \ );\n\
2262: \ case action\n\
2263: \ of SHIFT state' =>\n\
2264: \ println(\"SHIFT \" ^ showState state')\n\
2265: \ | REDUCE(ATTRIB{lhs, ...}) =>\n\
2266: \ println(\"REDUCE \" ^ showNonterminal lhs)\n\
2267: \ | ERROR =>\n\
2268: \ println \"ERROR\";\n\
2269: \ action\n\
2270: \ )\n\
2271: \ | prAction (_,_,action) = action\n\
2272: \ end\n\
2273: \\n\
2274: \ \n\
2275: \\n\
2276: \ val pr_errln = error\n\
2277: \ val pr_err = error\n\
2278: \ \n\
2279: \\n\
2280: \ \n\
2281: \\n\
2282: \ fun parse lexer (MaxLookAhead,Size) = \n\
2283: \ let exception Remove\n\
2284: \ val MaxLookAhead = max(0,MaxLookAhead) \n\
2285: \ val Size = max(0,Size)\n\
2286: \\n\
2287: \ val ls = (ref nil) : ((Terminal * Value) * Lineno) list ref\n\
2288: \\n\
2289: \ val lexer = fn () =>\n\
2290: \ case (!ls) of\n\
2291: \ nil => (lexer(),!lineno)\n\
2292: \ | a::b => (ls := b; a)\n\
2293: \\n\
2294: \ \n\
2295: \\n\
2296: \ fun print_lookahead () = \n\
2297: \ (app (fn ((a:Terminal,_),_) => (print (showTerminalClass a); print \" \")) (!ls);\n\
2298: \ print \"\\n\")\n\
2299: \\n\
2300: \ fun remove (0,s) = s\n\
2301: \ | remove (n,a::b) = remove(n-1,b)\n\
2302: \ | remove _ = raise Remove\n\
2303: \\n\
2304: \ exception ParseStep\n\
2305: \ val FixError = ParseStep\n\
2306: \ exception psRemoveBind\n\
2307: \\n\
2308: \ exception Reduce\n\
2309: \\n\
2310: \ fun reduce(l,vs) =\n\
2311: \ fold (fn (ATTRIB{rhsLength,num,...},vs) =>\n\
2312: \ let val (nv,vs) = rule (num,vs)\n\
2313: \ in nv::vs\n\
2314: \ end) l vs\n\
2315: \\n\
2316: \\n\
2317: \ \n\
2318: \\n\
2319: \ fun fix_error(ss as (topstate :: _ ) : State list ,\n\
2320: \ (vs,oss) : (Value list * State list),\n\
2321: \ queue as (x,y) : (Element list * Element list),\n\
2322: \ reductions : G.Attribute list,\n\
2323: \ lexv as ((term,value),lineno),\n\
2324: \ c : int,\n\
2325: \ min_advance : int,\n\
2326: \ max_advance : int) =\n\
2327: \ let\n\
2328: \\n\
2329: \ val _ = pr_errln(\"syntax error found at \" ^\n\
2330: \ (showTerminalClass term)) lineno\n\
2331: \\n\
2332: \ val min_delta = 3\n\
2333: \\n\
2334: \ \n\
2335: \\n\
2336: \ val toklist = x@(rev ({term=term,value=value,lineno=lineno,\n\
2337: \ stack=oss,def_reduces=nil}::y))\n\
2338: \\n\
2339: \ \n\
2340: \\n\
2341: \ datatype Oper = INSERT | DELETE | SUBST of Terminal\n\
2342: \ datatype Change = CHANGE of {pos : int, distance : int,\n\
2343: \ term : Terminal, value : Value,\n\
2344: \ oper : Oper,lineno : Lineno}\n\
2345: \\n\
2346: \ val print_change = fn (CHANGE {pos,distance,term,value,oper,lineno}) =>\n\
2347: \ (print (\"{ pos= \" ^ (makestring pos));\n\
2348: \ print (\" dis= \" ^ (makestring distance));\n\
2349: \ print (\" term = \" ^ (showTerminalClass term));\n\
2350: \ print (\"oper= \" ^ (case oper\n\
2351: \ of INSERT => \"INSERT \"\n\
2352: \ | SUBST _ => \"SUBST \"\n\
2353: \ | DELETE => \"DELETE \"));\n\
2354: \\n\
2355: \ print \"}\\n\")\n\
2356: \\n\
2357: \ val print_cl = map print_change\n\
2358: \\n\
2359: \ \n\
2360: \\n\
2361: \ val ExtraTokens =\n\
2362: \ let fun f (t,0) = rev t\n\
2363: \ | f (t,n) =\n\
2364: \ let val (lexval as ((term,_),_)) = lexer()\n\
2365: \ in f(lexval::t,\n\
2366: \ if eqTerminal(term,eof) then 0 else n-1)\n\
2367: \ end\n\
2368: \ in f(nil,max_advance)\n\
2369: \ end\n\
2370: \\n\
2371: \ \n\
2372: \ \n\
2373: \\n\
2374: \ val LexValueList =\n\
2375: \ (map (fn ({term, value,lineno, ...} : Element) =>\n\
2376: \ ((term,value),lineno))\n\
2377: \ toklist) @ (ExtraTokens)\n\
2378: \\n\
2379: \ val TermList = map (fn ((a,_),l) => (a,l)) LexValueList\n\
2380: \\n\
2381: \ \n\
2382: \\n\
2383: \ exception parseTest\n\
2384: \ exception parseRemoveBind\n\
2385: \\n\
2386: \ fun parse (ss as (s :: _),tokenlist) =\n\
2387: \ (case tokenlist\n\
2388: \ of nil => 0\n\
2389: \ | (e as (a, _ ))::b => \n\
2390: \ (case Lr_Table.action(s,a)\n\
2391: \ of ERROR => length tokenlist\n\
2392: \ | (SHIFT s) => parse(s::ss,b)\n\
2393: \ | (REDUCE (ATTRIB {lhs,rhsLength, ...})) =>\n\
2394: \\n\
2395: \ \n\
2396: \\n\
2397: \ if eqNonterminal(lhs,start) then ~1\n\
2398: \ else case remove(rhsLength,ss)\n\
2399: \ of (ns as (ts :: _ )) =>\n\
2400: \ parse(goto(ts,lhs)::ns,e::b)\n\
2401: \ | _ => raise parseRemoveBind\n\
2402: \ )\n\
2403: \ )\n\
2404: \ | parse _ = raise parseTest\n\
2405: \\n\
2406: \ exception Rev_queue_fold\n\
2407: \\n\
2408: \ \n\
2409: \\n\
2410: \ fun rev_queue_fold (queue : 'b list,toklist : 'c list)\n\
2411: \ (g : (int * 'a * 'b list * 'c list) -> 'a)\n\
2412: \ (start : 'a) =\n\
2413: \\n\
2414: \ let fun f(count,results,nil,_) = results\n\
2415: \ | f(count,results,queue as (q :: q'),toklist as (t :: t')) = \n\
2416: \ f(count+1,g(count,results,queue,toklist),q',t')\n\
2417: \ | f _ = raise Rev_queue_fold\n\
2418: \ in f(0,start,queue,toklist)\n\
2419: \ end\n\
2420: \\n\
2421: \\n\
2422: \ \n\
2423: \\n\
2424: \ fun test (new_token_list :\n\
2425: \ (Terminal * Lineno) * ((Terminal * Lineno) list) ->\n\
2426: \ ((Terminal * Lineno) list),\n\
2427: \ oper : Oper) =\n\
2428: \ let fun test' (count,results, ({stack, ...} : Element) :: _,\n\
2429: \ tl as ((_,lineno) :: _)) =\n\
2430: \ List.fold (fn ((a,v),r) =>\n\
2431: \ let val tokens_left = parse(stack,new_token_list((a,lineno),tl))\n\
2432: \ in if tokens_left > (max_advance - min_advance) then r\n\
2433: \ else (CHANGE {pos=count,term=a,value=v,distance=tokens_left,\n\
2434: \ oper = oper,lineno=lineno})::r\n\
2435: \ end) TestLexVList results\n\
2436: \ in rev_queue_fold (toklist,TermList) test' nil\n\
2437: \ end\n\
2438: \ \n\
2439: \ val SubstChanges =\n\
2440: \ let fun test (count,results,({stack, term, ...} : Element) :: _,\n\
2441: \ (_,lineno) :: rest) =\n\
2442: \ let val max_left = max_advance - min_advance\n\
2443: \ in List.fold (fn ((a,v),r) =>\n\
2444: \ let val tokens_left = parse(stack,(a,lineno)::rest)\n\
2445: \ in if tokens_left > max_left then r\n\
2446: \ else (CHANGE {pos=count,term=a,value=v,distance=tokens_left,\n\
2447: \ oper=SUBST term,lineno=lineno})::r\n\
2448: \ end) TestLexVList results\n\
2449: \ end\n\
2450: \ in rev_queue_fold (toklist,TermList) test nil\n\
2451: \ end\n\
2452: \\n\
2453: \ val DeleteChanges = \n\
2454: \ let fun test(count,results,({term,value,stack, ...} : Element) :: _,\n\
2455: \ termlist as ((_,lineno) :: rest)) =\n\
2456: \ let val tokens_left = parse(stack,rest)\n\
2457: \ in if tokens_left > (max_advance - min_advance) then\n\
2458: \ results\n\
2459: \ else (CHANGE {pos=count,distance=tokens_left,term=term,\n\
2460: \ value=value,oper=DELETE,lineno=lineno}) :: results\n\
2461: \ end\n\
2462: \ in rev_queue_fold (toklist,TermList) test nil\n\
2463: \ end\n\
2464: \\n\
2465: \ val InsertChanges =\n\
2466: \ test ((fn (a,rest) => a::rest),INSERT)\n\
2467: \\n\
2468: \\n\
2469: \\n\
2470: \ local\n\
2471: \\n\
2472: \ fun sieve(a as (CHANGE {distance, ...}),b as (min,results)) =\n\
2473: \ if min>distance then (distance,[a])\n\
2474: \ else if min=distance then (min,a::results)\n\
2475: \ else b\n\
2476: \\n\
2477: \ fun sieve_list l = List.fold sieve l (max_advance,nil)\n\
2478: \\n\
2479: \ in\n\
2480: \\n\
2481: \ val (min1,DeleteChanges) = sieve_list DeleteChanges\n\
2482: \ val (min2,SubstChanges) = sieve_list SubstChanges\n\
2483: \ val (min3,InsertChanges) = sieve_list InsertChanges\n\
2484: \\n\
2485: \ val min0 = min(min(min1,min2),min3)\n\
2486: \\n\
2487: \ val DeleteChanges = if min1>min0 then nil else DeleteChanges\n\
2488: \ val SubstChanges = if min2>min0 then nil else SubstChanges\n\
2489: \ val InsertChanges = if min3>min0 then nil else InsertChanges\n\
2490: \\n\
2491: \ end\n\
2492: \\n\
2493: \ val _ = if DEBUG then\n\
2494: \ (print_cl InsertChanges; print_cl DeleteChanges;\n\
2495: \ print_cl SubstChanges; ())\n\
2496: \ else ()\n\
2497: \\n\
2498: \\n\
2499: \\n\
2500: \ val (InsertChanges,t) =\n\
2501: \ List.fold (fn (a as (CHANGE {term, ...}),(r,t)) => \n\
2502: \ if preferred_insert term then \n\
2503: \ if t then (a::r,t) else ([a],true)\n\
2504: \ else if t then (r,t) else (a::r,t)\n\
2505: \ ) InsertChanges (nil,false)\n\
2506: \\n\
2507: \ val (SubstChanges,t') =\n\
2508: \ List.fold (fn (a as (CHANGE {term=term,oper=SUBST t', ...}),(r,t)) =>\n\
2509: \ if List.exists (fn a=>eqTerminal(a,term)) (preferred_subst t') then\n\
2510: \ if t then (a::r,t) else ([a],true)\n\
2511: \ else if t then (r,t) else (a::r,t)\n\
2512: \ | (a,(r,t)) => (a::r,t) \n\
2513: \ ) SubstChanges (nil,false)\n\
2514: \\n\
2515: \\n\
2516: \\n\
2517: \ local val max_tokens = max_advance - (min_advance+min_delta)\n\
2518: \\n\
2519: \ val remove_keywords = fn l =>\n\
2520: \ List.fold (fn (a as (CHANGE {term,distance,...}),r) =>\n\
2521: \ if (is_keyword term) andalso (distance > max_tokens) then\n\
2522: \ r\n\
2523: \ else a::r) l nil\n\
2524: \\n\
2525: \ in\n\
2526: \\n\
2527: \ val InsertChanges =\n\
2528: \ if t then InsertChanges else remove_keywords InsertChanges\n\
2529: \ \n\
2530: \ val DeleteChanges = remove_keywords DeleteChanges\n\
2531: \\n\
2532: \ val SubstChanges =\n\
2533: \ if t' then SubstChanges else remove_keywords SubstChanges\n\
2534: \\n\
2535: \ end\n\
2536: \ val MinChanges =\n\
2537: \ let val ic = length InsertChanges\n\
2538: \ and dc = length DeleteChanges\n\
2539: \ and sc = length SubstChanges\n\
2540: \ in if ic=1 then SOME InsertChanges\n\
2541: \ else if dc=1 then SOME DeleteChanges\n\
2542: \ else if sc=1 then SOME SubstChanges\n\
2543: \ else if (min0 > (max_advance-(min_advance+min_delta))\n\
2544: \ orelse (ic+dc+sc)=0)\n\
2545: \ then NONE\n\
2546: \ else SOME (InsertChanges @ DeleteChanges @ SubstChanges)\n\
2547: \ end\n\
2548: \\n\
2549: \\n\
2550: \in case MinChanges \n\
2551: \ of (SOME l) =>\n\
2552: \ let fun print_msg (CHANGE {term, oper, lineno, ...}) =\n\
2553: \\n\
2554: \ let val s = \n\
2555: \ case oper\n\
2556: \ of DELETE => \"deleting \"\n\
2557: \ | INSERT => \"inserting \"\n\
2558: \ | SUBST t => \"replacing \" ^ (showTerminalClass t) ^\n\
2559: \ \" with \"\n\
2560: \ in pr_errln (s ^ (showTerminalClass term)) lineno\n\
2561: \ end\n\
2562: \ \n\
2563: \ val a = \n\
2564: \ if (length l > 1)\n\
2565: \ then (\n\
2566: \ if DEBUG then\n\
2567: \ (pr_errln \"multiple fixes possible: could fix it by\" lineno;\n\
2568: \ map print_msg l;\n\
2569: \ pr_errln \"fixing it with\" lineno\n\
2570: \ )\n\
2571: \ else ();\n\
2572: \ print_msg (hd l);\n\
2573: \ (hd l))\n\
2574: \ else (print_msg (hd l); (hd l))\n\
2575: \\n\
2576: \ val pos = (fn (CHANGE {pos, ...}) => pos) a\n\
2577: \ \n\
2578: \ fun f(0,q,termlist,rq',CHANGE {oper,term,value, lineno,\n\
2579: \ ...}) =\n\
2580: \ let val ({stack, ...} : Element) = hd(q)\n\
2581: \ in\n\
2582: \ (case oper\n\
2583: \ of DELETE =>\n\
2584: \ if eqTerminal(term,eof) then\n\
2585: \ (pr_errln \"EOF encountered: goodbye!\" lineno;\n\
2586: \ raise FixError)\n\
2587: \ else ls := (tl termlist) @ (!ls)\n\
2588: \ | (SUBST _) =>\n\
2589: \ ls := (((term,value),lineno)::(tl termlist)) @ (!ls)\n\
2590: \ | INSERT =>\n\
2591: \ ls := (((term,value),lineno)::termlist) @ (!ls));\n\
2592: \ parse_step(stack,(vs,stack),(rev rq',nil),nil,lexer(),\n\
2593: \ Size-pos)\n\
2594: \ end\n\
2595: \ | f(n,e :: r, _ :: termlist, rq',change) =\n\
2596: \ f(n-1,r,termlist,e::rq',change)\n\
2597: \ in f(pos,toklist,LexValueList,nil,a)\n\
2598: \ end\n\
2599: \ | NONE => if eqTerminal(term,eof) then\n\
2600: \ (pr_errln \"EOF encountered: goodbye!\" lineno;\n\
2601: \ raise FixError)\n\
2602: \ else\n\
2603: \ (raise FixError\n\
2604: \\n\
2605: \)\n\
2606: \ end\n\
2607: \\n\
2608: \ | fix_error _ = raise FixError\n\
2609: \ \n\
2610: \ and parse_step(ss as (topstate :: _ ),\n\
2611: \ v as (vs,oss),queue as (x,y),reductions,\n\
2612: \ lexv as ((term,value),lineno),c) =\n\
2613: \ (case (if DEBUG then prAction(ss, term,\n\
2614: \ Lr_Table.action (topstate,term))\n\
2615: \ else Lr_Table.action (topstate,term))\n\
2616: \ of SHIFT s =>\n\
2617: \ let val ss = s::ss\n\
2618: \ val ny = {value=value,def_reduces=reductions,\n\
2619: \ term=term,stack=oss,lineno=lineno}::y\n\
2620: \\n\
2621: \ in if c > 0 then\n\
2622: \ parse_step(ss,(vs,ss),(x,ny),nil,lexer(),c-1)\n\
2623: \ else (case x of nil =>\n\
2624: \ let val ({value,def_reduces, ...}::nx) = rev ny\n\
2625: \ in parse_step(ss,(value::(reduce(def_reduces,vs)),ss),\n\
2626: \ (nx,nil),nil, lexer(),c)\n\
2627: \ end\n\
2628: \ | ({value,def_reduces, ...}::b) =>\n\
2629: \ parse_step(ss,(value::(reduce(def_reduces,vs)),ss),\n\
2630: \ (b,ny),nil,lexer(),c))\n\
2631: \ end\n\
2632: \ | REDUCE (r as (ATTRIB {lhs,rhsLength , ...})) =>\n\
2633: \ if eqNonterminal(lhs,start) then\n\
2634: \ hd(reduce(r::reductions,\n\
2635: \ fold (fn ({value,def_reduces, ...} : Element,vs) =>\n\
2636: \ value::(reduce(def_reduces,vs))) (y@(rev x)) vs))\n\
2637: \ else (\n\
2638: \ case (remove(rhsLength,ss)) \n\
2639: \ of (ss as (ts :: _)) =>\n\
2640: \ (\n\
2641: \\n\
2642: \ parse_step(goto(ts,lhs)::ss,v,queue,\n\
2643: \ r::reductions,lexv,c)\n\
2644: \ )\n\
2645: \ | _ => raise psRemoveBind\n\
2646: \ )\n\
2647: \ \n\
2648: \ | ERROR => fix_error(ss,v,queue,reductions,lexv,c,1,MaxLookAhead))\n\
2649: \ | parse_step _ = raise ParseStep\n\
2650: \ in parse_step([initialState],(nil,[initialState]),\n\
2651: \ (nil,nil),nil,lexer(),Size) \n\
2652: \ end\n\
2653: \end\n\
2654: \"
2655: end
2656: structure Misc =
2657: struct
2658: structure G : V2_LR_GRAMMAR =
2659: struct
2660: datatype Terminal = T of int
2661: and Nonterminal = NT of int
2662:
2663: datatype Symbol = TERM of Terminal
2664: | NONTERM of Nonterminal
2665:
2666: datatype Attribute = ATTRIB of { lhs : Nonterminal,
2667: rhsLength : int,
2668: num : int
2669: }
2670: datatype Rule = RULE of {lhs : Nonterminal,
2671: rhs : Symbol list,
2672: attribute : Attribute,
2673: precedence : int option
2674: }
2675:
2676: val termHash = fn (T i) => i
2677: val nontermHash = fn (NT i) => i
2678: val eqTerminal = fn ((T i),(T i')) => i = i'
2679: val eqNonterminal = fn ((NT i),(NT i')) => i = i'
2680:
2681: val gtTerminal = fn ((T i),(T i')) => i > i'
2682: val gtNonterminal = fn ((NT i),(NT i')) => i > i'
2683: end
2684:
2685: structure MakeTable = V2_TableGen(structure G = G)
2686:
2687: type Lineno = int
2688: val lineno = ref 1
2689: val infile = ref "";
2690:
2691: val error = fn t => fn (l : Lineno) =>
2692: (output std_out ((!infile) ^ ", line " ^
2693: (makestring l) ^ ": " ^ t ^ "\n"))
2694:
2695: datatype LexValue = LEFT | RIGHT | NONASSOC
2696:
2697: type symbol = string
2698: type constr = string
2699: type ty = string list option
2700: type constr_data = {ty: ty,num : int}
2701:
2702: structure PrecSet = FullSet(struct
2703: type elem = (symbol * (int*LexValue))
2704: val gt = fn ((a:string,_),(a',_)) => a > a'
2705: val eq = fn ((a:string,_),(a',_)) => a = a'
2706: end
2707: )
2708:
2709: structure ConstrSet = FullSet(struct
2710: type elem = (constr * {ty : ty, num : int})
2711: val gt = fn ((a:string,_),(a',_)) => a > a'
2712: val eq = fn ((a:string,_),(a',_)) => a = a'
2713: end)
2714:
2715: type decl_data = {start : symbol option,
2716: prec : { d : PrecSet.set,
2717: h : int} option,
2718: nonterm : ConstrSet.set option,
2719: term : ConstrSet.set option,
2720: eof : symbol option,
2721: prefer : (symbol*symbol) list,
2722: iprefer : symbol list,
2723: keyword : symbol list,
2724: structure' : symbol option,
2725: verbose : bool}
2726:
2727: type rhs_data = {rhs:symbol list, code:string, prec: symbol option} list
2728: type rule = { lhs : symbol, rhs : symbol list,
2729: code : string, prec : symbol option }
2730:
2731: val out = ref std_out;
2732:
2733: val len = ref 0
2734: val indent = ref 0
2735: val tw = 4
2736: val inc_margin = fn () => indent := (!indent)+tw
2737: val dec_margin = fn () => indent := (!indent)-tw
2738: val reset_margin = fn () => indent := tw
2739: val err_flag = ref false
2740: (* The next line is bogus, it gets the wrong value of lineno *)
2741: val errmsg = fn x => (err_flag := true; error x (!lineno))
2742: val errln = errmsg
2743:
2744: val say = fn x => output (!out) x
2745:
2746: fun newln () =
2747: let fun f i = if i > 0 then (say " "; f (i-1)) else ()
2748: in (say "\n"; len := (!indent); f(!indent))
2749: end
2750:
2751: val sayln = fn (x : string) =>
2752: let val wl = size x
2753: val new_count = !len + wl
2754: in if (!len = 0 orelse new_count < 78)
2755: then (say x; newln())
2756: else (newln(); say x; newln())
2757: end
2758:
2759: val saywd = fn x : string =>
2760: let val wl = size x
2761: val new_count = !len + wl
2762: in if (!len = 0 orelse new_count < 78)
2763: then (len := new_count; say x)
2764: else (newln(); len := (!len) + wl; say x)
2765: end
2766:
2767: local
2768: fun add_nums(nil,i) = nil
2769: | add_nums ((c,{ty=t, ...} : constr_data)::r,i) =
2770: (c,{ty=t,num=i}) :: add_nums(r,i+1)
2771: in
2772: fun make_tok_dict (l as (_ :: _)) = SOME (ConstrSet.make_set (add_nums(l,0)))
2773: | make_tok_dict nil = NONE
2774: end
2775:
2776: fun save_prec (l as (_::_),parity) =
2777: SOME {d= PrecSet.make_set (map (fn a => (a,(1,parity))) l), h=3}
2778: | save_prec _ = NONE
2779:
2780: fun join_decls {start=a, prec=b, nonterm=c, term=d,eof=e,
2781: iprefer=f,prefer=g,keyword=h,structure'=k,verbose=verbose}
2782: {start=a',prec=b',nonterm=c',term=d',eof=e',
2783: iprefer=f',prefer=g',keyword=h',structure'=k',
2784: verbose=verbose'} =
2785:
2786: let fun j (f,NONE,NONE) = NONE
2787: | j (f,a,NONE) = a
2788: | j (f,NONE,a) = a
2789: | j (f,SOME i,SOME j) = f(i,j)
2790:
2791: fun join e = fn(i,j) =>
2792: (errln ("ignoring duplicate "^e^" declaration"); SOME i)
2793:
2794: fun join_prec({d=t,h=h},{d=t',h=h'}) =
2795: let fun f ((e as (a,(_,p))),t) =
2796: if (PrecSet.exists e t) then
2797: (errln ("ignoring duplicate %prec definition of" ^ a); t)
2798: else (PrecSet.insert (a,(h+1,p)) t)
2799: in SOME {d = PrecSet.setfold f t' t,h=h+3}
2800: end
2801:
2802: in {start= j (join "start",a,a'),
2803: prec=j (join_prec,b,b'),
2804: term = j (join "%term",d,d'),
2805: nonterm = j (join "%nonterm",c,c'),
2806: eof = j (join "%eof",e,e'),
2807: iprefer=f'@f,
2808: prefer=g'@g,
2809: keyword=h'@h,
2810: structure' = j (join "%structure",k,k'),
2811: verbose = verbose orelse verbose'}
2812: end
2813:
2814: local fun print_bool_case (l : string list) =
2815: (sayln "fn t => ";
2816: sayln "case t";
2817: saywd "of ";
2818: List.app (fn s => (saywd s; sayln " => true"; saywd " | ")) l;
2819: sayln "_ => false"
2820: )
2821:
2822: in fun print_is_keyword_func (l : string list) =
2823: (sayln "val is_keyword =";
2824: print_bool_case l)
2825:
2826: and print_preferred_insert_func (l : string list) =
2827: (sayln "val preferred_insert =";
2828: print_bool_case l)
2829:
2830: and print_preferred_subst_func (l : (string*(string list)) list) =
2831: (sayln "val preferred_subst = fn t =>";
2832: sayln "case t";
2833: saywd "of ";
2834: List.app (fn (a,l') =>
2835: (saywd a; saywd " => ";
2836: List.app (fn s => (saywd s; saywd "::")) l';
2837: sayln "nil"; saywd "| "
2838: )
2839: ) l;
2840: sayln " _ => nil"
2841: )
2842: end
2843:
2844: fun printConstrSet(constr_set,name,only_with_values) =
2845: let val _ = (inc_margin(); inc_margin(); inc_margin();
2846: saywd ("datatype " ^ name ^ " = "))
2847: val printed_something =
2848: ConstrSet.revsetfold (fn ((s,{ty=d,...}),result) =>
2849: (if only_with_values then
2850: (case d
2851: of NONE => result
2852: | SOME t =>
2853: (if result then saywd " | " else ();
2854: saywd s;
2855: saywd " of ";
2856: List.app saywd t;
2857: true
2858: )
2859: )
2860: else
2861: (if result then saywd " | " else ();
2862: saywd s;
2863: case d
2864: of NONE => ()
2865: | SOME t => (saywd " of "; List.app saywd t);
2866: true
2867: )
2868: )
2869: ) constr_set false;
2870: in (dec_margin(); dec_margin(); dec_margin(); sayln "";
2871: printed_something)
2872: end
2873:
2874: fun PrConstructors(n,t) =
2875: (saywd ("datatype "^n^ " = ");
2876: ConstrSet.revsetfold( fn ((s,_),r) =>
2877: (if r then saywd " | " else (); saywd s; true)) t false;
2878: newln())
2879:
2880: val make_parser = fn (HEADER : string, MPC_DECLS : decl_data,
2881: TRULELIST : rule list) =>
2882: (let exception SemanticError
2883: in let val ({start=start,prec=p,nonterm=nt,term=t,eof=eof,
2884: prefer=prefer,iprefer=iprefer,keyword=keyword,
2885: structure'=structure',verbose=verbose}) = MPC_DECLS
2886:
2887: val p = case p of NONE => PrecSet.empty | SOME {d,h} => d
2888:
2889: val _ = (let val f = fn d => errln("missing "^d^" definition")
2890: in (case t of NONE => f "%term" | _ => ();
2891: case nt of NONE => f "%nonterm" | _ => ())
2892: end);
2893:
2894: val nonterms =
2895: case nt of SOME i => i
2896: | NONE => raise SemanticError
2897:
2898: val terms = case t of SOME i => i
2899: | NONE => raise SemanticError
2900:
2901: val dummy_data = {ty = NONE,num = 0}
2902: val is_term = fn a => ConstrSet.exists (a,dummy_data) terms
2903: val is_nonterm = fn a => ConstrSet.exists (a,dummy_data) nonterms
2904:
2905: exception Get_type
2906: val get_type = fn (a,terms,nonterms) =>
2907: case (ConstrSet.find (a,dummy_data) terms)
2908: of NONE =>
2909: (case (ConstrSet.find (a,dummy_data) nonterms)
2910: of SOME (_,{ty=t,...}) => t
2911: | _ => raise Get_type)
2912: | SOME (_,{ty=t,...}) => t
2913:
2914: val get_prec = fn a =>
2915: case PrecSet.find (a,(0,LEFT)) p
2916: of NONE => NONE
2917: | SOME (_,(a,_)) => SOME a
2918:
2919: val _ = PrecSet.app
2920: (fn (s,_) =>
2921: if is_term s then ()
2922: else errln (s^" in %prec is not defined as a token")
2923: ) p
2924:
2925: val start =
2926: case start
2927: of NONE => start
2928: | SOME i =>
2929: if is_nonterm i then start
2930: else (errln
2931: (i ^ " in %start is not defined as a nonterminal"); NONE)
2932:
2933: val eof = case eof
2934: of NONE =>(errln ("missing %eof definition"); "")
2935: | SOME i =>
2936: if is_term i then i
2937: else (errln (i ^ " in %eof is not defined as a nonterminal"); "")
2938:
2939: fun make_unique_id s =
2940: if (is_term s) orelse (is_nonterm s) then make_unique_id (s ^ "'")
2941: else s
2942: val void = make_unique_id "mlyVOID"
2943:
2944: local
2945: val dummy_start = make_unique_id "mlySTART"
2946: val nontermlist = rev (map (fn {lhs=lhs : symbol,...} => lhs) TRULELIST)
2947: val start = case start of NONE => (hd nontermlist) | SOME a => a
2948: val dummy_type = get_type(start,terms,nonterms)
2949: val code = case dummy_type of NONE => "" | _ => start
2950: in
2951: val nonterms = ConstrSet.insert (dummy_start,
2952: {ty=dummy_type,num=ConstrSet.card nonterms}) nonterms
2953: val is_nonterm = fn a => ConstrSet.exists (a,dummy_data) nonterms
2954: val TRULELIST={lhs=dummy_start,rhs=[start],code=code,prec=NONE}::
2955: TRULELIST
2956: val start=dummy_start
2957: end
2958:
2959: val (keyword, iprefer) =
2960: let val f = fn x =>
2961: fn (a,r) =>
2962: if (is_term a) then a::r
2963: else (errln (a^" in "^x^" is not defined as a terminal"); r)
2964: in (List.fold (f "%keyword") keyword nil,
2965: List.fold (f "%insert_prefer") iprefer nil)
2966: end
2967:
2968: val prefer =
2969: let val print_err =
2970: fn s => errln (s^" in %prefer is not defined as a terminal")
2971: val f = fn (pair as (a,a'),r) =>
2972: let val flag =
2973: if (is_term a) then false else (print_err a; true)
2974: val flag' =
2975: if (is_term a') then false else (print_err a'; true)
2976: in if (flag orelse flag') then r else (pair::r)
2977: end
2978: in List.fold f prefer nil
2979: end
2980:
2981: (* prefer_map : take list of (sym,sym') where sym is a preferred
2982: substitution for sym', make list of (sym,[ ... syms]) where
2983: elements in the list are all the preferred substitutions for some
2984: sym *)
2985:
2986: val prefer_map =
2987: let
2988: (* take prefer list, second elem of pair, return list of elems
2989: in prefer list w/ same second elem, prefer list - list of
2990: elems *)
2991:
2992: fun g (prefer_list,second_elem) =
2993: List.fold (fn (e as (f,s),(same,differ)) =>
2994: if s=second_elem then (f::same,differ) else (same,e::differ))
2995: prefer_list (nil,nil)
2996:
2997: fun f(nil,prefer_map) = prefer_map
2998: | f(l as (e as (_,s):: _),prefer_map) =
2999: let val (same,differ) = g(l,s)
3000: in f(differ,(s,same)::prefer_map)
3001: end
3002:
3003: in f(prefer,nil)
3004: end
3005:
3006: val _ =
3007: ConstrSet.app (fn (s,_) =>
3008: if is_term s andalso is_nonterm s
3009: then errln (s ^ " is defined as a nonterminal and a terminal")
3010: else ()) terms
3011:
3012: val both = ConstrSet.union(terms,nonterms)
3013:
3014: val _ =
3015: let fun undef s =
3016: if (is_term s orelse is_nonterm s) then ()
3017: else (errln (s ^" is not defined as a terminal or nonterminal"))
3018:
3019: fun undef' s =
3020: if is_nonterm s then ()
3021: else (errln (s ^ " is not defined as a nonterminal"))
3022:
3023: fun check_rule {lhs,rhs,code,prec} = (map undef rhs; undef' lhs)
3024:
3025: in map check_rule TRULELIST
3026: end
3027:
3028: in if (!err_flag = false) then
3029: (MLY_MAKE_PARSER.print_parser say;
3030: reset_margin();
3031: sayln ("structure " ^
3032: (case structure'
3033: of NONE => "C"
3034: | SOME i => i) ^
3035: " = ");
3036: inc_margin();
3037: sayln "struct";
3038: inc_margin();
3039:
3040: (* print HDR structure *)
3041:
3042: sayln "structure HDR =";
3043: inc_margin();
3044: sayln "struct";
3045: say HEADER;
3046: dec_margin();
3047: sayln "";
3048: dec_margin();
3049: sayln "end";
3050:
3051: (* print V structure *)
3052:
3053: inc_margin();
3054: sayln "structure V =";
3055: inc_margin();
3056: sayln "struct";
3057: sayln "open HDR;";
3058:
3059: (* printConstrSet returns true if it printed at least
3060: one constructor *)
3061:
3062: if (printConstrSet(both,"Value",true)=true)
3063: then say " | "
3064: else ();
3065: sayln void;
3066: dec_margin();
3067: sayln "";
3068: dec_margin();
3069: sayln "end";
3070:
3071: (* print LexValue structure *)
3072:
3073: inc_margin();
3074: sayln "structure LexValue =";
3075: inc_margin();
3076: sayln "struct";
3077: sayln "open HDR;";
3078: printConstrSet(terms,"V",false);
3079: dec_margin();
3080: sayln "";
3081: dec_margin();
3082: sayln "end";
3083:
3084: (* print G (the grammar) structure *)
3085:
3086: inc_margin();
3087: sayln "structure G =";
3088: inc_margin();
3089: sayln "struct";
3090: sayln
3091: "\tdatatype Terminal = T of int\n\
3092: \\tand Nonterminal = NT of int\n\
3093: \\n\
3094: \\tval eqTerminal = fn ((T i),(T i')) => i = i'\n\
3095: \\tval eqNonterminal = fn ((NT i),(NT i')) => i = i'";
3096:
3097: saywd "datatype Symbol = TERM of Terminal | ";
3098: sayln "NONTERM of Nonterminal";
3099: newln();
3100:
3101: let fun showSymbol(s,t,constr) =
3102: (sayln ("fun "^s^" t = ");
3103: sayln "case t"; saywd "of ";
3104: ConstrSet.app
3105: (fn (nt,{num,...}) =>
3106: ( say constr;
3107: say (makestring num);
3108: say " => ";
3109: sayln ("\""^nt^"\"");
3110: say " | "
3111: )
3112: ) t;
3113: sayln "_ => \"bogus\"";
3114: newln)
3115: in (showSymbol ("showTerminalClass",terms,"T ");
3116: showSymbol ("showNonterminal",nonterms,"NT "))
3117: end;
3118:
3119: sayln "fun showTerminalValue t = showTerminalClass t";
3120: newln();
3121:
3122: sayln "type Lineno = HDR.Lineno";
3123: sayln "val lineno = HDR.lineno";
3124: sayln "val error = HDR.error";
3125:
3126: saywd "datatype Attribute = ATTRIB of {lhs: Nonterminal,";
3127: sayln "rhsLength: int, num: int }";
3128: newln();
3129: saywd "fun showAttribute(ATTRIB{lhs,...}) =" =
3130: sayln "showNonterminal lhs";
3131: newln();
3132: saywd "datatype Rule = RULE of {lhs:Nonterminal,";
3133: saywd "rhs: Symbol list,";
3134: saywd "attribute : Attribute,";
3135: sayln "precedence : int option }";
3136: newln() ;
3137: saywd "val ErrTermList=";
3138: ConstrSet.app
3139: (fn (x,{ty=NONE,num}) =>
3140: if x=eof then ()
3141: else saywd ("(T " ^ (makestring num) ^ ")::")
3142: | _ => ()) terms;
3143: sayln "nil";
3144:
3145: (* invoke Table generator *)
3146:
3147: let
3148: exception TermNum
3149: exception NontermNum
3150: exception SymbolNum
3151:
3152: val get_term_num = fn t =>
3153: case ConstrSet.find (t,dummy_data) terms
3154: of NONE => raise TermNum
3155: | SOME (_,{num=num,...}) => num
3156:
3157: val get_nonterm_num = fn nt =>
3158: case ConstrSet.find (nt,dummy_data) nonterms
3159: of NONE => raise NontermNum
3160: | SOME (_,{num=num,...}) => num
3161:
3162: val get_symbol = fn s =>
3163: (G.TERM (G.T (get_term_num s)) handle TermNum =>
3164: (G.NONTERM (G.NT (get_nonterm_num s)))
3165: handle NontermNum => raise SymbolNum
3166: )
3167:
3168: val numTerminals = ConstrSet.card terms
3169: val numNonterminals = ConstrSet.card nonterms
3170:
3171: val showTerminalClass =
3172: let val b = array(numTerminals,"bogus")
3173: val f = fn (s,{num=num,...}:constr_data) =>
3174: update(b,num,s)
3175: val _ = ConstrSet.app f terms
3176: in fn (G.T i) => ((b sub i) handle _ => "bogus")
3177: end
3178:
3179: val showNonterminal =
3180: let val b = array(numNonterminals,"bogus")
3181: val f = fn (s,{num=num,...}:constr_data) =>
3182: update(b,num,s)
3183: val _ = ConstrSet.app f nonterms
3184: in fn (G.NT i) => ((b sub i) handle _ => "bogus")
3185: end
3186:
3187: val _ =
3188: (let val get_term_string = fn a =>
3189: "(T " ^ (makestring (get_term_num a)) ^ ")"
3190: in print_is_keyword_func (map get_term_string keyword);
3191: print_preferred_insert_func
3192: (map get_term_string iprefer);
3193: print_preferred_subst_func
3194: (map (fn (a,b) => ((get_term_string a),
3195: map get_term_string b))
3196: prefer_map);
3197: sayln ("val eof = " ^ (get_term_string eof))
3198: end;
3199: sayln ("val start = NT "^(makestring (get_nonterm_num start)));
3200: dec_margin();
3201: sayln "end"
3202: )
3203:
3204: val showTerminalValue = showTerminalClass
3205:
3206: val showAttribute = fn (G.ATTRIB {lhs,rhsLength,num}) =>
3207: showNonterminal lhs
3208:
3209: val eof = G.T (get_term_num eof)
3210: val start = G.NT (get_nonterm_num start)
3211:
3212: val termPrecedence =
3213: let val b = array(numTerminals,NONE)
3214: val f = fn (tk,(j:int,p)) =>
3215: let val prec =
3216: SOME (case p of NONASSOC => j
3217: | RIGHT => j+1
3218: | LEFT => j-1)
3219: in update(b,get_term_num tk,prec)
3220: end
3221: val _ = PrecSet.app f p
3222: in fn (G.T i) => b sub i
3223: end
3224:
3225: val (_,rules) =
3226: List.fold (fn ({lhs=lhs,rhs=rhs,code=_,prec},(n,r)) =>
3227: (let val newlhs = G.NT (get_nonterm_num lhs)
3228: val newrhs = map get_symbol rhs
3229: val newattrib =
3230: G.ATTRIB {lhs=newlhs,
3231: rhsLength=List.length rhs,
3232: num = n
3233: }
3234: val newprec =
3235: let fun f (a::b) =
3236: if (is_nonterm a) then f b else get_prec a
3237: | f nil = NONE
3238: in case prec
3239: of NONE => f (rev rhs)
3240: | SOME i => get_prec i
3241: end
3242: in (n+1,(G.RULE {lhs=newlhs,rhs=newrhs,
3243: attribute=newattrib,
3244: precedence=newprec})::r)
3245: end
3246: )) TRULELIST (0,nil)
3247:
3248: in MakeTable.mktable (!out)
3249: {rules=rules,verbose=verbose,
3250: eof = eof, start = start,
3251: termPrecedence = termPrecedence,
3252: showTerminalClass = showTerminalClass,
3253: showTerminalValue = showTerminalValue,
3254: showNonterminal = showNonterminal,
3255: showAttribute = showAttribute,
3256: numTerminals = numTerminals,
3257: numNonterminals = numNonterminals}
3258: end;
3259:
3260: (* Print R structure - actions for rules *)
3261:
3262: sayln "structure R = ";
3263: inc_margin();
3264: sayln "struct";
3265: saywd "val ErrValList = ";
3266: ConstrSet.app (fn (x,{ty=NONE,...}) =>
3267: if x=eof then ()
3268: else saywd ("(V." ^ void ^ ")::") | _ => ()) terms;
3269: sayln "nil";
3270:
3271: sayln "exception mlyRULE of int";
3272: sayln "fun rule(i,vl) =";
3273: sayln "let open HDR";
3274: sayln " val rule_array = arrayoflist(";
3275:
3276: let fun getconstr s =
3277: case (get_type(s,terms,nonterms))
3278: of NONE => NONE
3279: | SOME _ => SOME ("V."^s)
3280:
3281: (* prlist : print list of arguments for a function for a rule *)
3282:
3283: fun prlist rhs =
3284:
3285:
3286: (* f: list of symbols for rhs, list of pairs of (symbol,last # used)
3287: Takes a rhs symbol, finds the correct variable name (eg. the number
3288: to attach to it, and whether or not to have a variable w/o a number
3289: if the rhs symbol is used only once)
3290: *)
3291:
3292: let fun f(nil,l) = ()
3293: | f(t::rhs,l) =
3294:
3295: let
3296:
3297: fun g((e as (a,i))::b,r) =
3298: if a=t then ((a,i+1)::(b@r),t^(makestring (i+1)))
3299: else g(b,e::r)
3300: | g(nil,r) =
3301: if (List.exists (fn a=>a=t) rhs) then
3302: ((t,1)::r,"("^t^"1)")
3303: else ((t,1)::r,"("^t^" as "^t^"1)")
3304:
3305: val (newlist,var) = g(l,nil)
3306:
3307: in
3308:
3309: (f(rhs,newlist);
3310: saywd ("(" ^
3311: (case (getconstr t)
3312: of NONE => "_"
3313: | SOME i => ("(" ^ i ^ " " ^ var ^ ")")
3314: ) ^
3315: ")");
3316: saywd "::"
3317: )
3318: end
3319:
3320: in
3321: (f(rhs,nil); saywd "r672")
3322: end
3323:
3324: in
3325: List.fold (fn ({lhs,rhs,code,prec},n) =>
3326: ( saywd "(fn (";
3327: prlist rhs;
3328: saywd ") => ((";
3329:
3330: let val constr = getconstr lhs
3331: in case constr
3332: of SOME i => saywd i
3333: | NONE => ();
3334: saywd "(";
3335: saywd code;
3336: saywd ")";
3337: case constr
3338: of SOME i => ()
3339: | NONE => (saywd "; ";
3340: saywd ("V."^void)
3341: );
3342: sayln "),r672)";
3343: if (List.length rhs > 0) then
3344: (saywd " | _ => raise mlyRULE ";
3345: saywd (makestring (n:int))
3346: )
3347: else ();
3348: sayln ")"
3349: end; saywd "::"; n+1)) TRULELIST 0
3350: end;
3351: sayln "nil)";
3352: dec_margin();
3353: sayln "in (rule_array sub i) vl end";
3354: dec_margin();
3355: sayln "type Value = V.Value";
3356: say "val VOID = V.";
3357: sayln void;
3358: sayln "end";
3359: dec_margin();
3360:
3361: (* print P structure - contains parsing function *)
3362:
3363: sayln "structure P = ParserGen(structure Lr_Table = Lr_Table";
3364: dec_margin();
3365: sayln " structure RuleAction = R)";
3366: sayln "fun parse (lex : unit -> (LexValue.V)) i= ";
3367: inc_margin();
3368: saywd "(fn (";
3369: case (ConstrSet.find (start,dummy_data) nonterms) of
3370: SOME (_,{ty=SOME _,...})
3371: => (saywd "V."; saywd start; sayln " a) => a)")
3372: | _ => sayln "_) => ())";
3373: sayln "(P.parse (fn () => ";
3374: inc_margin();
3375: sayln "(case lex() of ";
3376: ConstrSet.setfold (fn ((x,{ty=constr,num}),result) =>
3377: (if result then () else saywd " | ";
3378: say "(LexValue."; say x;
3379: case constr
3380: of NONE => (say ") => (G.T ";
3381: say (makestring num);
3382: sayln ("," ^ "V." ^ void ^")"))
3383: | _ => (say " a) => (G.T ";
3384: say (makestring num);
3385: sayln ("," ^ "V." ^ x ^ " a)"));
3386: false))
3387: terms true;
3388: dec_margin(); dec_margin();
3389: sayln ")) i)";
3390: sayln "end";
3391: ()
3392: )
3393: else ()
3394: end handle SemanticError => ()
3395: end)
3396: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.