1\section{wxExpr overview}\label{exproverview} 2 3wxExpr is a C++ class reading and writing a subset of Prolog-like syntax, 4supporting objects attribute/value pairs. 5 6wxExpr can be used to develop programs with readable and 7robust data files. Within wxWidgets itself, it is used to parse 8the {\tt .wxr} dialog resource files. 9 10{\bf History of wxExpr} 11 12During the development of the tool Hardy within the AIAI, a need arose 13for a data file format for C++ that was easy for both humans and 14programs to read, was robust in the face of fast-moving software 15development, and that provided some compatibility with AI languages 16such as Prolog and LISP. 17 18The result was the wxExpr library (formerly called PrologIO), which is able to read and write a 19Prolog-like attribute-value syntax, and is additionally capable of 20writing LISP syntax for no extra programming effort. The advantages of 21such a library are as follows: 22 23\begin{enumerate}\itemsep=0pt 24\item The data files are readable by humans; 25\item I/O routines are easier to write and debug compared with using binary files; 26\item the files are robust: unrecognised data will just be ignored by the application 27\item Inbuilt hashing gives a random access capability, useful for when linking 28up C++ objects as data is read in; 29\item Prolog and LISP programs can load the files using a single command. 30\end{enumerate} 31 32The library was extended to use the ability to read and write 33Prolog-like structures for remote procedure call (RPC) communication. 34The next two sections outline the two main ways the library can be used. 35 36\subsection{wxExpr for data file manipulation}\itemsep=0pt 37 38The fact that the output is in Prolog syntax is irrelevant for most 39programmers, who just need a reasonable I/O facility. Typical output 40looks like this: 41 42\begin{verbatim} 43diagram_definition(type = "Spirit Belief Network"). 44 45node_definition(type = "Model", 46 image_type = "Diamond", 47 attribute_for_label = "name", 48 attribute_for_status_line = "label", 49 colour = "CYAN", 50 default_width = 120, 51 default_height = 80, 52 text_size = 10, 53 can_resize = 1, 54 has_hypertext_item = 1, 55 attributes = ["name", "combining_function", "level_of_belief"]). 56 57arc_definition(type = "Potentially Confirming", 58 image_type = "Spline", 59 arrow_type = "End", 60 line_style = "Solid", 61 width = 1, 62 segmentable = 0, 63 attribute_for_label = "label", 64 attribute_for_status_line = "label", 65 colour = "BLACK", 66 text_size = 10, 67 has_hypertext_item = 1, 68 can_connect_to = ["Evidence", "Cluster", "Model", "Evidence", "Evidence", "Cluster"], 69 can_connect_from = ["Data", "Evidence", "Cluster", "Evidence", "Data", "Cluster"]). 70\end{verbatim} 71 72This is substantially easier to read and debug than a series of numbers and 73strings. 74 75Note the object-oriented style: a file comprises a series of {\it clauses}. 76Each clause is an object with a {\it functor}\/ or object name, followed 77by a list of attribute-value pairs enclosed in parentheses, and finished 78with a full stop. Each attribute value may be a string, a word (no quotes), 79an integer, a real number, or a list with potentially recursive elements. 80 81The way that the facility is used by an application to read in a file is 82as follows: 83 84\begin{enumerate}\itemsep=0pt 85\item The application creates a wxExprDatabase instance. 86\item The application tells the database to read in the entire file. 87\item The application searches the database for objects it requires, 88decomposing the objects using the wxExpr API. The database may be hashed, 89allowing rapid linking-up of application data. 90\item The application deletes or clears the wxExprDatabase. 91\end{enumerate} 92 93Writing a file is just as easy: 94 95\begin{enumerate}\itemsep=0pt 96\item The application creates a wxExprDatabase instance. 97\item The application adds objects to the database using the API. 98\item The application tells the database to write out the entire database, 99in Prolog or LISP notation. 100\item The application deletes or clears the wxExprDatabase. 101\end{enumerate} 102 103To use the library, include "wxexpr.h". 104 105\subsection{wxExpr compilation} 106 107For UNIX compilation, ensure that YACC and LEX or FLEX are on your system. Check that 108the makefile uses the correct programs: a common error is to compile 109y\_tab.c with a C++ compiler. Edit the CCLEX variable in make.env 110to specify a C compiler. Also, do not attempt to compile lex\_yy.c 111since it is included by y\_tab.c. 112 113For DOS compilation, the simplest thing is to copy dosyacc.c to y\_tab.c, and doslex.c to 114lex\_yy.c. It is y\_tab.c that must be compiled (lex\_yy.c is included by 115y\_tab.c) so if adding source files to a project file, ONLY add y\_tab.c 116plus the .cc files. If you wish to alter the parser, you will need YACC 117and FLEX on DOS. 118 119The DOS tools are available at the AIAI ftp site, in the tools directory. Note that 120for FLEX installation, you need to copy flex.skl into the directory 121c:/lib. 122 123If you are using Borland C++ and wish to regenerate lex\_yy.c and y\_tab.c 124you need to generate lex\_yy.c with FLEX and then comment out the `malloc' and `free' 125prototypes in lex\_yy.c. It will compile with lots of warnings. If you 126get an undefined \_PROIO\_YYWRAP symbol when you link, you need to remove 127USE\_DEFINE from the makefile and recompile. This is because the parser.y 128file has a choice of defining this symbol as a function or as a define, 129depending on what the version of FLEX expects. See the bottom of 130parser.y, and if necessary edit it to make it compile in the opposite 131way to the current compilation. 132 133%To test out wxExpr compile the test program (samples/wxexpr/wxexpr.exe), 134%and try loading test.exp into the test 135%program. Then save it to another file. If the second is identical to the 136%first, wxExpr is in a working state. 137 138\subsection{Bugs} 139 140These are the known bugs: 141 142\begin{enumerate}\itemsep=0pt 143\item Functors are permissible only in the main clause (object). 144Therefore nesting of structures must be done using lists, not predicates 145as in Prolog. 146\item There is a limit to the size of strings read in (about 5000 bytes). 147\end{enumerate} 148 149\subsection{Using wxExpr} 150 151This section is a brief introduction to using the wxExpr package. 152 153First, some terminology. A {\it wxExprDatabase}\/ is a list of {\it clauses}, 154each of which represents an object or record which needs to be saved to a file. 155A clause has a {\it functor}\/ (name), and a list of attributes, each of which 156has a value. Attributes may take the following types of value: string, word, 157integer, floating point number, and list. A list can itself contain any 158type, allowing for nested data structures. 159 160Consider the following code. 161 162\begin{verbatim} 163wxExprDatabase db; 164 165wxExpr *my_clause = new wxExpr("object"); 166my_clause->AddAttributeValue("id", (long)1); 167my_clause->AddAttributeValueString("name", "Julian Smart"); 168db.Append(my_clause); 169 170ofstream file("my_file"); 171db.Write(file); 172\end{verbatim} 173 174This creates a database, constructs a clause, adds it to the database, 175and writes the whole database to a file. The file it produces looks like 176this: 177 178\begin{verbatim} 179object(id = 1, 180 name = "Julian Smart"). 181\end{verbatim} 182 183To read the database back in, the following will work: 184 185\begin{verbatim} 186wxExprDatabase db; 187db.Read("my_file"); 188 189db.BeginFind(); 190 191wxExpr *my_clause = db.FindClauseByFunctor("object"); 192int id = 0; 193wxString name = "None found"; 194 195my_clause->GetAttributeValue("id", id); 196my_clause->GetAttributeValue("name", name); 197 198cout << "Id is " << id << ", name is " << name << "\n"; 199\end{verbatim} 200 201Note the setting of defaults before attempting to retrieve attribute values, 202since they may not be found. 203 204