// file: Parse.java // author: Robert Keller // purpose: Parse function object for kwic // note: Could also use a StringTokenizer instead of the methods here. class Parse implements Function1 { static private Character blank = new Character(' '); /** * Parse a title String. * @param title the String to be parsed * @return a list of words in the title */ public Object apply(Object title) { return parse1(OpenList.explode((String)title)); } /** * parse1 returns a list of words from an original String. The words * are formed from consecutive characters, as separated by blanks in the * String. * @param Chars characters of the String to be parsed * @return a list of words in the title */ // rex: parse1([]) => []; // rex: parse1([' ' | Chars]) => parse1(Chars); // rex: parse1([NonBlank | Chars]) => parse2([NonBlank], Chars); OpenList parse1(OpenList Chars) { if( Chars.isEmpty() ) return OpenList.nil; if( Chars.first().equals(blank) ) return parse1(Chars.rest()); return parse2(OpenList.list(Chars.first()), Chars.rest()); } /** * parse2 is an auxiliary method for parse1. It collects non-blank characters * in an accumulator. When a blank is found, or the end of the list of * characters is reached, it reverses the accumulator and returns a list * beginning with that, followed by the result of calling parse1 recursively. * @param Acc accumulated characters * @param Chars characters of the String to be parsed * @return a list of words in the title */ // rex: parse2(Acc, []) => [reverse(implode(Acc))]; // rex: parse2(Acc, [' ' | Chars]) => [reverse(implode(Acc)) | parse1(Chars)]; // rex: parse2(Acc, [Char | Chars]) => parse2([Char | Acc], Chars); OpenList parse2(OpenList Acc, OpenList Chars) { if( Chars.isEmpty() ) return OpenList.list(Acc.reverse().implode()); if( Chars.first().equals(blank) ) return OpenList.cons(Acc.reverse().implode(), parse1(Chars.rest())); return parse2(OpenList.cons(Chars.first(), Acc), Chars.rest()); } }