+global defs
+
+record nonterm(name)
+
+procedure main()
+ local line
+ defs := table()
+ while line := read() do
+ (define | generate)(line)
+end
+
+procedure define(line)
+ return line ?
+ defs[(="<",tab(find(">::=")))] := (move(4),alts(tab(0)))
+end
+
+procedure alts(defn)
+ local alist
+ alist := []
+ defn ? while put(alist,syms(tab(many(~'|')))) do move(1)
+ return alist
+end
+
+procedure syms(alt)
+ local slist
+ slist := []
+ alt ? while put(slist,tab(many(~'<')) |
+ nonterm(2(="<",tab(upto('>')),move(1))))
+ return slist
+end
+
+procedure generate(line)
+ local goal, count
+ line ? {
+ ="<" &
+ goal := tab(upto('>')) &
+ move(1) &
+ count := tab(0)
+ }
+ every write(gener(goal)) \ count
+ return
+end
+
+procedure gener(goal)
+ local pending, genstr, symbol
+ repeat {
+ pending := [nonterm(goal)]
+ genstr := ""
+ while symbol := get(pending) do
+ if type(symbol) == "string" then genstr ||:= symbol
+ else pending := ?defs[symbol.name] ||| pending
+ suspend genstr
+ }
+end