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