%{
#include <stdio.h>
#include "sml.h"
#include "smlproto.h"
#include "smldefs.h"

extern int debug_flag;
extern int yylineno;            /* declared in y.tab.c */
extern FILE *yyin;              /* ditto */
char *malloc(), *calloc();

static Display *xdpy = NULL;
static Colormap xcolormap = 0;
static char **surfarray = NULL;
static int *vertIndices = NULL;       /* array of indices to vertices */
static byte *symbolBytes = NULL;
static int arrayIndx = 0;            /* general purpose array index */
static int surfcnt = 0;

%}
/* -------------------------------------------------------------- */
/* Define the union of three data types -- real numbers,          */
/* integers, and text -- so the parser can recieve all types from */
/* the lex specification. 					  */
/* -------------------------------------------------------------- */
%union {
	int	intval;
	double	realval;
	char  *stringval;
}
/* ------------------------------------------------------ */
/* James Anderson put these tokens together to work with  */
/*  his parser					          */
/* ------------------------------------------------------ */
%token  SECTION HEADER TABLES BLOCKS ENTITIES ENDSEC
%token  TABLE LTYPE LAYER STYLE VIEW UCS VPORT DWGMGR ENDTAB
%token  BLOCK ENDBLK INSERT 
%token  LINE POINT CIRCLE ARC TRACE SOLID 
%token  TEXT SHAPE ATTDEF ATTRIB POLYLINE VERTEX
%token  THREE_D_LINE THREE_D_FACE
%token  SEQEND DXFEOF
/* -------------------------------------------------------- */
/* These are variable names found in the Header section of  */
/* the DXF file.					    */
/* -------------------------------------------------------- */
%token	ANGBASE ANGDIR AUNITS AUPREC
%token	AXISUNIT CECOLOR CELTYPE CLAYER COORDS
%token	ELEVATION EXTMAX EXTMIN INSBASE
%token	LIMMAX LIMMIN LTSCALE LUNITS LUPREC
%token	PDMODE PDSIZE PLINEWID TDCREATE TDUPDATE
%token	TEXTSIZE TEXTSTYLE THICKNESS TRACEWID
/* --------------------------------------------------------------- */
/* These tokens denote DXF codes. 				   */
/* While ZERO is defined as a token, it is not used in the yacc    */
/* specification, since it introduces shift/reduce problems in the */
/* grammar.							   */
/* --------------------------------------------------------------- */
%token  ZERO ONE TWO THREE FOUR
%token  FIVE SIX SEVEN EIGHT NINE
%token  TEN ELEVEN TWELVE THIRTEEN FOURTEEN
%token  FIFTEEN SIXTEEN SEVENTEEN EIGHTEEN 
%token  TWENTY TWENTY_ONE TWENTY_TWO TWENTY_THREE TWENTY_FOUR
%token  TWENTY_FIVE TWENTY_SIX TWENTY_SEVEN TWENTY_EIGHT
%token  THIRTY THIRTY_ONE THIRTY_TWO THIRTY_THREE THIRTY_FOUR
%token  THIRTY_FIVE THIRTY_SIX THIRTY_SEVEN THIRTY_EIGHT THIRTY_NINE
%token  FORTY FORTY_ONE FORTY_TWO FORTY_THREE FORTY_FOUR
%token  FORTY_FIVE FORTY_SIX FORTY_SEVEN FORTY_EIGHT FORTY_NINE
%token  FIFTY FIFTY_ONE FIFTY_TWO FIFTY_THREE FIFTY_FOUR
%token  FIFTY_FIVE FIFTY_SIX FIFTY_SEVEN FIFTY_EIGHT
%token  SIXTY_TWO SIXTY_SIX
%token  SEVENTY SEVENTY_ONE SEVENTY_TWO SEVENTY_THREE SEVENTY_FOUR
%token  SEVENTY_FIVE SEVENTY_SIX SEVENTY_SEVEN SEVENTY_EIGHT
%token  TWO_TEN TWO_TWENTY TWO_THIRTY

/* -------------------------------------------------------------- */
/* Finally, we get the actual integers, real numbers, and strings */
/* from the DXF file.						  */
/* -------------------------------------------------------------- */
%token	<realval> REAL
%token	<intval> INTEGER
%token	<stringval> STRING

/* ----------------------- */
/* Name the start symbol.  */
/* ----------------------- */
%start 	file
%%


