wxWidgets/docs/latex/wx/texpr.tex

204 lines
7.4 KiB
TeX
Raw Normal View History

\section{wxExpr overview}\label{exproverview}
wxExpr is a C++ class reading and writing a subset of Prolog-like syntax,
supporting objects attribute/value pairs.
wxExpr can be used to develop programs with readable and
robust data files. Within wxWindows itself, it is used to parse
the {\tt .wxr} dialog resource files.
{\bf History of wxExpr}
During the development of the tool Hardy within the AIAI, a need arose
for a data file format for C++ that was easy for both humans and
programs to read, was robust in the face of fast-moving software
development, and that provided some compatibility with AI languages
such as Prolog and LISP.
The result was the wxExpr library (formerly called PrologIO), which is able to read and write a
Prolog-like attribute-value syntax, and is additionally capable of
writing LISP syntax for no extra programming effort. The advantages of
such a library are as follows:
\begin{enumerate}\itemsep=0pt
\item The data files are readable by humans;
\item I/O routines are easier to write and debug compared with using binary files;
\item the files are robust: unrecognised data will just be ignored by the application
\item Inbuilt hashing gives a random access capability, useful for when linking
up C++ objects as data is read in;
\item Prolog and LISP programs can load the files using a single command.
\end{enumerate}
The library was extended to use the ability to read and write
Prolog-like structures for remote procedure call (RPC) communication.
The next two sections outline the two main ways the library can be used.
\subsection{wxExpr for data file manipulation}\itemsep=0pt
The fact that the output is in Prolog syntax is irrelevant for most
programmers, who just need a reasonable I/O facility. Typical output
looks like this:
\begin{verbatim}
diagram_definition(type = "Spirit Belief Network").
node_definition(type = "Model",
image_type = "Diamond",
attribute_for_label = "name",
attribute_for_status_line = "label",
colour = "CYAN",
default_width = 120,
default_height = 80,
text_size = 10,
can_resize = 1,
has_hypertext_item = 1,
attributes = ["name", "combining_function", "level_of_belief"]).
arc_definition(type = "Potentially Confirming",
image_type = "Spline",
arrow_type = "End",
line_style = "Solid",
width = 1,
segmentable = 0,
attribute_for_label = "label",
attribute_for_status_line = "label",
colour = "BLACK",
text_size = 10,
has_hypertext_item = 1,
can_connect_to = ["Evidence", "Cluster", "Model", "Evidence", "Evidence", "Cluster"],
can_connect_from = ["Data", "Evidence", "Cluster", "Evidence", "Data", "Cluster"]).
\end{verbatim}
This is substantially easier to read and debug than a series of numbers and
strings.
Note the object-oriented style: a file comprises a series of {\it clauses}.
Each clause is an object with a {\it functor}\/ or object name, followed
by a list of attribute-value pairs enclosed in parentheses, and finished
with a full stop. Each attribute value may be a string, a word (no quotes),
an integer, a real number, or a list with potentially recursive elements.
The way that the facility is used by an application to read in a file is
as follows:
\begin{enumerate}\itemsep=0pt
\item The application creates a wxExprDatabase instance.
\item The application tells the database to read in the entire file.
\item The application searches the database for objects it requires,
decomposing the objects using the wxExpr API. The database may be hashed,
allowing rapid linking-up of application data.
\item The application deletes or clears the wxExprDatabase.
\end{enumerate}
Writing a file is just as easy:
\begin{enumerate}\itemsep=0pt
\item The application creates a wxExprDatabase instance.
\item The application adds objects to the database using the API.
\item The application tells the database to write out the entire database,
in Prolog or LISP notation.
\item The application deletes or clears the wxExprDatabase.
\end{enumerate}
To use the library, include "wxexpr.h".
\subsection{wxExpr compilation}
For UNIX compilation, ensure that YACC and LEX or FLEX are on your system. Check that
the makefile uses the correct programs: a common error is to compile
y\_tab.c with a C++ compiler. Edit the CCLEX variable in make.env
to specify a C compiler. Also, do not attempt to compile lex\_yy.c
since it is included by y\_tab.c.
For DOS compilation, the simplest thing is to copy dosyacc.c to y\_tab.c, and doslex.c to
lex\_yy.c. It is y\_tab.c that must be compiled (lex\_yy.c is included by
y\_tab.c) so if adding source files to a project file, ONLY add y\_tab.c
plus the .cc files. If you wish to alter the parser, you will need YACC
and FLEX on DOS.
The DOS tools are available at the AIAI ftp site, in the tools directory. Note that
for FLEX installation, you need to copy flex.skl into the directory
c:/lib.
If you are using Borland C++ and wish to regenerate lex\_yy.c and y\_tab.c
you need to generate lex\_yy.c with FLEX and then comment out the `malloc' and `free'
prototypes in lex\_yy.c. It will compile with lots of warnings. If you
get an undefined \_PROIO\_YYWRAP symbol when you link, you need to remove
USE\_DEFINE from the makefile and recompile. This is because the parser.y
file has a choice of defining this symbol as a function or as a define,
depending on what the version of FLEX expects. See the bottom of
parser.y, and if necessary edit it to make it compile in the opposite
way to the current compilation.
%To test out wxExpr compile the test program (samples/wxexpr/wxexpr.exe),
%and try loading test.exp into the test
%program. Then save it to another file. If the second is identical to the
%first, wxExpr is in a working state.
\subsection{Bugs}
These are the known bugs:
\begin{enumerate}\itemsep=0pt
\item Functors are permissable only in the main clause (object).
Therefore nesting of structures must be done using lists, not predicates
as in Prolog.
\item There is a limit to the size of strings read in (about 5000 bytes).
\end{enumerate}
\subsection{Using wxExpr}
This section is a brief introduction to using the wxExpr package.
First, some terminology. A {\it wxExprDatabase}\/ is a list of {\it clauses},
each of which represents an object or record which needs to be saved to a file.
A clause has a {\it functor}\/ (name), and a list of attributes, each of which
has a value. Attributes may take the following types of value: string, word,
integer, floating point number, and list. A list can itself contain any
type, allowing for nested data structures.
Consider the following code.
\begin{verbatim}
wxExprDatabase db;
wxExpr *my_clause = new wxExpr("object");
my_clause->AddAttributeValue("id", (long)1);
my_clause->AddAttributeValueString("name", "Julian Smart");
db.Append(my_clause);
ofstream file("my_file");
db.Write(file);
\end{verbatim}
This creates a database, constructs a clause, adds it to the database,
and writes the whole database to a file. The file it produces looks like
this:
\begin{verbatim}
object(id = 1,
name = "Julian Smart").
\end{verbatim}
To read the database back in, the following will work:
\begin{verbatim}
wxExprDatabase db;
db.Read("my_file");
db.BeginFind();
wxExpr *my_clause = db.FindClauseByFunctor("object");
int id = 0;
wxString name = "None found";
my_clause->GetAttributeValue("id", id);
my_clause->GetAttributeValue("name", name);
cout << "Id is " << id << ", name is " << name << "\n";
\end{verbatim}
Note the setting of defaults before attempting to retrieve attribute values,
since they may not be found.