%{
#include <stdio.h>

extern int yylineno;
%}
/* -------------------------------------------------------------- */
/* 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

%type <stringval> group_list

/* ----------------------- */
/* 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
{
	fprintf(stderr, "End of HEADER section.\n");
}
	;

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
{
  fprintf(stderr, "End of TABLES section.\n");
}
;

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
{
  fprintf(stderr, "End of the BLOCKS section.\n");
}
;

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
{
  fprintf(stderr, "End of the ENTITIES section.\n");
}
;

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 EIGHT STRING SIX STRING TEN REAL TWENTY REAL ELEVEN REAL TWENTY_ONE REAL
{ 
  indices[nvert++] = SmlCoordInsertTree($7, $9);
  indices[nvert++] = SmlCoordInsertTree($11, $13);
  SmlAddPolyLine(yylineno, smlDefaultForeColor, 1, 0, indices, nvert);
}
  | LINE EIGHT STRING TEN REAL TWENTY REAL ELEVEN REAL TWENTY_ONE REAL
{
  indices[nvert++] = SmlCoordInsertTree($5, $7);
  indices[nvert++] = SmlCoordInsertTree($9, $11);
  SmlAddPolyLine(yylineno, smlDefaultForeColor, 1, 0, indices, nvert);
}
  | 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
{
  /* Put the group_list into a data structure */
  /* Get the x,y coordinates using dxf codes 10, 20 */
  /* Call SmlCoordInsertTree() with x,y point for an arugment */
  /* Call SmlAddSymbol() to represent the point */
}
	;

 circle :
	CIRCLE group_list
{
  /* Don't have an example to use for this entity. Will have to invent */
  /* one or wait for Phil's return. */
}
	;

arc :
	ARC group_list

{
  /* I think that this can be treated as part of a circle, since Phil has */
  /* a provision for an arc argument in his SmlAddCircle() function */
}
	;

trace :
	TRACE group_list
	;

solid :
	SOLID group_list
	;

text : 	TEXT EIGHT STRING TEN REAL TWENTY REAL FORTY REAL ONE STRING FIFTY REAL 
{
  indices[nvert++] = SmlCoordInsertTree($5, $7);
  SmlAddText(yylineno, indx, $11, color, font);
}
  | 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
{
	fprintf(stderr, "polyline has been read.\n");
	/* alloc space for indices */
}

group_list vertex_complete
{
	/* SmlAddPolyLine() */
	/* free vertex list */
}
	;

vertex_complete :
	/* empty */
	| vertex_list seqend
        ;

vertex_list :
	/* empty */
	| vertex_list vertex
	;

vertex :
	VERTEX group_list
{
	/* smladdVertex */
  /* May have to increment an nindices counter here to satisfy a call to */
  /* SmlAddPolyLine(). sml.y should provide some examples for the correct */
  /* code. */
}
	;

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:
  
{ $$ = 0;}
	| 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
|
;
%%
#include "sml.h"
#include "smlproto.h"

/* Static status pointers for this module */
extern XColor *smlDefaultForeColor;

int  nvert = 0, *indices = NULL;

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);
}

