%prefix sch_bxl_%

%struct
{
	long line, first_col, last_col;
}

%union
{
	double d;
	int i;
	char *s;
	double c;
}


%{
/*
 *                            COPYRIGHT
 *
 *  pcb-rnd, interactive printed circuit board design
 *
 *  BXL IO plugin - BXL grammar
 *  pcb-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas
 *  (Supported by NLnet NGI0 PET Fund in 2020)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *  Contact:
 *    Project page: http://repo.hu/projects/pcb-rnd
 *    lead developer: http://repo.hu/projects/pcb-rnd/contact.html
 *    mailing list: pcb-rnd (at) list.repo.hu (send "subscribe")
 */
#include <stdio.h>
#include "bxl_gram.h"
#include "bxl.h"

%}

/* Generic */
%token T_ID T_INTEGER T_REAL_ONLY T_QSTR

/* Keywords for footprints */
%token T_TRUE T_FALSE T_TEXTSTYLE T_FONTWIDTH T_FONTCHARWIDTH T_FONTHEIGHT
%token T_FONTFAMILY T_FONTFACE
%token T_PADSTACK T_ENDPADSTACK T_SHAPES T_PADSHAPE T_HOLEDIAM T_SURFACE
%token T_PLATED T_WIDTH T_HEIGHT T_PADTYPE T_LAYER T_PATTERN T_ENDPATTERN
%token T_DATA T_ENDDATA T_ORIGINPOINT T_PICKPOINT T_GLUEPOINT T_PAD T_NUMBER
%token T_PINNAME T_PADSTYLE T_ORIGINALPADSTYLE T_ORIGIN T_ORIGINALPINNUMBER
%token T_ROTATE T_POLY T_LINE T_ENDPOINT T_ATTRIBUTE T_ATTR T_JUSTIFY
%token T_ARC T_RADIUS T_STARTANGLE T_SWEEPANGLE T_TEXT T_ISVISIBLE T_PROPERTY
%token T_WIZARD T_VARNAME T_VARDATA T_TEMPLATEDATA T_ISFLIPPED T_NOPASTE

/* Symbol specific */
%token T_ORIGINALNAME T_SYMBOL T_ENDSYMBOL
%token T_PIN T_PINNUM T_ORIGIN T_PINLENGTH T_PINDES T_PINNAME T_TEXTSTYLEREF

/* Sections that are to be ignored (non-footprint data) */
%token  T_COMPONENT T_ENDCOMPONENT

%type <s> T_QSTR
%type <s> T_ID
%type <i> T_INTEGER
%type <d> T_REAL_ONLY
%type <d> real
%type <c> coord
%type <i> boolean

%%

full_file:
	maybe_nl
	file
	;

file:
	/* empty */
	|statement nl file
	;

statement:
	  text_style
	| symbol
	| boring_section
	;

/*** common and misc ***/

boolean:
	  T_TRUE       { $$ = 1; }
	| T_FALSE      { $$ = 0; }
	;

nl:
	  '\n'
	| '\n' nl
	;

maybe_nl:
	  /* empty */
	| nl
	;

real:
	  T_INTEGER            { $$ = $1; }
	| T_REAL_ONLY          { $$ = $1; }
	;

coord:
	real    { $$ = $1; }
	;

common_attr_text:
	  T_JUSTIFY T_ID             { sch_bxl_set_justify(ctx, $2); free($2); }
	| T_TEXTSTYLE T_QSTR         { sch_bxl_set_text_style(ctx, $2); free($2); }
	| T_TEXTSTYLEREF T_QSTR      { sch_bxl_set_text_style_ref(ctx, $2); free($2); }
	| T_ISVISIBLE boolean        { ctx->state.is_visible = $2; }
	;

common_origin:
	T_ORIGIN coord ',' coord     { ctx->state.origin_x = $2; ctx->state.origin_y = $4; }
	;

common_width:
	T_WIDTH coord                { ctx->state.width = $2; }
	;

/*** TextStyle ***/

text_style:
	T_TEXTSTYLE T_QSTR             { sch_bxl_text_style_begin(ctx, $2); /* $2 is taken over */ }
		text_style_attrs             { sch_bxl_text_style_end(ctx); }
	;

text_style_attrs:
	  /* empty */
	| '(' text_style_attr ')' text_style_attrs
	;

text_style_attr:
	  T_FONTWIDTH real             { ctx->state.text_style->width = $2; }
	| T_FONTCHARWIDTH real         { ctx->state.text_style->char_width = $2; }
	| T_FONTHEIGHT real            { ctx->state.text_style->height = $2; }
	| T_FONTFAMILY T_QSTR          { free($2); /* ignore for now */ }
	| T_FONTFACE T_QSTR            { free($2); /* ignore for now */ }
	;

/*** Poly ***/
poly:
	T_POLY                { sch_bxl_poly_begin(ctx); }
		poly_attrs          { sch_bxl_poly_end(ctx); }
	;

poly_attrs:
	  /* empty */
	| '(' poly_attr ')' poly_attrs
	;

poly_attr:

	  T_PROPERTY T_QSTR            { /* can't add attributes to polygons */ free($2); }
	| coord ',' coord              { sch_bxl_poly_add_vertex(ctx, $1, $3); }
	| common_origin
	| common_layer
	| common_width
	;

/*** Line ***/
line:
	T_LINE                        { sch_bxl_reset(ctx); }
		line_attrs                  { sch_bxl_add_line(ctx); sch_bxl_reset(ctx); }
	;

line_attrs:
	  /* empty */
	| '(' line_attr ')' line_attrs
	;

line_attr:
	  T_ENDPOINT coord ',' coord   { ctx->state.endp_x = $2; ctx->state.endp_y = $4; }
	| common_origin
	| common_layer
	| common_width
	;

