Annotation of researchv10dc/cmd/icon/ipl/source/rsg.icn, revision 1.1.1.1

1.1       root        1: #      RSG
                      2: #
                      3: #      Random sentence generation
                      4: #
                      5: #      Ralph E. Griswold
                      6: #
                      7: #      Last modified 4/29/86
                      8: #
                      9: 
                     10: global defs, ifile, in, limit, tswitch, prompt
                     11: 
                     12: record nonterm(name)
                     13: record charset(chars)
                     14: record query(name)
                     15: 
                     16: procedure main(x)
                     17:    local line, plist, i, s
                     18:                                        # procedures to try on input lines
                     19:    plist := [define,generate,grammar,source,comment,prompter,error]
                     20:    defs := table()                     # table of definitions
                     21:    defs["lb"] := [["<"]]               # built-in definitions
                     22:    defs["rb"] := [[">"]]
                     23:    defs["vb"] := [["|"]]
                     24:    defs["nl"] := [["\n"]]
                     25:    defs[""] := [[""]]
                     26:    defs["&lcase"] := [[charset(&lcase)]]
                     27:    defs["&ucase"] := [[charset(&ucase)]]
                     28:    defs["&digit"] := [[charset('0123456789')]]
                     29:    i := 0
                     30:    while i < *x do {                   # process options
                     31:       s := x[i +:= 1] | break
                     32:       case s of {
                     33:          "-t":   tswitch := 1
                     34:          "-l":   limit := integer(x[i +:= 1]) | Usage()
                     35:          "-s":   &random := integer(x[i +:= 1]) | Usage()
                     36:          default:   Usage()
                     37:          }
                     38:       }
                     39:    ifile := [&input]                   # stack of input files
                     40:    prompt := ""
                     41:    while in := pop(ifile) do {         # process all files
                     42:       repeat {
                     43:          if *prompt ~= 0 then writes(prompt)
                     44:          line := read(in) | break
                     45:          while line[-1] == "\\" do line := line[1:-1] || read(in) | break
                     46:          (!plist)(line)
                     47:          }
                     48:       close(in)
                     49:       }
                     50: end
                     51: 
                     52: #  process alternatives
                     53: #
                     54: procedure alts(defn)
                     55:    local alist
                     56:    static nonbar
                     57:    initial nonbar := ~'|'
                     58:    alist := []
                     59:    defn ? while put(alist,syms(tab(many(nonbar)))) do move(1)
                     60:    return alist
                     61: end
                     62: 
                     63: #  look for comment
                     64: #
                     65: procedure comment(line)
                     66:    if line[1] == "#" then return
                     67: end
                     68: 
                     69: #  look for definition
                     70: #
                     71: procedure define(line)
                     72:    return line ?
                     73:       defs[(="<",tab(find(">::=")))] := (move(4),alts(tab(0)))
                     74: end
                     75: 
                     76: #  define nonterminal
                     77: #
                     78: procedure defnon(sym)
                     79:    local chars, name
                     80:    if sym ? {
                     81:       ="'" &
                     82:       chars := cset(tab(-1)) &
                     83:       ="'"
                     84:       }
                     85:    then return charset(chars)
                     86:    else if sym ? {
                     87:       ="?" &
                     88:       name := tab(0)
                     89:       }
                     90:    then return query(name)
                     91:    else return nonterm(sym)
                     92: end
                     93: 
                     94: #  note erroneous input line
                     95: #
                     96: procedure error(line)
                     97:    write("*** erroneous line:  ",line)
                     98:    return
                     99: end
                    100: 
                    101: #  generate sentences
                    102: #
                    103: procedure gener(goal)
                    104:    local pending, genstr, symbol
                    105:    repeat {
                    106:       pending := [nonterm(goal)]
                    107:       genstr := ""
                    108:       while symbol := get(pending) do {
                    109:          if \tswitch then
                    110:             write(&errout,genstr,symimage(symbol),listimage(pending))
                    111:          case type(symbol) of {
                    112:             "string":   genstr ||:= symbol
                    113:             "charset":  genstr ||:= ?symbol.chars
                    114:             "query":    {
                    115:                writes("*** supply string for ",symbol.name,"  ")
                    116:                genstr ||:= read() | {
                    117:                   write(&errout,"*** no value for query to ",symbol.name)
                    118:                   suspend genstr
                    119:                   break next
                    120:                   }
                    121:                }
                    122:             "nonterm":  {
                    123:                pending := ?\defs[symbol.name] ||| pending | {
                    124:                   write(&errout,"*** undefined nonterminal:  <",symbol.name,">")
                    125:                   suspend genstr
                    126:                   break next
                    127:                   }
                    128:                if *pending > \limit then {
                    129:                   write(&errout,"*** excessive symbols remaining")
                    130:                   suspend genstr
                    131:                   break next
                    132:                   }
                    133:                }
                    134:             }
                    135:          }
                    136:       suspend genstr
                    137:       }
                    138: end
                    139: 
                    140: #  look for generation specification
                    141: #
                    142: procedure generate(line)
                    143:    local goal, count
                    144:    if line ? {
                    145:       ="<" &
                    146:       goal := tab(upto('>')) \ 1 &
                    147:       move(1) &
                    148:       count := (pos(0) & 1) | integer(tab(0))
                    149:       }
                    150:    then {
                    151:       every write(gener(goal)) \ count
                    152:       return
                    153:       }
                    154:    else fail
                    155: end
                    156: 
                    157: #  get right hand side of production
                    158: #
                    159: procedure getrhs(a)
                    160:    local rhs
                    161:    rhs := ""
                    162:    every rhs ||:= listimage(!a) || "|"
                    163:    return rhs[1:-1]
                    164: end
                    165: 
                    166: #  look for request to write out grammar
                    167: #
                    168: procedure grammar(line)
                    169:    local file, out, name
                    170:    if line ? {
                    171:       name := tab(find("->")) &
                    172:       move(2) &
                    173:       file := tab(0) &
                    174:       out := if *file = 0 then &output else {
                    175:          open(file,"w") | {
                    176:             write(&errout,"*** cannot open ",file)
                    177:             fail
                    178:             }
                    179:          }
                    180:       }
                    181:    then {
                    182:       (*name = 0) | (name[1] == "<" & name[-1] == ">") | fail
                    183:       pwrite(name,out)
                    184:       if *file ~= 0 then close(out)
                    185:       return
                    186:       }
                    187:    else fail
                    188: end
                    189: 
                    190: #  produce image of list of grammar symbols
                    191: #
                    192: procedure listimage(a)
                    193:    local s, x
                    194:    s := ""
                    195:    every x := !a do
                    196:       s ||:= symimage(x)
                    197:    return s
                    198: end
                    199: 
                    200: #  look for new prompt symbol
                    201: #
                    202: procedure prompter(line)
                    203:    if line[1] == "=" then {
                    204:       prompt := line[2:0]
                    205:       return
                    206:       }
                    207: end
                    208: 
                    209: #  write out grammar
                    210: #
                    211: procedure pwrite(name,ofile)
                    212:    local nt, a
                    213:    static builtin
                    214:    initial builtin := ["lb","rb","vb","nl","","&lcase","&ucase","&digit"]
                    215:    if *name = 0 then {
                    216:       a := sort(defs,3)
                    217:       while nt := get(a) do {
                    218:          if nt == !builtin then {
                    219:             get(a)
                    220:             next
                    221:             }
                    222:          write(ofile,"<",nt,">::=",getrhs(get(a)))
                    223:          }
                    224:       }
                    225:    else write(ofile,name,"::=",getrhs(\defs[name[2:-1]])) |
                    226:       write("*** undefined nonterminal:  ",name)
                    227: end
                    228: 
                    229: #  look for file with input
                    230: #
                    231: procedure source(line)
                    232:    local file
                    233:    return line ? (="@" & push(ifile,in) & {
                    234:       in := open(file := tab(0)) | {
                    235:          write(&errout,"*** cannot open ",file)
                    236:          fail
                    237:          }
                    238:       })
                    239: end
                    240: 
                    241: #  produce string image of grammar symbol
                    242: #
                    243: procedure symimage(x)
                    244:    return case type(x) of {
                    245:       "string":   x
                    246:       "nonterm":  "<" || x.name || ">"
                    247:       "charset":  "<'" || x.chars || "'>"
                    248:       }
                    249: end
                    250: 
                    251: #  process the symbols in an alternative
                    252: #
                    253: procedure syms(alt)
                    254:    local slist
                    255:    static nonbrack
                    256:    initial nonbrack := ~'<'
                    257:    slist := []
                    258:    alt ? while put(slist,tab(many(nonbrack)) |
                    259:       defnon(2(="<",tab(upto('>')),move(1))))
                    260:    return slist
                    261: end
                    262: 
                    263: #  stop, noting incorrect usage
                    264: #
                    265: procedure Usage()
                    266:    stop("usage:  [-t] [-l n] [-s n]")
                    267: end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.