next up previous contents index
Next: TextWriter Up: TextReader Previous: stdin   Contents   Index


textReader


Usage

textReader(f, g)


Signature

textReader: (() $\to$ Character, Character $\to$ ()) $\to$ %


Parameter Type Description
f () $\to$ Character the single-character read function
g Character $\to$ () the single-character pushback function


Returns

Returns the input stream for which $f()$ reads a character and $g(c)$ pushes back the character c.


Example

textReader can be used to modify existing readers by ``hooking'' their read! and push! functions in order to customize their behavior. For example, the following function counter transforms any TextReader into one that keeps track of the number of characters and lines read from it.
macro COUNT == Record(chars:MachineInteger, lines:MachineInteger);

counter(rd:TextReader, ct:COUNT):TextReader == {
      ct.chars := ct.lines := 0;    -- initialize counts to 0
      textReader(readAndCount!(rd, ct), pushAndCount!(rd, ct));
}

local readAndCount!(rd:TextReader, ct:COUNT)():Character == {
      c := read! rd;
      if c ~= eof then ct.chars := next(ct.chars);
      if c = newline then ct.lines := next(ct.lines);
      c;
}

local pushAndCount!(rd:TextReader, ct:COUNT)(c:Character):() == {
      if c ~= eof then ct.chars := prev(ct.chars);
      if c = newline then ct.lines := prev(ct.lines);
      push!(c, rd);
}
With the above function, the statements
cnt:COUNT := [0, 0];
countin := counter(stdin, cnt);
produces the reader countin that reads from stdin while side-effecting the variable cnt in order to keep track of the characters and lines read.


next up previous contents index
Next: TextWriter Up: TextReader Previous: stdin   Contents   Index
Manuel Bronstein 2004-06-28