file :		

	header_section table_section block_section entity_section DXFEOF
	;

/* ------------------------------------------- */
/* Here's where I deal with the HEADER section */
/* ------------------------------------------- */
header_section :
	
	SECTION TWO HEADER variable_list ENDSEC
	;

variable_list :

	/* empty */
	| variable_list variable
	;

variable :

	NINE '$' variable_name group_list
	;

variable_name :
	ANGBASE
	| ANGDIR
	| AUNITS
	| AUPREC
	| AXISUNIT
	| CECOLOR
	| CELTYPE
	| CLAYER
	| COORDS
	| ELEVATION
	| EXTMAX
	| EXTMIN
	| INSBASE
	| LIMMAX
	| LIMMIN
	| LTSCALE
	| LUNITS
	| LUPREC
	| PDMODE
	| PDSIZE
	| PLINEWID
	| TDCREATE
	| TDUPDATE
	| TEXTSIZE
	| TEXTSTYLE
	| THICKNESS
	| TRACEWID
	| STRING
	;

/* ---------- END OF HEADER SECTION ------------- */

/* -------------------------------------------- */
/* Here's where I deal with the TABLES section  */
/* -------------------------------------------- */
table_section :
  
	SECTION TWO TABLES table_list ENDSEC
	;

table_list :
	
	/* empty */
	| table_list table
	;

table :
  
	TABLE TWO table_name SEVENTY INTEGER table_entry_list ENDTAB
	;

table_entry_list :

	/* empty */
	| table_entry_list table_entry
	;

table_name :

	LTYPE
	| LAYER
	| STYLE
	| VIEW
	| UCS
	| VPORT
	| DWGMGR
	;

table_entry :
	
	table_name TWO value SEVENTY INTEGER group_list
	;
	
/* ---------- END OF TABLES SECTION ------------- */

/* -------------------------------------------- */
/* Here's where I deal with the BLOCKS section  */
/* -------------------------------------------- */
block_section :

	SECTION TWO BLOCKS block_list ENDSEC
	;

block_list :

	/* empty */
	| block_list block
	;

block :

	BLOCK group_list entity_list ENDBLK group
	;


/* ---------- END OF BLOCKS SECTION ------------- */

/* ------------------------------------------- */
/* Here's how I break up the ENTITIES section  */
/* ------------------------------------------- */

entity_section :

	SECTION TWO ENTITIES entity_list ENDSEC
    	;

entity_list :

	/* empty */
	| entity_list entity_element 
	;

entity_element :
	
	line
	| three_d_line 
	| three_d_face
	| point 
	| circle
	| arc 
	| trace
	| solid 
	| text
	| shape 
	| polyline 
	| insert
	| attdef
	;

line :
	LINE group_list
	;

three_d_line :
THREE_D_LINE group_list
{
	fprintf(stderr, "3Dline has been read.\n");
}
;

three_d_face :
THREE_D_FACE group_list
{
	fprintf(stderr, "3Dface has been read.\n");
}
;

point :
	POINT group_list
	;

circle :
	CIRCLE group_list
	;

arc :
	ARC group_list
	;

trace :
	TRACE group_list
	;

solid :
	SOLID group_list
	;

text :
	TEXT group_list
	;

shape :
	SHAPE group_list
	;

attdef :
	ATTDEF group_list
	;

/* ------------------------------------------------------------------ */
/* NOT SURE WE WANT TO DO ANYTHING WITH DIMENSION:			*/
/*   1) IT'S A VERY COMPLICATED STRUCTURE.				*/
/*   2) IT PRESUMES 3-DIMENSIONS; WE ONLY CARE ABOUT 2.			*/
/*   3) IT'S NOT EVEN IN THE COMPLICATED DXF FILE WE HAVE AVAILABLE.  */
/*									*/
/* THEREFORE, HANDLING IT WILL MAINLY BE OF THEORETICAL INTEREST FOR  */
/* THE TIME BEING -- AND TIME MARCHES ON, REQUIRING PRACTICAL SOLUTIONS	*/
/* TO MORE IMMEDIATE PROBLEMS.	*/
/*								*/
/* dimension :					*/
/*								*/
/*	DIMENSION group_list		*/
/*	;							*/
/* ------------------------------------------------------------------ */

polyline :
	POLYLINE group_list vertex_complete
{
	fprintf(stderr, "polyline has been read.\n");
}
	;

