#ifndef COMPILER_H_
#define COMPILER_H_

#include <compiler/LogicalFactory.h>
#include <compiler/ConstantFactory.h>
#include <compiler/MixtureFactory.h>
#include <compiler/CounterTab.h>

#include <map>
#include <string>
#include <utility>
#include <list>

class ParseTree;
class Graph;
class SymTab;
class Index;
class FuncTab;
class DistTab;
class NodeAlias;

class Compiler;
typedef void (Compiler::*CompilerMemFn) (ParseTree const *);

class Compiler {
  Graph &_graph;
  SymTab &_symtab;
  CounterTab _countertab;
  FuncTab const &_functab;
  DistTab const &_disttab;
  std::map<std::string, SArray> const &_data_table;
  unsigned long _nresolved, _nlogical;
  bool *_is_resolved;
  bool _strict_resolution;
  LogicalFactory _logicalfactory;
  ConstantFactory _constantfactory;
  MixtureFactory _mixfactory;
  std::map<std::string, std::vector<Index> > _ranges;

  Node *getArraySubset(ParseTree const *t);
  bool indexExpression(ParseTree const *t, long &value);
  bool constantExpression(ParseTree const *p, double &value);
  Range VariableSubsetRange(ParseTree const *var);
  Range CounterRange(ParseTree const *var);
  Node* VarGetNode(ParseTree const *var);
  Range getRange(std::vector<ParseTree*> const &range_list, 
		Range const &default_range);


  void traverseTree(ParseTree const *relations, CompilerMemFn fun,
		    bool resetcounter=true);
  void allocateStochastic(ParseTree const *stoch_rel);
  void allocateLogical(ParseTree const *dtrm_rel);
  void getArrayDim(ParseTree const *p);
  void setStochasticParameters(ParseTree const *node);
  void setLogicalParameters(ParseTree const *node);

  Node* getParameter(ParseTree const *t);
  bool getLogicalParameterVector(ParseTree const *t,
			      std::vector<Node*> &parents);
  Node * getSubSetNode(ParseTree const *var);
  Node * getMixtureNode(ParseTree const *var);
  double constFromTable(ParseTree const *p);
  double constFromNode(ParseTree const *p);
  void collectNodes();
  void addDevianceNode();
public:
  /**
   * Constructor
   * @param graph Graph to be created. It should initially be empty
   * @param symtab Symbol table to be created. It should initially be empty
   * @param functab Function table to look up functions by name
   * @param disttab Distribution table to look up distributions by name
   * @param datatab Data table. This is required since some constant
   * expressions in the bugs language may depend on data values.
   */
  Compiler(Graph &graph, SymTab &symtab,
	   FuncTab const &functab, DistTab const &disttab,
	   std::map<std::string, SArray> const &data_table);
  void declareVariables(std::vector<ParseTree*> const &pvariables);
  void undeclaredVariables(ParseTree const *prelations);
  void writeRelations(ParseTree const *prelations);
};


#endif /* COMPILER_H_ */



syntax highlighted by Code2HTML, v. 0.9.1