The readerprinter class implements all the methods constituting the wwlisp reader and printer. The reader parses an input stream of characters, converts it to tokens, which are identified as weird atoms, strings, floats, integers, unsignedintegers symbolic atoms or special characters, and from those builds a wwlisp form structure in memory, which can be passed to the eval function. Per default, the reader recognizes left and right parenthesis, and readmacros like simple quote for quote function, semi-colon or dash for comment and skip to end of line, tilde for eval function, colon for list function. All the readmacros can be suppressed or redefined, except the parenthesis which can only be suppressed but not redefined. By changing the special characters and the readmacros linked to them, it is possible to reconfigure deeply the behaviour of an instance of the reader, in order for example to make it able to parse and understand xml, html or almost whatever. The reader (actually the readerprinter-read method), invokes repeatitively the scanner (ie: readerprinter-ratom ). On each token delimited by whitechar or specialchar, and which is not a weird atom, readerprinter-ratom applies sequentially the list of recognizers defined in the property scanner of the readerprinter object. If an object is returned by one of the recognizers, it is returned by ratom. If no recognizer returns other than nil, ratom makes a symbolic atom from the token and returns it. The scanner property is updated by the set-scanner function. The printer converts lists and the inner representation of the wwlisp types back to a human readable stream of characters. Actually the conversion to a printable form is done by the format method of each class. readerprinter-prin1 and readerprinter-princ just invoke the format method for each object to be printed. Once defined for a class in a thread, a format method applies to all the instances of readerprinter in that thread, but it is possible to override it for a specific readerprinter and for a specific class with the function set-formatter which maintains the formatter property of the readerprinter object. Example: The class binary has a formatter named binary-format The form (format(make-instance binary 10)) would return the following string: "[binary]AAAAAAAAAAAAAA" . When readerprinter- prin1 or readerprinter- princ must print a binary, they invoke binary-format with the binary object as argument, the result being a string like the previous one. That string is then sent to the output, without the quotes. The printer is also responsible of presenting nicely a form on the output in order to make it more readable by a human being, i.e. pretty printing. It is in the readerprinter-pprint method that conversions symmetrical to some readmacros are performed, for instance to replace a quote function by a simple quote character. The readerprinter-pprint method is not compiled but interpreted in order to allow the programmer to customize it at will. In summary, there are three different ways to express an object on the output: by the class formatter, by a class override per readerprinter instance (set by using set-formatter ), or by another method not yet discussed: readerprinter-cformat The readerprinter class is never instantiated as such because it lacks the methods to get or put characters from or on a stream, so readerprinter is always used as an inherited base class for defining other more specific classes. The readerprinter class is a base class of the symbolicstream , symbolicsocket , symbolicstring classes. When the constructor of a class inheriting from the readerprinter class is called, it must itself call explicitely readerprinter-constructor , in order to add all the adequate properties to the object. Some of the properties are derived from those bound to the symbol *readtable* , which is initialized at startup of the interpreter. These properties are: nil-is-empty , whitespace , specialchar , readmacro , scanner and formatter . When nil-is-empty is t, the pretty printer uses nil to print an empty list otherwise it uses (). The whitespace property is a list of the Unicode characters which are similar as space and can be skipped transparently between tokens. The specialchar property is a list of all the Unicode characters which trigger a special handling, defined as a readmacro. The readmacro property is a list of pairs each of a Unicode character and an evaluable wwlisp form. The scanner and formatter properties have already been described here above. For performance reason, a C structure containing buffers and flags is also bound to the property lreaderprinter of each instance of the class; this structure is customized for reading or printing or both during object construction. |
Function Type | subr |
Arguments | a readerprinter object |
Return Value | t |
Description | formats using the C library function vsnprintf and does a princ of the result on the object given as first argument; the format string is given as second argument; the next arguments are the argument for the formatting function; as each integer or pointer is promoted to long, this is transparent on a 32 bits CPU, but must be taken in account in the format on a 64 bits CPU (use 'l' modifiers); in addition to the C standard, Unicode characters not present on the keyboard can be represented by a \ and an octal sequence or a \x and a hexadecimal sequence which will be translated in UTF-8 |
Example | (cformat stdout "*** %s %6.2lf \x20ac ***" "credit" 100.0) => *** credit 100.000000 € ***t |
Function Type | subr |
Arguments | an integer |
Return Value | t |
Description | this function must be called explicitely from inside a constructor of a subclass of the class readerprinter ; the method allocates the C structure bound to the lreaderprinter property; the integer passed as argument defines which buffers must be allocated: the value 1 indicates that the object is allowed to read things, 2 indicates that a parser buffer is to be allocated, and 4 indicates that an ouput buffer is to be allocated and that the object is allowed to print; the values can be combined by bit-or, i.e. 7 means all options; as we are executing from inside the dynamic scope of a constructor of the class, the object to act on is already bound to the this symbol and hence implicitely accessible to readerprinter-constructor |
Example | (readerprinter-constructor 7) |
Function Type | subr |
Arguments | none |
Return Value | t |
Description | this function must be called from inside the destructor of an object of a class inheriting from the readerprinter class; the method deallocates properly the C structure bound to the lreaderprinter property; as we are executing from inside the dynamic scope of a destructor of the class, the object to act on is already bound to the this symbol and hence implicitely accessible to readerprinter-destructor |
Example | (readerprinter-destructor) |
Function Type | subr |
Arguments | a readerprinter object, t or nil |
Return Value | t or nil |
Description | returns t if the object passed as first argument has just printed an atom; also sets it arbitrarily following the value t or nil of the second argument |
Example | (need-space stdout t) |
Function Type | fexpr |
Arguments | a readerprinter object, a form |
Return Value | nil |
Description | never use directly, is a subroutine of readerprinter-pretty-print |
Example | none |
Function Type | expr |
Arguments | a readerprinter object, anything |
Return Value | nil |
Description | prints nicely the form passed as second argument on the object passed as first argument; per default the indentation is 4 characters; if the property nil-is-empty of *readtable* is t, then an empty list is represented by nil, otherwise it is represented by () |
Example | (pretty-print stdout(getprop 'edit 'function)) |
Function Type | subr |
Arguments | a readerprinter (or subclass) object, anything |
Return Value | the second argument |
Description | prints the second argument on the object given as first argument and also returns the second argument; the second argument is printed in such a way that it can be read back by a read function and give the same value; a string will be printed between double quote i.e. Unicode 34, and an atom containing special characters, i.e. a weird atom, will be printed between vertical bars i.e. Unicode 124; if a double quote occurs in a string, the double quote will be doubled, and if a vertical bar occurs in a weird atom, the vertical bar will be doubled; a list will be printed with the parenthesis and recursively, but infinite recursion or circular lists will throw errors; space characters will be added automatically as needed between atoms or values in order to avoid spurious apparent concatenations and errors while reading back; no newline will be issued at the end |
Example | (prin1 stdout "hello" ) => "hello" "hello" |
Function Type | subr |
Arguments | a readerprinter (or subclass) object, anything |
Return Value | the second argument |
Description | prints the second argument on the object given as first argument and also returns the second argument; the second argument is printed in such a way that strings and weird atoms are as they are, i.e. not enclosed by double quote or vertical bar respectively, and occurences of double quote or vertical bar are not doubled; a list will be printed recursively with the parenthesis, but infinite recursion or circular lists will throw errors; no space characters will be added between atoms or values, leading to spurious apparent concatenations while reading back; no newline will be issued at the end |
Example | (princ "hello" ) => hello"hello" |
Function Type | subr |
Arguments | a readerprinter (or subclass) object, anything |
Return Value | the second argument |
Description | prints the second argument on the object given as first argument and also returns the second argument; the second argument is printed in such a way that it can be read back by a read function and give the same value; a string will be printed between double quote i.e. Unicode 34, and an atom containing special characters, i.e. a weird atom, will be printed between vertical bars i.e. Unicode 124; if a double quote occurs in a string, the double quote will be doubled, and if a vertical bar occurs in a weird atom, the vertical bar will be doubled; a list will be printed with the parenthesis and recursively, but infinite recursion or circular lists will throw errors; space characters will be added automatically as needed between atoms or values in order to avoid spurious apparent concatenations and errors while reading back; a newline will be issued at the end |
Example | (print stdout "hello" ) => "hello" "hello" |
Function Type | subr |
Arguments | a readerprinter (or subclass) object |
Return Value | an atom |
Description | reads the object given as argument and returns the next token; the token can be a symbolic atom, a weird atom enclosed in vertical bars, a double precision floating point real number, a signed integer or an unsigned integer, or an instance of the class specialchar; the special character is represented by an object of the class specialchar of which the value is the Unicode value of the character, allowing the use of accented and international characters as special characters for readmacros or separators; ratom is seldom used by itself but is generally used by the read function; ratom uses the more fundamental read-char and unread-char methods which must be inherited from a parent class |
Example | (setq token(ratom stdin)) (cond((specialcharp token) ... special character handling ...) (t ... all other tokens handling ...) ) |
Function Type | subr |
Arguments | a readerprinter (or subclass) object |
Return Value | anything |
Description | reads the object given as argument and returns the next wwlisp form; the form can be a symbolic atom, a weird atom enclosed in vertical bars, a string enclosed in double quotes, a double precision floating point real number, a signed integer or an unsigned integer, or a list structure eventually also made recursively of sublists; the form is ready to be evaluated by passing to eval ; read is one of the components of the toplevel loop read-eval-print; read uses ratom to fetch the next token on the input, and if the token is a special character, read looks into the property readmacro of the object given as argument for the corresponding form to execute; a special character and its readmacro can be redefined or inhibited by the function set-macro-char |
Example | (read stdin) |
Function Type | subr |
Arguments | a readerprinter (or subclass) object |
Return Value | a string |
Description | reads the object given as argument and returns the next line as a string; the line read goes from the current position in the input buffer to just after the newline character, but the newline character is deleted from the string returned; readerprinter-read-line works by calling iteratively on the object the more fundamental method read-char which must be inherited from a parent class |
Example | (read-line stdin)hello! => "hello!" |
Function Type | subr |
Arguments | a readerprinter (or subclass) object, a string, a series of optional symbols |
Return Value | a string |
Description | reads the object given as argument and returns the result as a string; the string read goes from the current position in the input buffer to the first of the delimiting UTF-8 characters found in the string given as second argument; the optional keyword 'duplicate indicates that any double occurrence of a delimiter character is to be included in the string as a simple occurrence and does not indicate the end of the string; the optional keyword 'skip indicates that the the delimiting character is to be deleted from the input and will not be read again by the following call; the optional keyword 'include means that the delimiter is to be included in the string and deleted from the input; the optional keyword 'exclude means that the delimiter must stay on the input in order to be used by a subsequent call; if 'duplicate is specified, then 'include or 'exclude may not be used; 'skip is the default value assumed when no keyword or just 'duplicate is specified readerprinter-read-string works by calling iteratively on the object the more fundamental methods read-char and unread-char , which must be inherited from a parent class; |
Example | (read-string stdin "€" 'duplicate) => reads a string delimited by € which could contain some occurrences of €€ to be read as single € |
Function Type | subr |
Arguments | a readerprinter (or subclass) object |
Return Value | nil |
Description | prints a newline character on the object passed as argument; terpri is based on the more fundamental write-char method which must be inherited from a parent class; terpri can be redefined in order to write another line termination like for example CR-LF on its output; as terpri is used by print , print will automatically also be redefined in the same way for the same class |
Example | (terpri stdout) |