Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!ucsd!ucbvax!SOPHIST.UCHICAGO.EDU!goer From: goer@SOPHIST.UCHICAGO.EDU (Richard Goerwitz) Newsgroups: comp.lang.icon Subject: (none) Message-ID: <9005292322.AA13953@sophist.uchicago.edu> Date: 29 May 90 23:22:07 GMT Sender: daemon@ucbvax.BERKELEY.EDU Distribution: inet Organization: The Internet Lines: 82 I am trying to parse a file with lines of backslash delimited fields, with no trailing delimiter: field1\field2\field3 I thought I was on to an elegant way with the string scanning operator: procedure main() while line := read() do { line ? while write(tab(find("\\"))) do move(1) } end It looks to me as though, for a beginner, you have gotten pretty far into string scanning. Nice work. The problem is easy to see - once, that is, you "get it." Find() will tell you the position in line (the subject of the string- scanning operation) at which a backslash occurs. Tab() will then move you there. This works fine for a while. But what happens when you've come to the last \, have move()'d past it? You have no backslashes left on the line to find(), and so naturally find() fails, the loop fails, the scanning espression fails, and you are sent back for another input string. Try doing something like this: while line := read() do { line ? { while write(tab(find("\\")|0)) do move(1) | break } } The expression a|b yields all results in a, then those for b. In the context above, the a side is all that will normally get evalu- ated. In other words, when you say, tab(find(x)), find will only look for one result. Icon only starts backtracking and doing all those fancy result-sequences in contexts like every i := tab(find(x)) do ... Right here we are looking for only one result. What I've done above is to show you how to exploit Icon's desire to find just one result. find() in tab(find(x)) will return an integer as long as there is a backslash ahead of it in the current subject. When it fails, that's it. However, if we say tab(find(x)|0) when find() fails, Icon has another expression it can try to see if it produces another result, namely the 0. Tab(0) means, "go to the end of the line." You'll note above that I put in the expression "move(1) | break" as the do-clause associated with tab(find("\\")|0). All this does is make sure that if you can't move one character (i.e. you've hit line's end), the loop will fail. "Move(1) | fail" means, at least in this con- text, "try to move(1), and if you can't, try to do whatever is on the other side of the slash (namely break out of the loop)." This should do what you want, though I confess that I haven't tested the code. You might want to use the fields of your backslashed strings in various ways, but I'd guess you best bet is to place them in a list: tmp_list := [] line ? { while put(tmp_lst,tab(find("\\")|0)) do move(1) | break } now do something with tmp_lst, like save it in a bigger list, or permutate it, or just print it... Get it? Am I being too pedantic, or is this okay? Nice job picking up string scanning so fast.