|
|
1.1 root 1: # This program tests rt/gollect.s and rt/sweep.c
2:
3: global defs, ifile, in, limit, tswitch, prompt
4:
5: record nonterm(name)
6: record charset(chars)
7: record query(name)
8:
9: procedure main(x)
10: local line, plist
11: plist := [define,generate,grammar,source,comment,prompter,error]
12: defs := table()
13: defs["lb"] := [["<"]]
14: defs["rb"] := [[">"]]
15: defs["vb"] := [["|"]]
16: defs["nl"] := [["\n"]]
17: defs[""] := [[""]]
18: defs["&lcase"] := [[charset(&lcase)]]
19: defs["&ucase"] := [[charset(&ucase)]]
20: defs["&digit"] := [[charset('0123456789')]]
21: i := 0
22: while i < *x do {
23: s := x[i +:= 1] | break
24: case s of {
25: "-t": tswitch := 1
26: "-l": limit := integer(x[i +:= 1]) | stop("usage: [-t] [-l n]")
27: default: stop("usage: [-t] [-l n]")
28: }
29: }
30: ifile := [&input]
31: prompt := ""
32: test := ["<a>::=1|2|3","<a>10","->","<b>::=<a>|<a><a>|<b><b>","<b>5",
33: "<c>::=<b><b><b>","<c>100","<b>100"]
34: every line := !test do {
35: (!plist)(line)
36: collect()
37: }
38: end
39:
40: procedure comment(line)
41: if line[1] == "#" then return
42: end
43:
44: procedure define(line)
45: return line ?
46: defs[(="<",tab(find(">::=")))] := (move(4),alts(tab(0)))
47: end
48:
49: procedure defnon(sym)
50: if sym ? {
51: ="'" &
52: chars := cset(tab(-1)) &
53: ="'"
54: }
55: then return charset(chars)
56: else if sym ? {
57: ="?" &
58: name := tab(0)
59: }
60: then return query(name)
61: else return nonterm(sym)
62: end
63:
64: procedure error(line)
65: write("*** erroneous line: ",line)
66: return
67: end
68:
69: procedure gener(goal)
70: local pending, genstr, symbol
71: repeat {
72: pending := [nonterm(goal)]
73: genstr := ""
74: while symbol := get(pending) do {
75: if \tswitch then write(&errout,genstr,symimage(symbol),listimage(pending))
76: case type(symbol) of {
77: "string": genstr ||:= symbol
78: "charset": genstr ||:= ?symbol.chars
79: "query": {
80: writes("*** supply string for ",symbol.name," ")
81: genstr ||:= read() | {
82: write(&errout,"*** no value for query to ",symbol.name)
83: suspend genstr
84: break next
85: }
86: }
87: "nonterm": {
88: pending := ?\defs[symbol.name] ||| pending | {
89: write(&errout,"*** undefined nonterminal: <",symbol.name,">")
90: suspend genstr
91: break next
92: }
93: if *pending > \limit then {
94: write(&errout,"*** excessive symbols remaining")
95: suspend genstr
96: break next
97: }
98: }
99: }
100: }
101: suspend genstr
102: }
103: end
104:
105: procedure generate(line)
106: local goal, count
107: if line ? {
108: ="<" &
109: goal := tab(upto('>')) \ 1 &
110: move(1) &
111: count := (pos(0) & 1) | integer(tab(0))
112: }
113: then {
114: every write(gener(goal)) \ count
115: return
116: }
117: else fail
118: end
119:
120: procedure getrhs(a)
121: local rhs
122: rhs := ""
123: every rhs ||:= sform(!a) || "|"
124: return rhs[1:-1]
125: end
126:
127: procedure grammar(line)
128: local file, out
129: if line ? {
130: name := tab(find("->")) &
131: move(2) &
132: file := tab(0) &
133: out := if *file = 0 then &output else {
134: open(file,"w") | {
135: write(&errout,"*** cannot open ",file)
136: fail
137: }
138: }
139: }
140: then {
141: (*name = 0) | (name[1] == "<" & name[-1] == ">") | fail
142: pwrite(name,out)
143: if *file ~= 0 then close(out)
144: return
145: }
146: else fail
147: end
148:
149: procedure listimage(a)
150: local s, x
151: s := ""
152: every x := !a do
153: s ||:= symimage(x)
154: return s
155: end
156:
157: procedure alts(defn)
158: local alist
159: alist := []
160: defn ? while put(alist,syms(tab(many(~'|')))) do move(1)
161: return alist
162: end
163:
164: procedure prompter(line)
165: if line[1] == "=" then {
166: prompt := line[2:0]
167: return
168: }
169: end
170:
171: procedure pwrite(name,ofile)
172: local nt, a
173: static builtin
174: initial builtin := ["lb","rb","vb","nl","","&lcase","&ucase","&digit"]
175: if *name = 0 then {
176: a := sort(defs)
177: every nt := !a do {
178: if nt[1] == !builtin then next
179: write(ofile,"<",nt[1],">::=",getrhs(nt[2]))
180: }
181: }
182: else write(ofile,name,"::=",getrhs(\defs[name[2:-1]])) |
183: write("*** undefined nonterminal: ",name)
184: end
185:
186: procedure sform(alt)
187: local s, x
188: s := ""
189: every x := !alt do
190: s ||:= case type(x) of {
191: "string": x
192: "nonterm": "<" || x.name || ">"
193: "charset": "<'" || x.chars || "'>"
194: }
195: return s
196: end
197:
198: procedure source(line)
199: return line ? (="@" & push(ifile,in) & {
200: in := open(file := tab(0)) | {
201: write(&errout,"*** cannot open ",file)
202: fail
203: }
204: })
205: end
206:
207: procedure symimage(x)
208: return case type(x) of {
209: "string": x
210: "nonterm": "<" || x.name || ">"
211: "charset": "<'" || x.chars || "'>"
212: }
213: end
214:
215: procedure syms(alt)
216: local slist
217: slist := []
218: alt ? while put(slist,tab(many(~'<')) |
219: defnon(2(="<",tab(upto('>')),move(1))))
220: return slist
221: end
222:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.