vertex_complete :
	/* empty */
	| vertex_list seqend
        ;

vertex_list :
	/* empty */
	| vertex_list vertex
	;

vertex :
	VERTEX group_list
	;

insert :
	INSERT group_list attrib_complete
	;

attrib_complete :
	/* empty */
	| attrib_list seqend
        ;

attrib_list :
	/* empty */
	| attrib_list attrib
	;

attrib :
	ATTRIB group_list
	;

seqend :
	SEQEND group_list
	;

/* --------- END OF THE ENTITIES SECTION ---------- */

group_list :

	/* empty */
	| group_list group
	;

group:
	code value
	;

code :

  ONE | TWO | THREE | FOUR |
  FIVE | SIX | SEVEN | EIGHT | 
  TEN | ELEVEN | TWELVE | THIRTEEN | FOURTEEN |
  FIFTEEN | SIXTEEN | SEVENTEEN | EIGHTEEN |
  TWENTY | TWENTY_ONE | TWENTY_TWO | TWENTY_THREE | TWENTY_FOUR |
  TWENTY_FIVE | TWENTY_SIX | TWENTY_SEVEN | TWENTY_EIGHT |
  THIRTY | THIRTY_ONE | THIRTY_TWO | THIRTY_THREE | THIRTY_FOUR |
  THIRTY_FIVE | THIRTY_SIX | THIRTY_SEVEN | THIRTY_EIGHT | THIRTY_NINE |
  FORTY | FORTY_ONE | FORTY_TWO | FORTY_THREE | FORTY_FOUR |
  FORTY_FIVE | FORTY_SIX | FORTY_SEVEN | FORTY_EIGHT | FORTY_NINE |
  FIFTY | FIFTY_ONE | FIFTY_TWO | FIFTY_THREE | FIFTY_FOUR |
  FIFTY_FIVE | FIFTY_SIX | FIFTY_SEVEN | FIFTY_EIGHT |
  SIXTY_TWO | SIXTY_SIX | SEVENTY | SEVENTY_ONE | SEVENTY_TWO |
  SEVENTY_THREE | SEVENTY_FOUR | SEVENTY_FIVE | SEVENTY_SIX |
  SEVENTY_SEVEN | SEVENTY_EIGHT | TWO_TEN | TWO_TWENTY | TWO_THIRTY ;

value:
REAL
| INTEGER
| STRING
|
;
%%

yyerror(str)
char *str;
{
    extern char yytext[];

    fprintf(stderr, "%cyyerror: bad data at line %d: (%s)\n", 7,
            yylineno, str);
    fprintf(stderr, "%d:\"%s\"\n", yylineno, yytext);
}

/* returns an array of surface names read in
*/
char **SmlReadDxfFile(filename, count, dpy, colormap)
char *filename;
int *count;
Display *dpy;
Colormap colormap;
{
    int i;

    if (debug_flag & DEBUGFUNC)
        fprintf(stderr, "Sml Reader entered...\n");
    if ((yyin = fopen(filename, "r")) == NULL) {
        SmlWarn("SmlReadFile: can't open file \"%s\"", filename);
        return 0;
    }
    vertIndices = NULL;
    symbolBytes = NULL;
    arrayIndx = 0;
    surfarray = NULL;
    surfcnt = 0;
    yylineno = 1;
    xdpy = dpy;
    xcolormap = colormap;

    /* read the Sml file data into memory */
    if (yyparse() != 0) {
        SmlWarn("SmlReadFile: invalid input data");
        goto error;
    }
    if (surfcnt <= 0)
        goto error;
    if ((surfarray = (char**)SmlRealloc((char*)surfarray,
            surfcnt, sizeof(char*))) == NULL) {
        SmlWarn("SmlReadFile: can't realloc surface name pointers");
        xdpy = NULL;
        xcolormap = 0;
        return 0;
    }
    if (debug_flag & DEBUGFUNC)
        fprintf(stderr, "Sml Reader done.\n");
    *count = surfcnt;
    xdpy = NULL;
    xcolormap = 0;
    return surfarray;

error:
    SmlWarn("SmlReadFile: error reading data");
    for (i=0; i < surfcnt; i++)
        SmlDeleteSurface(surfarray[i]);
    FREE(surfarray);
    *count = 0;
    return NULL;
}