/*** Attribute ***/
attribute:
	T_ATTRIBUTE                         { sch_bxl_reset(ctx); ctx->state.is_text = 0; }
		attribute_attrs                   { sch_bxl_add_text(ctx); sch_bxl_reset(ctx); }
	;

attribute_attrs:
	  /* empty */
	| '(' attribute_attr ')' attribute_attrs
	;

attribute_attr:
	  T_ATTR T_QSTR T_QSTR      { sch_bxl_set_attr_val(ctx, $2, $3); /* $2 and $3 are taken over */ }
	| common_attr_text
	| common_origin
	| common_layer
	;


/*** Arc ***/
arc:
	T_ARC                   { sch_bxl_reset(ctx); }
		arc_attrs             { sch_bxl_add_arc(ctx); sch_bxl_reset(ctx); }
	;

arc_attrs:
	  /* empty */
	| '(' arc_attr ')' arc_attrs
	;

arc_attr:
	  T_RADIUS coord        { ctx->state.radius = $2;  }
	| T_STARTANGLE real     { ctx->state.arc_start = $2; }
	| T_SWEEPANGLE real     { ctx->state.arc_delta = $2; }
	| common_origin
	| common_layer
	| common_width
	;

/*** Text ***/
text:
	T_TEXT                        { sch_bxl_reset(ctx); ctx->state.is_text = 1; }
		text_attrs                  { sch_bxl_add_text(ctx); sch_bxl_reset(ctx); }
	;

text_attrs:
	  /* empty */
	| '(' text_attr ')' text_attrs
	;

text_attr:
	  T_TEXT T_QSTR               { sch_bxl_set_text_str(ctx, $2); /* $2 is taken over */ }
	| T_ISFLIPPED boolean         { ctx->state.flipped = $2; }
	| T_ROTATE real               { ctx->state.rot = $2; }
	| common_attr_text
	| common_origin
	| common_layer
	;

/*** Wizard & template ***/
wizard:
	T_WIZARD wizard_attrs
	;

templatedata:
	T_TEMPLATEDATA wizard_attrs
	;

wizard_attrs:
	  /* empty */
	| '(' wizard_attr ')' wizard_attrs
	;

wizard_attr:
	  T_VARNAME T_QSTR      { free($2); }
	| T_VARDATA T_QSTR      { free($2); }
	| common_origin
	;

/*** pin ***/
pin:
	T_PIN
		{ sch_bxl_pin_begin(ctx); }
		pin_fields
		nl T_PINDES T_QSTR '(' coord ',' coord ')'     pintext_fields   { sch_bxl_pin_des(ctx, $6, $8, $10); }
		nl T_PINNAME T_QSTR '(' coord ',' coord ')'    pintext_fields   { sch_bxl_pin_name(ctx, $16, $18, $20); }
		{ sch_bxl_pin_end(ctx); }
	;

pin_fields:
	  /* empty */
	| pin_field pin_fields
	;

pin_field:
	  '(' T_PINNUM T_INTEGER ')'            { ctx->pin.num = $3; }
	| '(' T_ORIGIN coord ',' coord ')'      { ctx->pin.origin_x = $3; ctx->pin.origin_y = $5; }
	| '(' T_PINLENGTH coord ')'             { ctx->pin.length = $3; }
	| '(' T_ROTATE T_INTEGER ')'            { ctx->pin.rot = $3; }
	| '(' T_WIDTH  T_INTEGER ')'            { ctx->pin.width = $3; }
	| '(' T_ISVISIBLE  boolean ')'          { ctx->pin.is_visible = $3; }
	;

pintext_fields:
	  /* empty */
	| pintext_field pintext_fields;

pintext_field:
	  '(' T_TEXTSTYLEREF T_QSTR ')'      { sch_bxl_set_text_style_ref(ctx, $3); free($3); }
	| '(' T_JUSTIFY T_ID ')'             { sch_bxl_set_justify(ctx, $3); free($3); }
	| '(' T_TEXTSTYLE T_QSTR ')'         { sch_bxl_set_text_style(ctx, $3); free($3); }
	| '(' T_ISVISIBLE boolean ')'        { ctx->state.is_visible = $3; }
	| '(' T_ROTATE real ')'              { ctx->state.rot = $3; }
	;


/*** Symbol ***/
symbol:
	T_SYMBOL T_QSTR nl      { sch_bxl_reset_symbol(ctx); sch_bxl_symbol_begin(ctx, $2); free($2); }
	symbol_chldrn
	T_ENDSYMBOL             { sch_bxl_symbol_end(ctx); sch_bxl_reset_symbol(ctx); }
	;

symbol_chldrn:
	  /* empty */
	| symbol_chld nl symbol_chldrn
	;

symbol_chld:
	  data
	| T_ORIGINPOINT '(' coord ',' coord ')'   { ctx->sym_state.origin_x = $3; ctx->sym_state.origin_y = $5; }
	| T_ORIGINALNAME T_QSTR                   { free($2); }
	;

data:
	T_DATA ':' T_INTEGER nl
	data_chldrn
	T_ENDDATA
	;

data_chldrn:
	  /* empty */
	| data_chld nl data_chldrn
	;

data_chld:
	  pin
	| poly
	| line
	| attribute
	| arc
	| text
	| wizard
	;

/*** Sections not interesting for sch-rnd ***/
boring_section:
	  { ctx->in_error = 1; } T_PADSTACK   error  T_ENDPADSTACK  { ctx->in_error = 0; }
	| { ctx->in_error = 1; } T_PATTERN    error  T_ENDPATTERN   { ctx->in_error = 0; }
	| { ctx->in_error = 1; } T_COMPONENT  error  T_ENDCOMPONENT { ctx->in_error = 0; }
	;
