home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- #
- # File: concord.icn
- #
- # Subject: Program to produce concordance
- #
- # Author: Ralph E. Griswold
- #
- # Date: September 6, 1992
- #
- ###########################################################################
- #
- # This program produces a simple concordance from standard input to standard
- # output. Words less than three characters long are ignored.
- #
- # There are two options:
- #
- # -l n set maximum line length to n (default 72), starts new line
- # -w n set maximum width for word to n (default 15), truncates
- #
- # There are lots of possibilities for improving this program and adding
- # functionality to it. For example, a list of words to be ignored could be
- # provided. The formatting could be made more flexible, and so on.
- #
- ############################################################################
- #
- # Note that the program is organized to make it easy (via item()) to
- # handle other kinds of tabulations.
- #
- ############################################################################
- #
- # Links: options
- #
- ############################################################################
-
- link options
-
- global uses, colmax, namewidth, lineno
-
- procedure main(args)
- local opts, uselist, name, line
- opts := options(args, "l+w+") # process options
- colmax := \opts["l"] | 72
- namewidth := \opts["w"] | 15
- uses := table()
- lineno := 0
- every tabulate(item(), lineno) # tabulate all the citations
- uselist := sort(uses, 3) # sort by uses
- while name := get(uselist) do
- format(left(name, namewidth) || get(uselist))
- end
-
- # Add line number to citations for name. If it already has been cited,
- # add (or increment) the number of citations.
- #
- procedure tabulate(name, lineno)
- local count, i, j, k, last, head, tail
- lineno := string(lineno)
- if /uses[name] := lineno || ", " then return
- uses[name] ? {
- j := 1 # token start
- every i := upto(',') + 2 do { # token end
- k := j
- j := i # last token start
- }
- head := tab(k) # everything but last token
- last := tab(many(&digits)) # last line number
- if last ~= lineno then { # new number
- tail := last || tab(0) || lineno || ", "
- }
- else { # repeated number
- if ="(" then count := tab(many(&digits)) + 1 else
- count := 2
- tail := last || "(" || count || "), "
- }
- }
- uses[name] := head || tail
- return
- end
-
- # Format the output, breaking long lines as necessary.
- #
- procedure format(line)
- local i
- while *line > colmax + 2 do {
- i := colmax + 2
- until line[i -:= 1] == " " # back off to break point
- write(line[1:i])
- line := repl(" ", namewidth) || line[i + 1:0]
- }
- write(line[1:-2])
- end
-
- # Get an item. Different kinds of concordances can be obtained by
- # modifying this procedure.
- #
- procedure item()
- local i, word, line
- while line := read() do {
- lineno +:= 1
- write(right(lineno, 6), " ", line)
- line := map(line) # fold to lowercase
- i := 1
- line ? {
- while tab(upto(&letters)) do {
- word := tab(many(&letters))
- if *word >= 3 then suspend word # skip short words
- }
- }
- }
- end
-