//-----------------------------------------------------------
// Copyright Christian Arnault LAL-Orsay CNRS
// arnault@lal.in2p3.fr
// See the complete license in cmt_license.txt "http://www.cecill.info". 
//-----------------------------------------------------------

#ifndef __cmt_tag_h__
#define __cmt_tag_h__

#include "cmt_parser.h"
#include "cmt_system.h"
#include "cmt_use.h"
#include "cmt_map.h"

class Tag
{
public:
  typedef cmt_map<cmt_string, Tag> TagMap;
  typedef cmt_vector<Tag> TagVector;
  typedef cmt_vector<Tag*> TagPtrVector;

  static void action (const CmtSystem::cmt_string_vector& words, Use* use);
  static void action_apply (const CmtSystem::cmt_string_vector& words, Use* use);
  static void action_exclude (const CmtSystem::cmt_string_vector& words, Use* use);
  static Tag* find (const cmt_string& name, TagMap& instances);
  static Tag* find (const cmt_string& name);
  static Tag* add (const cmt_string& name, int priority,
                   const cmt_string& context, Use* use = 0);
  static int tag_number ();
  static Tag* tag (int index);
  static void unmark_all ();
  static void restore_tree ();
  static void clear_all ();

  static TagMap& tag_map ();
  static TagVector& all_tags ();
  static TagPtrVector& tags ();

  static Tag* get_default ();

  static bool check_tag_used (const Tag* tag);

public:
  Tag ();
  Tag (const Tag& other);
  Tag& operator = (const Tag& other);
  ~Tag ();
  void clear ();
  void add_tag_ref (Tag* ref);
  void add_tag_exclude (Tag* ref);
  void unmark ();
  void mark ();
  void show_definition (bool quiet) const;
  void show (bool quiet) const;
  bool is_selected () const;
  bool is_primary () const;
  const cmt_string& get_name () const;
  int get_priority () const;
  void install (TagMap& instances);
  bool use_operand (const Tag* other) const;
  bool use_ref (const Tag* other) const;

private:
  cmt_string m_name;
  bool m_selected;
  TagPtrVector m_and_operands;
  TagPtrVector m_tag_refs;
  TagPtrVector m_tag_excludes;
  cmt_string m_context;
  Use* m_def_use;
  Use* m_set_use;
  int m_priority;
  ScopeType scope;
};

#endif
