// eval5.h

#ifndef __EVAL5_H__
#define __EVAL5_H__

class proglet_t {
   enum {
      MaxTokenLen    =  10,
      MaxStackDepth  =  10,
      MaxSymbols     =  20,
      MaxProgLen     = 100
   };

   typedef enum {
      UnknownS_e,
      skip_e,     // Discard statement, but continue program.
      stop_e      // Terminate program.
   } severity_t;

   typedef char   token_t[MaxTokenLen+1]; // Leave one extra character for the terminating null.

   typedef enum {
      UnknownTT_e,
      identifier_e,
      number_e
   } TokenType_t;

   typedef double	value_t;

   typedef enum {
      function_e,
      constant_e,
      variable_e
   } SymType_t;      // Symbol types.

   typedef struct {
      token_t     name;
      SymType_t   type;
      value_t     value;
   } symbol_t;

   typedef enum {
         PushNum_e, PushSym_e,               // Primary stack operations.
         neg_e,                              // Unary arithmetic operations.
         add_e,      mul_e,   sub_e, div_e,  // Binary arithmetic operations.
         rand_e,                             // Functions of 0 variables.
         abs_e,                              // Functions of 1 variable.
         sin_e,      cos_e,   tan_e,
         asin_e,     acos_e,  atan_e,
         atan2_e,                            // Functions of 2 variables.
         print_e,    assign_e                // Statements.
   } instr_t;

   typedef union {
      instr_t  instr;
      symbol_t *sym;
      value_t  num;
   } program_t;

   char        *statement;
   int         StmtLen,
               StmtIndex;

   token_t     token;
   value_t     TokenValue;
   TokenType_t TokenType;

   value_t     stack[MaxStackDepth];
   int         StackDepth;
   symbol_t    symbols[MaxSymbols];
   int         NumFunctions,
               NumSymbols,
               ProgLen;

   program_t   *prog;

   bool     equal (token_t a, token_t b);
   void     error (severity_t severity, char *msg1, char *msg2 = 0);
   void     AddInstr (instr_t instr);
   void     AddInstr (value_t num);
   void     AddInstr (instr_t instr, symbol_t *sym);
   symbol_t *FindSymbol (token_t name);
   symbol_t *CreateSymbol (token_t name, SymType_t type, value_t value = 0.0);
   value_t  GetValue (token_t name, bool AllowFunctions);
   void     GetNextToken (void);
   void     InitLexer (char *line);
   int      ParseArgList (void);
   void     ParsePrimary (void);
   void     ParseFactor (void);
   void     ParseTerm (void);
   void     ParseExpression (void);
   void     ParsePrint (void);
   void     ParseAssignment (void);
   bool     ParseStatement (void);
   void     InitSymbolTable (void);
   void     push (value_t v);
   value_t  pop (void);

public:  // The public interface for the proglet class.
   proglet_t ();					// Constructor.
   ~proglet_t ();					// Destructor.
   void reinit (void);				// For re-using a proglet.
   bool parse  (char *line);		// Add a line to the proglet.
   bool dump   (void);				// Disassemble a compiled proglet.
   bool run    (value_t time = 0);	// Run a proglet.
};

#endif
