goer@quads.uchicago.edu (Richard L. Goerwitz) (10/05/90)
I had to write this the other day, and it seemed to be something that would be of general interest. -Richard ############################################################################ # # Name: slashbal.icn # # Title: Bal() with backslash escaping # # Author: Richard L. Goerwitz # # Version: 1.1 # ############################################################################ # # I am often frustrated at bal()'s inability to deal elegantly with # the common \backslash escaping convention (a way of telling Unix # Bourne and C shells, for instance, not to interpret a given # character as a "metacharacter"). I recognize that bal()'s generic # behavior is a must, and so I wrote slashbal() to fill the gap. # # Slashbal behaves like bal, except that it ignores, for purposes of # balancing, any character which is preceded by a backslash. Note # that we are talking about internal backslashes, and not necessarily # the backslashes used in Icon string literals. If you have "\(" in # your source code, the string produced will have no backslash. To # get this effect, you would need to write "\\(." # # BUGS: Note that, like bal() (v8), slashbal() cannot correctly # handle cases where c2 and c3 intersect. # ############################################################################ # # Links: none # ############################################################################ procedure slashbal(c1, c2, c3, s, i, j) local allcs, chr, count /c1 := &cset /c2 := '(' /c3 := ')' allcs := c1 ++ c2 ++ c3 ++ '\\' /s := \&subject | stop("slashbal: No string argument.") /i := \&pos | 1 /j := *s + 1 count := 0 s ? { while tab(upto(allcs)) do { chr := move(1) if chr == "\\" then { chr := move(1) | fail if any(c1, chr) & count = 0 then suspend .&pos - 1 } else { if any(c1, chr) & count = 0 then suspend .&pos - 1 if any(c2, chr) then count +:= 1 else if any(c3, chr) then count -:= 1 } } } end