1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
############################################################################
#
# File: longstr.icn
#
# Subject: Procedure to match longest string
#
# Author: Jerry Nowlin
#
# Date: June 1, 1991
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# Contributors: Stephen B. Wampler, Kenneth Walker, Bob Alexander,
# and Richard E. Goerwitz
#
############################################################################
#
# Version: 1.9
#
############################################################################
#
# longstr(l,s,i,j) works like any(), except that instead of taking a
# cset as its first argument, it takes instead a list or set of
# strings (l). Returns i + *x, where x is the longest string in l
# for which match(x,s,i,j) succeeds. Fails if no match occurs.
#
# Defaults:
# s &subject
# i &pos if s is defaulted, otherwise 1
# j 0
#
# Errors:
# The only manual error-checking that is done is to test l to
# be sure it is, in fact, a list or set. Errors such as non-
# string members in l, and non-integer i/j parameters, are
# caught by the normal Icon built-in string processing and sub-
# scripting mechanisms.
#
############################################################################
procedure longstr(l,s,i,j)
local elem, tmp_table
static l_table
initial l_table := table()
#
# No-arg invocation wipes out all static structures, and forces an
# immediate garbage collection.
#
if (/l, /s) then {
l_table := table()
collect() # do it NOW
return # return &null
}
#
# Is l a list, set, or table?
#
type(l) == ("list"|"set"|"table") |
stop("longstr: list, set, or table expected (arg 1)")
#
# Sort l longest-to-shortest, and keep a copy of the resulting
# structure in l_table[l] for later use.
#
if /l_table[l] := [] then {
tmp_table := table()
# keys = lengths of elements, values = elements
every elem := !l do {
/tmp_table[*elem] := []
put(tmp_table[*elem], elem)
}
# sort by key; stuff values, in reverse order, into a list
every put(l_table[l], !sort(tmp_table,3)[*tmp_table*2 to 2 by -2])
}
#
# First element in l_table[l] to match is the longest match (it's
# sorted longest-to-shortest, remember?).
#
return match(!l_table[l],s,i,j)
end
|