Name: Listener class library
Version: 1.0
Author: David Pacheco (
Date: 2003-01-21
  1. About
  2. Installation
  3. Usage
  4. History

I. About

The Listener class is intended to encapsulate the functionality of a read-eval- print loop used, for example, in command-line shells, console interpreters, etc.

After instantiating an object of type Listener, you can call the startLoop() member function to begin the loop. It will first prompt the user for input. The input is passed to a handler, and the result of that handler is output back to the user.

The important thing is that the input is safely entered. All quotation marks (both " and ') must be properly closed. If not, the prompt will continue. Additionally, a StatusChecker object (similar to the Handler one) is used to see if the input is complete. If not, the user is prompted again to complete the entry.

II. Installation

  1. Download the source code ( listener-1.0.tar.gz | ).
  2. Installation is simple. Within the listener/src directory, type make. This will create the libListener.a file, which you can then link in another
  3. Make sure to also include the Listener.h header file in any C++ source file you compile that uses the Listener class. Also be sure to link the library you
    created in step 1.

    To clean up the unneeded object files, do make clean. To get rid of all files created by compiling this source, do make clobber.

III. Usage

For sample source code, see the test.cpp source file included in this archive. To compile this, run make test. It shouldn't be hard to figure out, but I'm going to explain the class anyway.

The only parts of the class the client directly needs to interact with are the constructor and the startLoop() function (although you can directly use the getStatement() and putResult() functions to create your own REP loop). You can also use the static isClosed() predicate in your derived StatusChecker classes (see below) to see if a string is "closed" with respect to some char (like quotation marks, though that particular one is handled automatically) or a pair (like parentheses).

The constructor, then, is the most complicated part. It takes several parameters, some optional (defaults listed in [square brackets]):

Let's take these one-by-one.


The Handler is simply a class (inherited from the ADT* Handler provided in the Listener.h header file) which provides a functional action() method. You must specify this; there is no default. The action() method is called on every complete user input with a string parameter representing the input. It returns a string that will be displayed to the user (the result of the print).

In the example of using the Listener as an interactive interpreter, action() will be passed a statement to be evaluated, evaluate it, and return a string representing the result. This is why there cannot be a default - it's the primary means by which the Listener is customized.


The StatusChecker, like the Handler, is a class inherited from the ADT StatusChecker provided in the Listener.h header file. Although there could be a defult, there currently isn't one. If you really want a do-nothing StatusChecker, you have to write it yourself.

The point of the StatusChecker is to provide further checking on the input, so that if it's incomplete, the user can be prompted to finish it. For example, Scheme inputs must have balanced parentheses. Thus, in the test.cpp, where a StatusChecker for Scheme inputs is defined, it simply checks that the number of open paren's matches the number of closed ones. You can customize this to your own needs (e.g. you could write one for SQL queries that simply makes sure that the query ends with a semicolon).


The prompt string is displayed at the beginning of the loop, followed by the prompt character. If the input is incomplete, the prompt continues using the prompt character only. If the input has unmatching quoted characters, they are included in the prompt. A sample Scheme exchange, where the prompt has value "scheme" and the promptChar is ">":

scheme> (define foo "string
   "> "
   > )

On the second line, the user finished the quoted string (having been prompted to do so), and on the third, s/he finished the statement.


The last part of the constructor is the input stream, which defaults to std::cin. Originally (as you can tell by looking at the source files) both the input and output were customizable, but I changed the implementation to use GNU's readline instead of the standard getline(). readline() deals directly with stdout, and I didn't have the need to customize that functionality. This part of the constructor may be taken out in the future, because there's little reason to change the input stream, and even less so if you can't change the output stream as well.


1.0: First release. Fully functional.

*ADT = abstract data type

Back to Projects

Back to Phoenix Web Home.

Phoenix-webmaster: Dave Pacheco
Last updated 2003-01-21