
#ifndef DICT_H
#define DICT_H

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#include<stdarg.h> 
#include"insert.h"
#include"general.h"


typedef unsigned char DTYPE;

struct dictree {
  char letter; // letter of current node
  DTYPE type; // Different nodes allocated to entries with the same name if 
  DTYPE parse;// they do not have the same 'type' and 'parse'. A node 
              // containing an entry will have type != 0.
  void *data; // Available for additional data. In the context of 'struct dict'
              // allocate it with the 'mem' field of struct dict.
  struct dictree* next; // next node of same depth
  struct dictree* down; // next node of depth + 1; 
};

/*

  The following illustrates the format of the tree when used for words of a
  dictionary. The part of speach info is stored in 'type' of struct dict.

  a -----------------------------> b 
  |                                |
  b (noun) -> b (verb) -> d -> f   g (verb)
  |                       |    |
  f                       s    r (noun)
  |                       |
  h (adj)                 a (noun) -> j (verb)

  The tree above has the entries "ab" (noun), "ab" (verb), "abfh" (adj), 
  "adsv" (noun), "adsj" (verb), "afr" (noun), "bg" (verb).
  Note that 'a' is at the root node.
  Note that the node of 'b (verb)' MUST have down = 0. Only the first 'b'
  node in the chain (that is, 'b (noun)') may have down != 0.
  Note that in a chain entries are ordered ('b' entries first, then the 'd'
  entry, then the 'f' entry.)

*/


struct dict {
  struct dictree* root;
  int n; // number of entries (not of nodes)
  int maxlen; // maximum string length + 1
  struct alloc mem; 
};


inline int compare_to_entry(char letter, int type, int parse, \
			    struct dictree* y);
// defined in dict.c

//int compare_entries(struct dictree* x, struct dictree* y);
#define compare_entries(x,y) compare_to_entry(x->letter, x->type, x->parse, y);


int dic_insert(char* str, int n, DTYPE type, DTYPE parse, struct dictree** y,\
	       struct dict* x);
/* str is the string to be included, n the length of str (i.e. str[n-1] is 
   the final nonzero character of the string), and type and parse are the
   attributes of the (final) struct dictree node that should be created. If
   y is nonzero, the function writes to *y the address of the node of the 
   element. Note that x is the dictionary. 

   If initially the tree is empty, *root MUST BE ZERO!

   Returns a nonzero value if the element is not already in the tree. */


struct dictree* dic_lookup(char* entry, struct dictree *root);
/* Returns the tree element where 'entry' is defined; use the next fields
   to see whether there is another element for the same entry. A next field
   refers to the same entry if entry[n-1] == letter field, where n is the
   string length of entry (and thus entry[n-1] is the last char. of 'entry'). 
 */


struct dictree* include_in_tree(char* str, int n, DTYPE type, DTYPE parse, \
				struct dict* x);
/* This calls dic_insert and returns zero if the element is already in the 
   tree. Otherwise, it returns the node in which the element was added. 
   See dic_insert for the meaning of the parameters. */

struct dictree* next_entry(char* str, struct dict* x);
/* This function can be used to list all entries in 'x' in alphabetical
   order. The return value is the entry. The name of the entry is stored 
   in 'str'. When the function is called, 'str' should contain the name of
   the previous entry; 'str' should have room for x->maxlen characters. 
   For the first call, set str[0] = 0. When no more entries are found the 
   function returns 0. A call with str = 0 will reset the function. 
 */

#define DFLT_NODE_TYPE 1 // must be nonzero

// struct dictree* add_to_dict(char* s, struct dict x);
#define add_to_dict(s, x) include_in_tree(s, 0, DFLT_NODE_TYPE, 0, &x);


// void init_dict(struct dict x);
#define init_dict(x) {	    \
  memset(&x, 0, sizeof(x)); \
  initalloc(&(x.mem), 64); }

// void free_dict(struct dict x);
#define free_dict(x) { 	\
  sfree(&(x.mem));      \
  x.root = 0; }

#endif
