%{
  /* yacc for xml->gm_iim */
#include "xmlgiim.h"
#include "xmlgiimglob.h"
#include <string.h>
char *bsu_now;


%}

%union{
   char *val;
}

%token SUPPLIER_LIB_START SUPPLIER_LIB_END 
%token CLASS_START CLASS_END 
%token PROPERTY_START PROPERTY_END 
%token TABLE_START TABLE_END 
%token <val>QUOTED_STRING GREATER_THAN 
%token CNAME_START CNAME_END 
%token PNAME_START PNAME_END 
%token PTYPE_START PTYPE_END 
%token COLUMN_START COLUMN_END 
%token TD_START TD_END 
%token <val> TAGGED_TEXT
%%

supplier_library : supplier_lib_start class_list SUPPLIER_LIB_END
                 ;

supplier_lib_start : SUPPLIER_LIB_START bsu GREATER_THAN {
            supplier_bsu  = strdup(bsu_now);
            }
            ;

class_list : class_list class 
           | class
           ;

class : class_start cname opt_property_list opt_table opt_class_list CLASS_END       {
              level--;
      }
      ;


 
opt_class_list : /*empty*/
               | class_list
               ;


class_start : CLASS_START bsu GREATER_THAN {
              level++;
              if (class_now->level < level)
		{
              class_temp = (struct class*)malloc(sizeof(struct class));
              class_temp->level = level;
	      class_temp->next = NULL;
              class_temp->property_first = NULL;
              class_temp->table = NULL;
              class_temp-> next = NULL;
              class_temp->parent = class_now;
              class_now->first_child = class_temp;
              class_now = class_temp;
              class_now->class_bsu = strdup(bsu_now);
		}
              else if (class_now->level == level)
		{
              class_temp = (struct class*)malloc(sizeof(struct class));
              class_temp->level = level;
              class_temp->parent = class_now->parent;
              class_now->next = class_temp;
              class_now = class_temp;
              class_now->class_bsu = strdup(bsu_now);
		}
              else if (class_now->level - level == 1)
		{
              class_now = class_now->parent;
              class_temp = (struct class*)malloc(sizeof(struct class));
              class_temp->level = level;
              class_temp->parent = class_now->parent;
              class_now->next = class_temp;
              class_now = class_temp;
              class_now->class_bsu = strdup(bsu_now);
		}
	      else {printf("error with class level\n"); 
                    printf("class(%s) level: %d",class_now->class_name,class_now->level); printf("level = %d\n",level);exit(0);}

            }
            ;

cname : CNAME_START TAGGED_TEXT CNAME_END {
        class_now->class_name = strdup($2);
      }
      ;

opt_property_list : /* empty */
                  | property_list {
                     class_now->property_first = property_first;
	             property_first = (struct property*)malloc(sizeof(struct property));
                     property_now = property_first;
                     property_first->next = NULL;
                  }
                  ;

property_list : property_list property
              | property
              ;

property : property_start pname ptype PROPERTY_END {
            property_temp = (struct property*)malloc(sizeof(struct property));
            property_now->next = property_temp;
            property_temp->next = NULL;
            property_now = property_temp;
         }
         ;
property_start : PROPERTY_START bsu GREATER_THAN {
            property_now->property_bsu  = strdup(bsu_now);
            }
            ;

bsu : QUOTED_STRING {
      bsu_now = strdup($1);
      /* strip off the quotes */
         bsu_now[strlen(bsu_now)-1] = 0;
         bsu_now = &bsu_now[1];
    }
    ;

pname : PNAME_START TAGGED_TEXT PNAME_END {
            property_now->property_name = strdup($2);
      }
      ;
ptype : PTYPE_START TAGGED_TEXT PTYPE_END {
            property_now->property_type = strdup($2);
      }
      ;

opt_table : /*empty*/
          | table {
              class_now->table = table_now;
              table_now = (struct table*)malloc(sizeof(struct table));
              table_now->column_first = NULL;
          }
          ;

table : table_start column_list TABLE_END {
        table_now->column_first = column_first;
        column_first = (struct column*)malloc(sizeof(struct column));
        column_first->next = NULL;
        column_first->td_first;
        column_now=column_first;
      }
      ;
table_start : TABLE_START bsu GREATER_THAN {
              table_now->table_bsu = strdup(bsu_now);
            }
            ;

column_list : column_list column
            | column
            ;

column : COLUMN_START table_data_list COLUMN_END {
         column_now->td_first = td_first;
         column_temp = (struct column*)malloc(sizeof(struct column));
	 column_now->next = column_temp;
         column_temp->next = NULL;
	 column_now = column_temp;
	 td_first = (struct td*)malloc(sizeof(struct td));
	 td_now = td_first;
	 td_now->next = NULL;
       }
       ;
table_data_list : table_data_list table_data
                | table_data
                ;
table_data: TD_START TAGGED_TEXT TD_END {
            td_now->value = strdup($2);
            td_temp = (struct td*)malloc(sizeof(struct td));
            td_now->next = td_temp;
            td_temp->next = NULL;
            td_now = td_temp;
          }
          ;

%%
