home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / CALCPLUS.ZIP / CALCPLUS.TXT < prev    next >
Encoding:
Text File  |  1996-04-02  |  28.5 KB  |  772 lines

  1.  
  2.                THE CALC PLUS CLASS LIBRARY
  3.  
  4.                   by Vladimir Schipunov,
  5.  
  6.                    Copyright (c) 1996.
  7.  
  8.               Version 1.0, April 2, 1996
  9.  
  10.  
  11.  
  12.                         CONTENTS
  13.  
  14.           1.      What is CalcPlus library.
  15.           2.      Distribution and warranty notice.
  16.           3.      Installation and running examples.
  17.           4.      How it works.
  18.           4.1     Lexical analyzer.
  19.           4.2     Class CType hierarchy.
  20.           4.3     Class Expression hierarchy.
  21.           4.4     Language and YACC rules.
  22.           4.5     Interface with C++.
  23.           4.6     Modifying source code.
  24.           5.      Known bugs and problems.
  25.           6.      Appendix. Language description.
  26.  
  27.  
  28.   1. What is CalcPlus library.
  29.   ----------------------------
  30.  
  31.   The CalcPlus library is the C++ class library which provides an ability
  32.   to use your own programming language built into C++ project. Almost any
  33.   complex C++ application needs to be tuned by some external description,
  34.   e.g. INI file. CalcPlus generalizes this approach, any algorithm or any
  35.   constant needed by application can be carried out into the special file,
  36.   when process comes to the key point, it calls function or procedure stored
  37.   in the text file. Interpreter runs the function and process returns back
  38.   to C++ code. Library contains the interpreter which understands simple
  39.   nameless procedural language. Bi-directional communication between C++ and
  40.   the code for interpreter available.
  41.  
  42.   If you develop C++ project and want to provide user access to the algorithm
  43.   of application, its constants or schemes, then probably you can make use of
  44.   the CalcPlus class library.
  45.  
  46.   Version of the language that comes with the library allows to use functions,
  47.   procedures, blocks, preprocessor, global and local variables and constants,
  48.   if/for/while statements. Each variable can have value of type: nil, bool,
  49.   long, float, string, date. Type definitions and arrays are allowed. Functions
  50.   and procedures may be recursive. New functions written in C++ may be easily
  51.   added to the language. Syntax of the language can be modified by changing
  52.   YACC rules. Interpreter is fast enough and may be helpful for many tasks.
  53.  
  54.   Interpreter was successfully used in server application of Btrieve-based
  55.   financial software. Often changing on requests of customers parts of C++
  56.   code were moved into special file, which was interpreted by CalcPlus.
  57.  
  58.   The other application of the library was emulation Clipper machine (except
  59.   "code blocks"), this allowed to debug C-extensions written for Clipper
  60.   in normal C++ environment. (Actually, interpreter has a lot of common
  61.   with Clipper and runs with the same speed on 16-bit platform, on 32-bit
  62.   platform it is faster).
  63.  
  64.   Interpreter was written in 1995 during approximately 3 months. Parts of
  65.   older C++ and YACC code were used. This is the first freeware release.
  66.   Library pretends to be compiler/OS independent. This means you can
  67.   compile it on any OS with any C++ compiler, YACC required. Templates,
  68.   exception handling and RTTI were not used for compatibility with older
  69.   compilers.
  70.  
  71.  
  72.   2. Distribution and warranty notice.
  73.   ------------------------------------
  74.  
  75.   The CalcPlus Class Library is freeware, you may use, modify and redistribute
  76.   it under the condition that copyright notice is not removed from the source
  77.   code.
  78.  
  79.   NO WARRANTY OF ANY KIND, YOU USE THIS SOFTWARE ON YOUR OWN RISK.
  80.  
  81.   Author:
  82.  
  83.     Vladimir Schipunov, 25 years,
  84.  
  85.     email:  vschipun@cammail1.attmail.com
  86.     phone:  1-908-2716881
  87.  
  88.   Any comments, suggestions, extensions, bugs information are very welcome.
  89.  
  90.  
  91.   3. Installation and running examples.
  92.   -------------------------------------
  93.  
  94.   To install the class library, unzip file calcplus.zip.
  95.   In UNIX platforms you probably will need to use options -a -L for unzip,
  96.   these options are needed to convert file names to lower case and to convert
  97.   DOS text with Carriage-Return-Line-Feed to UNIX text with Line-Feed.
  98.  
  99.   DOS:    pkunzip calcplus.zip
  100.   UNIX:   unzip -a -L calcplus.zip
  101.  
  102.   This version of archive contains files:
  103.  
  104.   calcexpr.h          |
  105.   calclex.h           |
  106.   calctype.h          |
  107.   yycalc.h            |
  108.   calcexpr.cpp        |   C++ source code
  109.   calclex.cpp         |
  110.   calctype.cpp        |
  111.   calcplus.cpp        |
  112.   calclib.cpp         |
  113.   yycalc.yac      YACC source code
  114.   calc.mak        makefile for DOS
  115.   gcalc.mak       makefile for UNIX
  116.   readme          short description of the archive
  117.   calcplus.txt    this file
  118.   hello           Hello, world!
  119.   example         selfcheck and example of program
  120.   prime           example of program
  121.   pi              example of program
  122.  
  123.  
  124.   To build the interpreter you will need YACC and C++ compiler.
  125.  
  126.   DOS:  Command line options for some widely used C++ compilers for DOS are
  127.         written in the file calc.mak. Uncomment or change CC and LINK to your
  128.         C++ compiler and specify your version of YACC if necessary.
  129.         Run make utility:
  130.  
  131.         make -f calc.mak
  132.  
  133.   UNIX: gcalc.mak is the makefile for GNU C++, simply run:
  134.  
  135.         make -f gcalc.mak
  136.  
  137.   Library was carefully tested for use with many versions of popular compilers:
  138.   Borland, Watcom, Microsoft, Zortech, GNU. Generally, you should not have
  139.   problems with building the interpreter. However, if you have problems,
  140.   please contact me.
  141.  
  142.   The first thing you should do after building the interpreter is to check it:
  143.  
  144.       a)  calc example
  145.  
  146.           This is the primary check of correct work of the interpreter.
  147.           File 'example' contains most of interpretable syntax constructions.
  148.           If version works correctly output should be:
  149.  
  150.           {0,1,4,9}
  151.           {0,1,4,9,{1,2,3}}
  152.           {0,1,9,{1,2,3}}
  153.           1 7 255
  154.           {a,b,c}
  155.           {a,{d,e,f},c}
  156.           {a,{d,TRUE,f},c}
  157.           3 ab 1
  158.           exiting...
  159.  
  160.       b)  calc pi [Number of iterations]
  161.  
  162.           If interpreter works right you should see
  163.           something around PI number.
  164.  
  165.       c)  calc prime [Upper limit]
  166.  
  167.           This test calculates prime numbers below
  168.           the upper limit, 1000 by default.
  169.  
  170.   Command line switch /d can be added to trace the program, e.g.:
  171.  
  172.           calc prime 100 /d
  173.  
  174.   Note, that interpreter uses recursive algorithms and requires enough
  175.   space on the stack. So, if you get runtime error 'stack overflow',
  176.   increase the stack size.
  177.  
  178.   If interpreter works right, you can begin its adaptation for your own tasks.
  179.   Here is the general description of the library.
  180.  
  181.  
  182.   4. How it works.
  183.   ----------------
  184.  
  185.   First of all, interpreter designed using YACC (yet another compiler of
  186.   compilers). Hand written lexical analyzer takes input from the file(s),
  187.   yyparse() function processes input and builds program as the tree of
  188.   instructions. Each node of the tree has its own value, execution goes
  189.   from the child nodes to the root.
  190.  
  191.   So, CalcPlus consists of:
  192.  
  193.       lexical analyzer,
  194.       yacc parser,
  195.       basic types hierarchy,
  196.       hierarchy of language instructions.
  197.  
  198.  
  199.   4.1. Lexical analyzer.
  200.   ----------------------
  201.  
  202.   In general function YLex::yylex() is the traditional translator of input
  203.   stream into tokens for yacc parser. Class YLex takes care of token
  204.   analysis, simple preprocessing is performed. However, there are some
  205.   features listed below.
  206.  
  207.   Tokens are divided into two parts - the first contains key words, signs of
  208.   arithmetic operations, etc., the second part contains tokens returned
  209.   by descendors of YLex class. Overloadable method YLex::__name() may
  210.   find the word in the lists of already defined symbols: functions,
  211.   procedures, structures, variables or constants. At the first case
  212.   token lx*** used, at the second - yy***.
  213.  
  214.   Several simple container classes provide storage and linear search
  215.   of the objects and references to them. There is also stack container,
  216.   objects stored in stack are destroyed after pushing them, so often
  217.   only references to the objects are pushed into stack.
  218.  
  219.   Preprocessing is performed by pushing into the stack of input streams.
  220.   Only 'include', 'define', 'ifdef', 'endif' directives are supported.
  221.   Input stream is an 'ifstream' for file input and 'istrstream' for
  222.   preprocessor.
  223.  
  224.   Symbol '->' is translated as 'implementation'. When interpreter
  225.   finds statement 'A -> B' it assumes that 'if A then B end' occurred.
  226.  
  227.   Strings separated by both '...' and "..." are allowed.
  228.  
  229.   Comments are of C++ style:
  230.  
  231.           //  This is comment
  232.           /*  Another comment */
  233.  
  234.   Case of letters is insignificant.
  235.  
  236.   In all other senses lexical analyzer acts like any other yylex function.
  237.  
  238.  
  239.   4.2. Class CType hierarchy.
  240.   ---------------------------
  241.  
  242.   Class CType is the base class for all classes corresponding to the CalcPlus
  243.   types. They are: CNil, CBool, CLong, CDouble, CString, CDate, CArray.
  244.   These types may be used for writing program for the interpreter. When
  245.   yylex() finds immediate value in the program, it allocates the object of
  246.   appropriate type. For instance, following constants correspond to types:
  247.  
  248.       2       CLong
  249.       1.2     CDouble
  250.       true    CBool
  251.       'aaa'   CString
  252.       {1,2,3} CArray
  253.  
  254.   New types may be added by simply adding new class inherited from the base
  255.   abstract class CType. Values of new types may be returned by C++ functions
  256.   or yyparse() may be changed to translate input tokens into the instances
  257.   of new class. Class CType has a good number of pure virtual methods,
  258.   some of them actually may be set dummy.
  259.  
  260.   First of all, class should provide its identification. Unique numeric
  261.   identifier is received from enumeration in file calctype.h. This identifier
  262.   should be used in the constructor of CType and returned by method type().
  263.   Method name() is the symbolic identification of the class.
  264.  
  265.   Method copy() returns pointer to the copy of the object allocated
  266.   by operator new. Usually this is call of copying constructor:
  267.  
  268.       CType* copy() const { return CNewClass( *this ); }
  269.  
  270.   Input and output methods should be overwritten as well. They are:
  271.  
  272.       void print( ostream& ) const;
  273.       void get( istream& );
  274.  
  275.   Other important methods are comparison and assignment:
  276.  
  277.       CType& operator =( const CType& t );
  278.       compare( const CType& ) const;
  279.  
  280.   In order to provide standard implementation of these operations for
  281.   simple objects represented by sequence of bytes, methods data(), size()
  282.   and ptr() are used. These methods are intended to give an access to binary
  283.   data of objects. The only difference between data() and ptr() is that data()
  284.   is const method and it should be used in most cases rather than method ptr().
  285.  
  286.       const void *data() const;
  287.       void *ptr();
  288.       size() const;
  289.  
  290.   Class CArray is only non-primitive example of data type. It implements
  291.   data() and ptr() methods to return null pointer and overloads methods of
  292.   comparison and assignment. Arrays may be indexed by strings. Field
  293.   CArray::structure points to the array of CString's, operator[](const char*)
  294.   looks for the pattern string in the index array and returns reference
  295.   to the object of the array, which has the same index as the element of
  296.   CArray::structure. String indexes are used with structure types:
  297.  
  298.       struct abc {a,b,c};
  299.       abc a;
  300.       echo a.b;
  301.  
  302.   This will be translated as the CArray indexed by CArray {'a','b','c'}
  303.   and echo a['b']. Such definitions may be useful though they are not
  304.   strict. No optimization made for speed of the index search.
  305.  
  306.   Classes of the CType hierarchy are relatively simple. For details of
  307.   realization refer to the source code in file calctype.cpp.
  308.  
  309.  
  310.   4.2. Class Expression hierarchy.
  311.   --------------------------------
  312.  
  313.   Classes of Expression hierarchy are the main part of the interpreter.
  314.   All lexical input after parsing is converted into the tree of the
  315.   instances of Expression inheritants as the nodes.
  316.  
  317.   Each node, as it is the instance of Expression, has:
  318.  
  319.       1) field 'flags' which shows the current state of the node
  320.       2) field 'v' which is the pointer to the value of the node
  321.       3) method 'Calc' which is called every time when node is being
  322.          calculated
  323.  
  324.   Let us see what the process actually does during interpretation. Recursive
  325.   method Expression::Calculate runs first at child nodes, if the execution
  326.   of child nodes was not interrupted by setting non-zero flags, then method
  327.   Calc() of the node will be called. Calc() refers to the values of its child
  328.   nodes. For instance, if we have inherited class Addition from the abstract
  329.   class Expression, then method Addition::Calc() could look like:
  330.  
  331.       void Addition::Calc()
  332.       {
  333.           *v = *child[0]->v + *child[1]->v;
  334.       }
  335.  
  336.   More precisely, we should check the type of arguments, because this is an
  337.   interpreter and there is no type checking in compilation time.
  338.   So, the method rather should be:
  339.  
  340.       void Addition::Calc()
  341.       {
  342.           if( child[0]->type()!=idLong ||
  343.               child[1]->type()!=idLong )
  344.           {
  345.               flags = exError;
  346.               return;
  347.           }
  348.           delete v;
  349.           v = new CLong;
  350.           (CLong&)(*v) = (CLong&)(*child[0]->v) + (CLong&)(*child[1]->v);
  351.       }
  352.  
  353.   Process is controlled by the state of bit flags of the nodes. There are
  354.   normal flags, like indication of function return or exit from while/for
  355.   statement, and flags showing that runtime error occurred. Flags are copied
  356.   from the children to parents. Analysis of the state of flags can show the
  357.   location of node where there was error.
  358.  
  359.   Every statement written in input language is translated to the instance
  360.   of corresponding class of Expression hierarchy. This is the picture of
  361.   the hierarchy.
  362.  
  363.  
  364.       Expression                      base class
  365.       |
  366.       |-------XImmediate              immediate value
  367.       |       |
  368.       |       +-------XEndl           line-feed constant
  369.       |
  370.       |-------XBreak                  exit from for/while
  371.       |
  372.       |-------XAr1                    unary arithmetic
  373.       |       |
  374.       |       +-------XBool1          unary boolean
  375.       |
  376.       |-------XAr2                    binary arithmetic
  377.       |       |
  378.       |       +-------XComparison     comparison
  379.       |       |
  380.       |       +-------XBool2          binary boolean
  381.       |
  382.       |-------XVariable               variable
  383.       |
  384.       |-------XEcho                   output on cout
  385.       |
  386.       |-------XConditional            if ... then ... else ... end
  387.       |
  388.       |-------XLoop                   like 'continue' in C
  389.       |
  390.       |-------XWhile                  while/for
  391.       |
  392.       |-------XBlock                  begin ... end
  393.       |       |
  394.       |       +-------XFunction       func/proc ... end
  395.       |               |
  396.       |               +-------XUserFunction       external C++ functions
  397.       |
  398.       |-------XCall                   function call: f(1,2,3)
  399.       |       |
  400.       |       +-------XDynamic        function by name: &('f')(1,2,3)
  401.       |
  402.       |-------XReturn                 return expr
  403.       |
  404.       +-------XSet                    arrays: {1,2,{1,2,3}}
  405.  
  406.  
  407.   Though C++ is much more easier language than English, and full description
  408.   of used algorithms and methods can be found in file calcexpr.cpp, we will
  409.   discuss in the next paragraphs some non-obvious points of architecture of
  410.   the Expression hierarchy.
  411.  
  412.   For storage values of variables class Var is used. There may be many
  413.   references (nodes of the tree) to the variable in different expressions,
  414.   each reference is the instance class XVariable. Class XVariable has fields:
  415.  
  416.       PrintObj* obj;
  417.       CType** ptr;
  418.       int ref;
  419.  
  420.   Field obj is used for debugging output, ptr for setting new value to
  421.   the variable. Field ref used as flag for passing argument to the function by
  422.   reference. This field is set by XCall class temporally while function works.
  423.  
  424.   Method XVariable::Calc() acts in different manners depending of the number
  425.   of child nodes. We assume, that if the number of children is zero, then
  426.   this is the usage of variable inside of other expression, e.g. (x+y). If
  427.   node of XVariable class has only one child node, then this is the operation
  428.   of assignment: x := expr. When the number of child nodes is two, this is
  429.   array element inside of the expression; (x[i]+y[j]). The only case left is
  430.   three child nodes - this is assignment to the array element: x[i] := expr.
  431.   child[0] is considered to be an array, child[1] index in the array,
  432.   child[2] is expression which is assigned.
  433.  
  434.   Class XBlock is the composite expression consisting of a number of
  435.   subexpressions. In the input language corresponding statement is:
  436.  
  437.       begin
  438.           expr1
  439.           expr2
  440.           ...
  441.           exprn
  442.       end
  443.  
  444.   Every block bounds visibility of variables defined inside of it.
  445.   That is why class XBlock has fields: vars, funcs and structs.
  446.   Actually list of functions used only in global context.
  447.  
  448.   Function is the block, its arguments are local variables. Function
  449.   has only one child node of class XBlock, which is the body of the function.
  450.  
  451.   Like XVariable references to Var, XCall references to XFunction.
  452.   Arguments for function are child nodes of XCall. Method XCall::TieArgs()
  453.   is called twice. The first call is to assign values of the arguments
  454.   to the local variables of XFunction. The second is to assign back
  455.   values for arguments passed by reference.
  456.  
  457.   It is easy to see that all algorithm with keeping temporary results
  458.   of calculation in the nodes of the tree does not allow recursive
  459.   calls of functions. To remove this problem method Expression::Recursion
  460.   used. There is a stack of pointers to the values. By the signal, all
  461.   subnodes of the function put their values onto the stack. This action
  462.   is synchronized with the passing arguments in method XCall::TieArgs().
  463.  
  464.   There is no separate class XFor. Class XWhile provides both types of
  465.   iterations: for and while.
  466.  
  467.   Most of other classes are obvious and intuitively clear.
  468.  
  469.  
  470.   4.4. Language and YACC rules.
  471.   -----------------------------
  472.  
  473.   Class CalcPlus is derived from the class YLex. It overloads method yyparse()
  474.   for YACC parsing of the tokens from the input stream. Language is described
  475.   by the set of rules for YACC, generally, every rule simply translates
  476.   its arguments to the appropriate instance of class Expression hierarchy.
  477.   For correct context handling, stack mechanism is used. Each recursive
  478.   syntax construction has corresponding stack container in the class
  479.   CalcPlus, they are:
  480.  
  481.       LexStack Blocks;    //  blocks
  482.       LexStack Calls;     //  function calls
  483.       LexStack Cond1;     //  'if'    part of the condition
  484.       LexStack Cond2;     //  'else'  part of the condition
  485.       LexStack Sets;      //  sets
  486.       LexStack Idx;       //  array indexes
  487.  
  488.   Often used definitions XBEG, XEND, XSEQ are intended for handling
  489.   current block context. When new variable defined, we store it in the
  490.   list of variables of the current block. if/else/for/while statements
  491.   have implicit blocks inside of them:
  492.  
  493.       if a then
  494.           a:=b;
  495.       end;
  496.  
  497.   This is actually translated as:
  498.  
  499.       if a then
  500.           begin
  501.               // local variables may be defined here
  502.               a:=b;
  503.           end;
  504.       end;
  505.  
  506.   Class CalcPlus overloads method __name and searches for symbols that are
  507.   already defined. This makes syntax analysis easier. Method Link uses
  508.   recursive tree search for connecting XCall nodes with the XCall.
  509.   Simple diagnostic is done.
  510.  
  511.   Method UserSym() is not implemented. It was initially added for different
  512.   extensions. For example, we change method __name to translate symbols
  513.   beginning with letter '@' as lxUser:
  514.  
  515.       Token CalcPlus::__name()
  516.       {
  517.           Token t = YLex::__name();
  518.           if( t == lxName && *Lex == '@' )
  519.           {
  520.               Expression* e = new XImmediate( new CString( Lex+1 ));
  521.               YYLVAL( e );
  522.               return lxUser;
  523.           }
  524.           ...
  525.       }
  526.  
  527.   When function yyparse() gets such token it calls method UserSym().
  528.   There two possible calls: with one or two arguments. One argument,
  529.   if token is detected on the right side of assignment, two arguments,
  530.   if token is on the left. Possible implementation of method UserSym may be:
  531.  
  532.       Expression* CalcPlus::UserSym( Expression *e1, Expression *e2 )
  533.       {
  534.           Expression *e = new XEcho;
  535.           if( e1 ) e->Add( e1 );
  536.           if( e2 ) e->Add( e2 );
  537.           return e;
  538.       }
  539.  
  540.   So, the statement "@Hello := ' World!';" will print: Hello World!
  541.  
  542.  
  543.   4.5. Interface with C++.
  544.   ------------------------
  545.  
  546.   It is possible both to call C++ code from interpreter code
  547.   as well as to call interpreter functions and procedures from C++.
  548.  
  549.   There are a number of definitions at the end of file calcexpr.h
  550.   to help writing C++ function visible from the interpreter.
  551.   Let's see the implementation of functions EMPTY and GETENV:
  552.  
  553.       USER_FUNC( Empty )      //  Is value empty?
  554.           DEF_ARGX( 0, x )    //  We don't know the type of argument
  555.           RETURNS( Bool )     //  Function returns TRUE or FALSE
  556.           ret = x.empty();    //  Getting the result
  557.       USER_END                //  Done
  558.  
  559.       USER_FUNC( Getenv )                 //  Reading environment variable
  560.           DEF_ARGV( 0, var, String )      //  Expecting string argument
  561.           RETURNS( String )               //  Result will be the string also
  562.           const char* s = getenv( var );  //  Calling C function
  563.           ret = s ? s : "";               //  Check if var is not in env.
  564.       USER_END                            //  Done
  565.  
  566.   Functions and procedures must be registered before running
  567.   the interpreter to make them visible from the program. Function
  568.   UserLib defined in module calclib.cpp performs the registration:
  569.  
  570.       void UserLib()
  571.       {
  572.           RegFunc( "EMPTY", Empty );
  573.           RegFunc( "GETENV", Getenv );
  574.  
  575.           //
  576.           //  Other functions
  577.           //
  578.       }
  579.  
  580.   If number of arguments exceed one, it should be passed as the third
  581.   parameter. For procedures DEF_PROC and RegProc are used.
  582.  
  583.   Call of the interpreter function from C++ code is illustrated in file
  584.   calcplus.cpp. Function 'atexit' called when program finishes.
  585.   Method CalcPlus::Call() takes as arguments pointer to function name,
  586.   number of arguments, and pointers to CType arguments:
  587.  
  588.       if( calc.Global->funcs( "atexit" ))
  589.       {
  590.           CString s("exiting... ");
  591.           calc.Call( "atexit", 1, &s );
  592.       }
  593.  
  594.  
  595.   4.6. Modifying source code.
  596.   ---------------------------
  597.  
  598.   If you are going to use the library in your project, then most
  599.   likely you will have to change its source code for your own needs.
  600.   There are different ways of source code modification, and you should
  601.   choose the better one. Which one is better depends of how serious
  602.   changes you need.
  603.  
  604.   The simplest way to extend the library is to add new functions visible
  605.   from the interpreter. This can be done by modifying file calclib.cpp.
  606.  
  607.   Another way of easy modification is the change of language syntax,
  608.   see file yycalc.yac.
  609.  
  610.   More difficult solution may require change of the hierarchies CType and
  611.   Expression. In this case you should overwrite necessary methods and probably
  612.   change YACC rules. Actually whole CType hierarchy can be replaced by your
  613.   own hierarchy, if you already have something like that in your project.
  614.  
  615.   As the example of changes in source code, let us consider steps
  616.   necessary for implementation of big numbers arithmetic:
  617.  
  618.       a)  We need CType inheritor, which will store, print, and calculate
  619.           very big numbers (hundreds of significant digits).
  620.  
  621.       b)  Method Calc() of classes Ar1, Ar2, Comparison should be changed
  622.           to be able handle big numbers.
  623.  
  624.       c)  YLex::yylex() must detect big number from the input stream and
  625.           return corresponding token. This can be done by adding special
  626.           conversion function as well.
  627.  
  628.       d)  CalcPlus::yyparse() must generate new Immediate( new BigNumber )
  629.           when such token detected.
  630.  
  631.   After we have done these steps, hopefully, big numbers arithmetic
  632.   will be available from the interpreter's programs.
  633.  
  634.  
  635.   5. Known bugs and problems.
  636.   ---------------------------
  637.  
  638.   The biggest known problem is obvious: error diagnostic is too simple.
  639.   So the user with low programming experience may have a lot of problems
  640.   trying to write program for the interpreter.
  641.  
  642.   Compiler returns line number 0 when EOF inside of unclosed block detected.
  643.   So, line number 0 is the last line in file.
  644.  
  645.   Complex recursive define directives may work not properly.
  646.   There is no real reason yet to develop full built-in preprocessor.
  647.  
  648.   Passing arguments to function by reference is not absolutely correct.
  649.   There were problems when operator throw was used in C++ code called
  650.   from inside of such function. However, this problem can be easily avoided
  651.   by adding flag to variable, which says that variable has passed its value
  652.   to the function, so operator delete cannot be used for the pointer to value.
  653.  
  654.   If you have found more errors, bugs, problems - please, let me know.
  655.  
  656.  
  657.   6. Appendix. Language description.
  658.   ----------------------------------
  659.  
  660.   This is informal description of CalcPlus interpreter's language.
  661.   Most of the syntax looks and works like the same syntax in other languages.
  662.   Language has a lot of common with C and Clipper.
  663.  
  664.   Like C:
  665.  
  666.       Module is the unit of compilation.
  667.       Program can consist of more than one module.
  668.       Start symbol is MAIN if not redefined.
  669.       File can include other files by #include 'filename' directive.
  670.       Global variables may be defined in the module context.
  671.       Semicolon ';' is the separator between statements.
  672.       Sign '!' is the logical NOT.
  673.  
  674.   Not like C:
  675.  
  676.       Case is insignificant.
  677.       Preprocessor has only 'define', 'ifdef', 'endif' directives.
  678.       No logical operations available for preprocessor.
  679.       There are no static variables.
  680.       Assignment is ':='.
  681.       Strings are declared with both (') and (") separator: 'str1', "str2".
  682.       Unary assignment sign used in comparison: if a=b then ... end;
  683.       EXIT and LOOP keywords are the same as 'break' and 'continue' in C.
  684.       OR, AND keywords used instead of ||, &&.
  685.       ARRAY, ADEL, AADD should be used for array access.
  686.       ARGC, ARGV functions provide access to the command line arguments.
  687.       '<>' used instead of '!=' for logical not_equal.
  688.  
  689.   Functions and procedures must be described before calling, description
  690.   of arguments is not required. Functions and procedures may contain
  691.   return statement. Default return value is NIL.
  692.  
  693.       func a;
  694.       proc b;
  695.  
  696.       ...
  697.           var x:=a(1,2,3);
  698.           b('abc');
  699.       ...
  700.  
  701.       func a(x,y,z)
  702.           return x+y+z;
  703.       end;
  704.  
  705.       proc b(x)
  706.           echo x,endl;
  707.       end;
  708.  
  709.   Arguments preceding with sign '*' are passed to the function by reference.
  710.   Arrays are always passed by reference. Result of the program below will be
  711.   1 2 3 3:
  712.  
  713.       func a(x)
  714.           x:=x+1;
  715.           return x;
  716.       end;
  717.       proc main()
  718.           var x:=0;
  719.           echo a(*x),' ',a(*x),' ';
  720.           echo a( x),' ',a( x);
  721.       end;
  722.  
  723.  
  724.   Blocks are allowed in any place inside of function or procedure:
  725.  
  726.       begin
  727.           expr1;
  728.           expr2;
  729.           ...
  730.           exprn;
  731.       end;
  732.  
  733.   Variables, constants, structures may be declared in any place of
  734.   program, they are visible only inside of block where were defined.
  735.   No type checking. Structures are actually arrays indexed by arrays
  736.   of strings.
  737.  
  738.       var     count := 1;
  739.       const   pi := 3.14;
  740.       struct  abc {a,b,c};
  741.       abc     test;
  742.  
  743.   Output is performed by ECHO statement followed by expressions list.
  744.   ENDL is the Line-Feed constant.
  745.  
  746.       echo '2*2=',2*2,endl;
  747.  
  748.   All control structures: begin, if, for, while, func, proc must be
  749.   closed by keyword 'end'. Variables defined inside of such structures
  750.   are considered as local for them. STEP keyword may be omitted in
  751.   FOR statement, step is 1 by default.
  752.  
  753.       if a=b then
  754.           f1();
  755.       else
  756.           f2();
  757.       end;
  758.  
  759.       for i:=1 to 10 step 2 do
  760.           echo i*i,' ';
  761.       end;
  762.  
  763.       while a>b do
  764.           b := b+1;
  765.       end;
  766.  
  767.   All the arithmetic operations are usual:  ((2+3)-1)*6/2.
  768.  
  769.  
  770.   <EOF>
  771.   -----
  772.