home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / CALCPLUS.ZIP / CALCEXPR.H < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-02  |  12.8 KB  |  560 lines

  1. /*******************************************************
  2.  
  3.     The CalcPlus Class Library Version 1.0,
  4.     Author: Vladimir Schipunov, Copyright (C) 1996
  5.  
  6.     This library is free software. Permission to use,
  7.     copy, modify and redistribute the CalcPlus library
  8.     for any purpose is hereby granted without fee,
  9.     provided that the above copyright notice appear
  10.     in all copies.
  11.  
  12. *******************************************************/
  13.  
  14. #ifndef __CALCEXPR_H
  15. #define __CALCEXPR_H
  16. #include "calclex.h"
  17.  
  18. //
  19. //  This header file contains description of the classes
  20. //  of Expression hierarchy. Instructions to the interpreter
  21. //  are all coded as the inheritants of class Expression.
  22. //
  23. //  Class Expression is the base of hierarchy.
  24. //  It provides representaion of the program to the interpreter
  25. //  as the tree of expressions. When process comes to the node
  26. //  of the tree, node calls its child nodes at first and then
  27. //  calculates its own value.
  28. //
  29. //  So, every node has its value, which is pointed by CType* v.
  30. //  Method Calc calculates the value of the node taking values
  31. //  of the child nodes as the arguments. For instance, the basic
  32. //  implementation of addition could look like:
  33. //
  34. //  void Addition::Calc()
  35. //  {
  36. //      *v = *child[0]->v + *child[1]->v;
  37. //  }
  38. //
  39. //  Process is running through all the tree and executes recursive
  40. //  method Calculate. During the execution field 'flags' is being checked
  41. //  for detecting errors, finishing calculation of current subtree, etc.
  42. //
  43. //  Such a simple algorithm has at least one problem - no recursion
  44. //  is allowed. In order to provide the recursion calls inside of
  45. //  the interpreter we have stack which is used only when function loop
  46. //  is matched.
  47. //
  48.  
  49. class Expression : public LexObj
  50. {
  51. protected:
  52.      virtual void Calc();   //  should be overloaded
  53.                             //  in most cases
  54.  
  55.      CheckType( int... );   //  Checks type of child nodes
  56.  
  57.      void printx( ostream &s, Expression* ) const;
  58.      precedence( const Expression& ) const;
  59.  
  60. public:
  61.      enum {
  62.           exError = 1,      //  runtime error
  63.           exLoop  = 2,      //  set by LOOP
  64.           exDone  = 4,      //  set by RETURN
  65.           exExit  = 8,      //  set by EXIT
  66.           exLink  = 16,     //  undefined function
  67.           exArgs  = 32,     //  wrong number of arguments
  68.           exRet   = 64      //  ret with or without result
  69.      };
  70.      typedef unsigned ExFlags;
  71.      ExFlags flags;
  72.  
  73.      enum                   //  precedence
  74.      {
  75.         opBool2,
  76.         opBool1,
  77.         opComp,
  78.         opAr2,
  79.         opAr1,
  80.         opPower,
  81.         opCast,
  82.         opTerm
  83.     };
  84.  
  85.     int n;                  //  tree implementation
  86.     Expression *father;
  87.     Expression **child;
  88.     CType *v;               //  value of the node
  89.  
  90.     virtual void print( ostream &s ) const;
  91.     virtual op() const { return opTerm; }
  92.     virtual range() const { return 0; }
  93.  
  94.     virtual Expression* Add( Expression* );
  95.     virtual void Descendor( Expression*e ) { if( e ) e->father = this; }
  96.     virtual Depth() const { return father ? father->Depth()+1 : 0; }
  97.     virtual void Space( ostream& ) const;
  98.     virtual AutoSpace() const { return 0; }
  99.     virtual XFunction* xfunction() { return father ? father->xfunction() : 0; }
  100.     virtual XBlock* xblock() { return father ? father->xblock() : 0; }
  101.     virtual xref( int = -1 ) { return 0; }
  102.  
  103.     typedef void (Expression::*ExprF)();
  104.     virtual void Recursion( ExprF, int dir = 0, int check = 1 );
  105.     virtual void Link(){ flags = 0; }
  106.     virtual void Push();
  107.     virtual void Pop();
  108.     loop( Expression* ) const;
  109.     void RecStep( ExprF, int );
  110.     void RecDebug();
  111.  
  112.     Expression( int n = 0 );
  113.     Expression( int, Expression*... );
  114.     virtual ~Expression();
  115.     virtual void Calculate();
  116.     virtual void Iterate();
  117.     virtual const Expression* LocateError( int = exError ) const;
  118.     static Debug;
  119. };
  120.  
  121. #define DREC void Recursion( ExprF f, int dir = 0, int flags = 1 )
  122. #define XSTD {Expression::Recursion( f, dir, flags );}
  123. #define XREC(x) {if( x ) x->Recursion( f, dir, flags );}
  124.  
  125. //
  126. //  Help class needed for recursive calls
  127. //
  128.  
  129. class PtrStack
  130. {
  131. public:
  132.     CType** stack;
  133.     int i;
  134.     PtrStack() : stack( 0 ), i( 0 ){}
  135.     ~PtrStack(){ delete[] stack; }
  136.     void Push( CType* t );
  137.     CType* Pop();
  138. };
  139.  
  140. //
  141. //  Immediate value like 1, 9.9, false or 'abc'
  142. //
  143.  
  144. class XImmediate : public Expression
  145. {
  146. public:
  147.     XImmediate( CType *u ) { v = u; }
  148.     void print( ostream& ) const;
  149.     void Calculate(){}
  150.     void Calc(){}
  151.     void Push(){}
  152.     void Pop(){}
  153. };
  154.  
  155. //
  156. //  Line feed
  157. //
  158.  
  159. class XEndl : public XImmediate
  160. {
  161. public:
  162.     XEndl();
  163.     void print( ostream& ) const;
  164. };
  165.  
  166. //
  167. //  Unary arithmetic operation
  168. //
  169.  
  170. class XAr1 : public Expression
  171. {
  172. protected:
  173.     char sign;
  174.     void Calc();
  175. public:
  176.     XAr1( char c, Expression *e ) : Expression( 1, e ), sign( c ) {}
  177.     op() const { return opAr1; }
  178.     void print( ostream& ) const;
  179. };
  180.  
  181. //
  182. //  Binary arithmetic operation
  183. //
  184.  
  185. class XAr2 : public Expression
  186. {
  187. protected:
  188.     char sign;
  189.     void Calc();
  190. public:
  191.     XAr2( Expression *e1, char c, Expression *e2 ) :
  192.         Expression( 2, e1, e2 ), sign( c ) {}
  193.     op() const { return opAr2; }
  194.     range() const { return sign == '*' || sign == '/'; }
  195.     void print( ostream& ) const;
  196. };
  197.  
  198. //
  199. //  Unary boolean operation
  200. //
  201.  
  202. class XBool1 : public XAr1
  203. {
  204. protected:
  205.     void Calc();
  206. public:
  207.     XBool1( Expression *e ) : XAr1( '!', e ) {}
  208.     op() const { return opBool1; }
  209. };
  210.  
  211. //
  212. //  Binary boolean operation
  213. //
  214.  
  215. class XBool2 : public XAr2
  216. {
  217. protected:
  218.     void Calc();
  219. public:
  220.     XBool2( Expression *e1, char c,
  221.         Expression *e2 ) : XAr2( e1, c, e2 ) {}
  222.     op() const { return opBool2; }
  223.     range() const { return sign=='&' ? 3 :
  224.             sign=='|' ? 2 : sign=='i' ? 1 : 0; }
  225. };
  226.  
  227. //
  228. //  Comparison
  229. //
  230.  
  231. class XComparison : public XAr2
  232. {
  233. private:
  234.     void Calc();
  235. public:
  236.     XComparison( Expression *e1, char c,
  237.         Expression *e2 ) : XAr2(e1,c,e2) {}
  238.     op() const { return opComp; }
  239. };
  240.  
  241. //
  242. //  Class Var is used for holding values of interpreter's variables
  243. //
  244.  
  245. class Var : public PrintObj
  246. {
  247. public:
  248.     char *name;
  249.     CType *v;
  250.     int isConst;
  251.  
  252.     Var( const char*, int isConst = 0 );
  253.     ~Var();
  254.     void print( ostream& ) const;
  255. };
  256.  
  257. //
  258. //  Variable of the interpreter,
  259. //  field ref is non-zero when variable is passed
  260. //  as the reference in the function call.
  261. //  All the arrays are given by reference by default.
  262. //
  263.  
  264. class XVariable : public Expression
  265. {
  266. protected:
  267.     void Calc();
  268. public:
  269.     PrintObj* obj;
  270.     CType** ptr;
  271.     int ref;
  272.  
  273.     XVariable( PrintObj* o, CType** p ) : obj( o ), ptr( p ), ref( 0 ){}
  274.     XVariable( Var* var ) : obj( var ), ptr( &var->v ), ref( 0 ){}
  275.     ~XVariable(){ v= 0; }
  276.     void print( ostream& ) const;
  277.     xref( int r ) { if( r>=0 ) ref = r; return ref; }
  278.     void Calculate()
  279.     {
  280.         if( !n ){ v = *ptr; return; }
  281.         Expression::Calculate();
  282.     }
  283.     void Push();
  284.     void Pop();
  285. };
  286.  
  287. //
  288. //  Output of the expression(s)
  289. //
  290.  
  291. class XEcho : public Expression
  292. {
  293. protected:
  294.     void Calc();
  295. public:
  296.     XEcho(){}
  297.     void print( ostream& ) const;
  298. };
  299.  
  300. //
  301. //  IF ... THEN ... ELSE  ... END;
  302. //
  303.  
  304. class XConditional : public Expression
  305. {
  306. protected:
  307.     void Calc();
  308. public:
  309.     Expression *Then, *Else;
  310.     XConditional( Expression* e, Expression *th, Expression *el = 0 ) :
  311.         Expression( 1, e ), Then( th ), Else( el )
  312.     { Descendor( Then ); Descendor( Else ); }
  313.     ~XConditional(){ delete Then; delete Else; }
  314.     void print( ostream& ) const;
  315.     AutoSpace() const { return 1; }
  316.     DREC
  317.     {
  318.         if( dir ){ XREC( Else ); XREC( Then ); }
  319.         XSTD;
  320.         if(!dir ){ XREC( Then ); XREC( Else ); }
  321.     }
  322. };
  323.  
  324. LEXEMA( LexVar, Var*, 0 )
  325. LEXEMA( LexFunc, XFunction*, 0 )
  326. LEXEMA( LexStruct, CArray*, 0 )
  327.  
  328. //
  329. //  BEGIN ... END;
  330. //
  331.  
  332. class XBlock : public Expression
  333. {
  334. public:
  335.     LexList vars;
  336.     LexList funcs;
  337.     LexList structs;
  338.  
  339.     XBlock();
  340.     void print( ostream& ) const;
  341.     AutoSpace() const { return 1; }
  342.     const Expression* LocateError( int = exError ) const;
  343.     XBlock* xblock(){ return this; }
  344.     void Push();
  345.     void Pop();
  346. };
  347.  
  348. //
  349. //  WHILE ... DO ... END;
  350. //
  351.  
  352. class XWhile : public Expression
  353. {
  354. protected:
  355.     void Calc();
  356. public:
  357.     Expression *Cond;
  358.     Expression *Action;
  359.     Expression *Step;
  360.  
  361.     XWhile( Expression* cond, Expression *action, Expression *step = 0 );
  362.     ~XWhile(){ delete Cond; delete Action; delete Step; }
  363.     void print( ostream& ) const;
  364.     AutoSpace() const { return 1; }
  365.     void Calculate(){ flags = 0; Calc(); }
  366.     DREC
  367.     {
  368.         if( dir ){ XREC( Action ); XREC( Step ); XREC( Cond ); }
  369.         XSTD;
  370.         if(!dir ){ XREC( Cond ); XREC( Step ); XREC( Action ); }
  371.     }
  372. };
  373.  
  374. class XLoop : public Expression
  375. {
  376. protected:
  377.     void Calc();
  378. public:
  379.     XLoop(){}
  380.     void print( ostream& ) const;
  381.     void Push(){}
  382.     void Pop(){}
  383. };
  384.  
  385. //
  386. //  FUNCTION F( ... )  ... END;
  387. //
  388.  
  389. class XFunction : public XBlock
  390. {
  391. public:
  392.     char *name;
  393.     int isProc;
  394.     int busy;
  395.  
  396.     XFunction( int proc = 0, const char* name = 0 );
  397.     ~XFunction(){ delete[] name; }
  398.     virtual Defined() const { return n; }
  399.     void SetName( const char* );
  400.     void AddLocal( const char*, int );
  401.     void print( ostream& ) const;
  402.     Depth() const { return -1; }
  403.     XFunction* xfunction() { return this; }
  404.     void Push();
  405.     void Pop();
  406.     Args() const { return vars.NumObj; }
  407. };
  408.  
  409. //
  410. //  Call to function
  411. //
  412.  
  413. class XCall : public Expression
  414. {
  415. protected:
  416.     void Calc();
  417. public:
  418.     XFunction *Func;
  419.     XCall( XFunction* f ) : Func( f ){}
  420.     void print( ostream& ) const;
  421.     void Link();
  422.     void TieArgs( int before = 1 );
  423.     const Expression *LocateError( int = exError ) const;
  424. };
  425.  
  426. //
  427. //  Let fname be a string value of the name of the function f.
  428. //  We provide the dynamic call to function f as &(fname).
  429. //
  430.  
  431. class XDynamic : public XCall
  432. {
  433. protected:
  434.     void Calc();
  435. public:
  436.     Expression *Ptr;
  437.     LexList *Table;
  438.  
  439.     XDynamic( Expression* e, LexList* t ) : XCall( 0 ),
  440.         Ptr( e ), Table( t ){ Descendor(Ptr); }
  441.     ~XDynamic(){ delete Ptr; }
  442.     void print( ostream& ) const;
  443.     DREC { if( dir ) XREC( Ptr ); XSTD; if( !dir ) XREC( Ptr ); }
  444. };
  445.  
  446. //
  447. //  RETURN
  448. //
  449.  
  450. class XReturn : public Expression
  451. {
  452. protected:
  453.     void Calc();
  454. public:
  455.     XReturn(){}
  456.     XReturn( Expression* e ) : Expression( 1, e ) {}
  457.     void print( ostream& ) const;
  458.     void Link();
  459. };
  460.  
  461. //
  462. //  EXIT
  463. //
  464.  
  465. class XBreak : public Expression
  466. {
  467. protected:
  468.     void Calc();
  469. public:
  470.     XBreak(){}
  471.     void print( ostream& ) const;
  472.     void Push(){}
  473.     void Pop(){}
  474. };
  475.  
  476. //
  477. //  This is an example of the set: { 1, 2, true, 'asd', 5 }.
  478. //  Sets are actually arrays.
  479. //
  480.  
  481. class XSet : public Expression
  482. {
  483. protected:
  484.     void Calc();
  485. public:
  486.     XSet(){}
  487.     Contains( CType* ) const;
  488.     void print( ostream& ) const;
  489.     xref( int = -1 ) { return -1; }
  490. };
  491.  
  492. class XUserFunction;
  493. typedef int (*DefFunction)( XUserFunction* );
  494. typedef XUserFunction* XPF;
  495.  
  496. //
  497. //  This class and definitions below provide convinient way
  498. //  for implementing interpreter's functions in C++.
  499. //  Basic functions are written in module calclib.cpp
  500. //
  501.  
  502. class XUserFunction : public XFunction
  503. {
  504. protected:
  505.     void Calc();
  506. public:
  507.     DefFunction Func;
  508.     XUserFunction( const char* name, DefFunction f,
  509.         int order = 1, int proc = 0 );
  510.     Defined() const { return 1; }
  511.     CheckArgs( int t... ) const;
  512.     CType* Arg( int i = 0 ) const;
  513.     static LexList funcs;
  514.     static Argc;
  515.     static const char** Argv;
  516. };
  517.  
  518. extern void RegFunc( const char*, DefFunction, int order = 1, int proc = 0 );
  519. extern void RegProc( const char*, DefFunction, int order = 1 );
  520. extern void UserLib();
  521.  
  522. #define USER_FUNCTION( name )\
  523.      static name( XUserFunction* xpf ){
  524.  
  525. //  argument i of function of given name has type t
  526.  
  527. #define DEF_ARGV(i,name,t)\
  528.      if( i>=xpf->vars.NumObj ) return 1;\
  529.      CType* argv_tmp_##i = xpf->Arg(i);\
  530.      if( !argv_tmp_##i || argv_tmp_##i->type()!=id##t ) return 1;\
  531.      C##t & name = (C##t &)(*argv_tmp_##i);
  532.  
  533. //  argument i of unknown type
  534.  
  535. #define DEF_ARGX(i,name)\
  536.      if( i>=xpf->vars.NumObj ) return 1;\
  537.      CType& name = *xpf->Arg(i);
  538.  
  539. //  function returns
  540.  
  541. #define RETURNS(t)\
  542.     if(!xpf->v || xpf->v->type()!=id##t)\
  543.     { delete xpf->v; xpf->v = new C##t; }\
  544.     C##t & ret = (C##t &)(*xpf->v);
  545.  
  546. #define USER_FUNC( name )\
  547.     USER_FUNCTION( name )
  548.  
  549. #define USER_PROC( name )\
  550.     USER_FUNCTION( name )\
  551.     if( !xpf->v ) xpf->v = new CNil;
  552.  
  553. #define USER_ERR( msg ) {\
  554.     cerr << msg << endl;\
  555.     return 1;}
  556.  
  557. #define USER_END return 0; }
  558.  
  559. #endif
  560.