4BSD/usr/src/cmd/cifplot/parser.y
%{
/*******************************************************************
* *
* File: CIFPLOT/parser.y *
* Written by Dan Fitzpatrick *
* copyright 1980 -- Regents of the University of California *
* *
********************************************************************/
/* This is a YACC description for the parser */
/* In the offical CIF language description SEMI = BLANKLIST ';' BLANKLIST
* but this causes ambiguities for the LALR(1) parser so the scanner
* returns ';' when it spots the pattern BLANKLIST ';'
*/
#include <stdio.h>
#include "defs.h"
#include "globals.h"
#include "structs.h"
#include "alloc.h"
#define yyparse parser
#define yylex scanner
#define null Concat("",0);
int Definning=0;
int SendAll=0; /* If set causes the lexical analyzer to return
* BLANKLIST and ';' seperately */
int A = 1;
int B = 1;
#define SCALE(x) ( (((real) A) * ((real) x)) / ((real) B ))
%}
%start CIF_FILE
%token BLANK
%token OTHERCHAR
%token COMMENT_COMMAND
%%
CIF_FILE
: COMMANDLIST END_COMMAND BLANKLIST
| COMMANDLIST END_COMMAND error
{ Error("Improper Ending",FATAL); }
| COMMANDLIST END_COMMAND SEMI
{ Error("Semi-Colon found after End",
RECOVERABLE); }
| COMMANDLIST
{ Error("No End Statement",RECOVERABLE); }
| COMMANDLIST END_COMMAND BLANKLIST GARBAGE error
{ Error("Garbage after End Statement",
RECOVERABLE); }
;
COMMANDLIST
: COMMANDLIST COMMAND SEMI
| COMMANDLIST SEMI
| BLANKLIST
| COMMANDLIST error
{ Error("Unrecognizable Command",FATAL); }
SEMI
;
COMMAND
: FCOMMAND
;
FCOMMAND
: PRIM_COMMAND
{ Execute($1); }
| DEF_DELETE_COMMAND
| SYMB_LIST DEF_FINNISH_COMMAND
{ Execute($1);
Definning = 0;
A=1; B=1; }
| ERROR_COMMAND
;
ERROR_COMMAND
: COMMENT_COMMAND
{ Error("Comments must end with a semi-colon",
RECOVERABLE); }
BLANKLIST FCOMMAND
{ $$ = $1; }
| DEF_FINNISH_COMMAND
{ Error("Define Finnished found outside of Definition",
FATAL);
$$ = $1; }
| DEF_ERROR
{ Error("Unrecognized Definition Command",
FATAL); }
;
SYMB_LIST
: SYMB_LIST SYMB_COMMAND
{ $$ = AddCmd($1,$2); }
| SYMB_LIST SEMI
{ $$ = $1; }
| DEF_START_COMMAND SEMI
{ Definning = 1;
A=(int) ((Command *) $1)->Ctype.Symbl.a;
B=(int) ((Command *) $1)->Ctype.Symbl.b;
$$ = $1; }
| SYMB_LIST error
{ $$ = $1;
Error("Unrecognized or Illegal Command in Definition",
FATAL); }
SEMI
;
SYMB_COMMAND
: PRIM_COMMAND SEMI
{ $$ = $1; }
| COMMENT_COMMAND
{ Error("Comments must end with a semi-colon",RECOVERABLE); }
BLANKLIST SYMB_COMMAND
{ $$ = $4; }
;
PRIM_COMMAND
: POLYGON_COMMAND
| BOX_COMMAND
| ROUNDFLASH_COMMAND
| WIRE_COMMAND
| LAYER_COMMAND
| CALL_COMMAND
| USEREXTENSION_COMMAND
| COMMENT_COMMAND
;
POLYGON_COMMAND
: 'P' PATH
{ /* Polygons must have more than two
* vertices to be well defined */
if( ((struct PathHeader *) $2)->PNo < 3)
Error("Degenerate Polygon",WARNING);
/* Polygons with less than two vertices are
* useless */
if( ((struct PathHeader *) $2)->PNo < 2) {
Error("Command Ignored",WARNING);
$$ = MakeComment();
}
else
$$ = MakePoly($2); }
| 'P' error
{ Error("Bad Path Descriptor in Polygon",FATAL);
$$ = MakeComment(); }
;
BOX_COMMAND
: 'B' INTEGER SEP INTEGER SEP POINT
{ $$ = MakeBox(SCALE($2),SCALE($4),$6,
MakePoint(1.0,0.0));
Free($6); }
| 'B' INTEGER SEP INTEGER SEP POINT SEP POINT
{ if(!CheckPoint($8))
Error("Bad Direction Vector in Box Command",FATAL);
$$ = MakeBox(SCALE($2),SCALE($4),$6,$8);
Free($6); Free($8); }
| 'B' error
{ Error("Illegal Box Description",FATAL);
$$ = MakeComment(); }
;
ROUNDFLASH_COMMAND
: 'R' INTEGER SEP POINT
{ $$ = MakeFlash(SCALE($2),$4);}
| 'R' error
{ Error("Illegal Round Flash Description",FATAL);
$$ = MakeComment(); }
;
WIRE_COMMAND
: 'W' INTEGER SEP PATH
{ if( ((struct PathHeader *) $4)->PNo < 2)
Error("Degenerate Wire",WARNING);
$$ = MakeWire(SCALE($2),$4); }
| 'W' error
{ Error("Illegal Wire Description",FATAL);
$$ = MakeComment(); }
;
LAYER_COMMAND
: 'L' BLANKLIST SHORTNAME
{ $$ = MakeLayer($3); }
| 'L' error
{ Error("Illegal Layer Command",FATAL);
$$ = MakeComment(); }
;
DEF_START_COMMAND
: 'D' BLANKLIST 'S' INTEGER
{ $$ = MakeSymbol($4,1,1);}
| 'D' BLANKLIST 'S' INTEGER SEP INTEGER SEP INTEGER
{ $$ = MakeSymbol($4,$6,$8);}
;
DEF_FINNISH_COMMAND
: 'D' BLANKLIST 'F'
{ $$ = 0; }
;
DEF_DELETE_COMMAND
: 'D' BLANKLIST 'D' INTEGER
{ DeleteDefintion($4);
$$ = MakeComment(); }
;
DEF_ERROR
: 'D' error
;
CALL_COMMAND
: 'C' INTEGER TRANSFORMATION
{ $$ = MakeCall($2,$3); }
| 'C' error
{ Error("Illegal Call Command",FATAL);
$$ = MakeComment(); }
;
USEREXTENSION_COMMAND
: SENDALL '0' SP NAME
{ $$ = MakeComment();
if(!standard)
Include($4);
else
Error("User Extention Ignored\n",WARNING);
SendAll = 0;
Free($4); }
| SENDALL '0' 'I' SP NAME
{ $$ = MakeComment();
if(!standard)
Include($4);
else
Error("User Extention Ignored\n",WARNING);
SendAll = 0;
Free($4); }
| SENDALL '0' 'A' INTEGER SEP INTEGER SEP INTEGER SEP SINTEGER SEP SINTEGER BLANKLIST
{ if(!standard)
$$ = MakeArray($4,$6,$8,SCALE($10),SCALE($12));
else {
Error("User Extention Ignored\n",WARNING);
$$ = MakeComment();
}
SendAll = 0; }
| SENDALL '1' BLANK USERLIST
{ $$ = MakeComment();
if(!standard)
fprintf(stderr,"%s\n",$4);
else
Error("User Extention Ignored\n",WARNING);
SendAll = 0;
Free($4); }
| SENDALL '2' SP '"' TEXT '"' TRANSFORMATION
{ if(!standard)
$$ = MakeText($5,$7,'l');
else {
Error("User Extention Ignored\n",WARNING);
$$ = MakeComment();
}
SendAll = 0; }
| SENDALL '2' 'C' SP '"' TEXT '"' TRANSFORMATION
{ if(!standard)
$$ = MakeText($6,$8,'c');
else {
Error("User Extention Ignored\n",WARNING);
$$ = MakeComment();
}
SendAll = 0; }
| SENDALL '9' SP NAME
{ if(!standard)
$$ = MakeName($4);
else {
Error("User Extention Ignored\n",WARNING);
$$ = MakeComment();
}
SendAll = 0; }
| SENDALL '9' '4' SP NAME BLANK POINT
{ if(!standard) {
$$ = MakePointName($5,$7,"all");
Free($7);
}
else {
Error("User Extention Ignored\n",WARNING);
$$ = MakeComment();
}
SendAll = 0; }
| SENDALL '9' '4' SP NAME BLANK POINT SP SHORTNAME
{ if(!standard) {
$$ = MakePointName($5,$7,$9);
Free($7);
}
else {
Error("User Extention Ignored\n",WARNING);
$$ = MakeComment();
}
SendAll = 0; }
| SENDALL EXTEN_DIGIT error
{ $$ = MakeComment();
Error("Bad Syntax in Extension Command --- Command Ignored",
WARNING);
SendAll = 0; }
| SENDALL OTHER_DIGIT error
{ $$ = MakeComment();
Error("Unimplemented User Extension",
WARNING);
SendAll = 0; }
;
EXTEN_DIGIT
: '0' | '1' | '2' | '9'
;
OTHER_DIGIT
: '3' | '4' | '5' | '6' | '7' | '8'
;
SENDALL
: EMPTY {SendAll = 1; }
;
END_COMMAND
: 'E'
;
TRANSFORMATION
: BLANKLIST 'T' POINT TRANSFORMATION
{ $$ = Translate($3,$4);
if(output == NOPLOT)
Free(((transform *) $4)->TransString);
Free($3); FreeTransform($4); }
| BLANKLIST 'M' BLANKLIST 'X' TRANSFORMATION
{ $$ = Mirror('x',$5);
if(output == NOPLOT)
Free(((transform *) $5)->TransString);
FreeTransform($5); }
| BLANKLIST 'M' BLANKLIST 'Y' TRANSFORMATION
{ $$ = Mirror('y',$5);
if(output == NOPLOT)
Free(((transform *) $5)->TransString);
FreeTransform($5); }
| BLANKLIST 'R' POINT TRANSFORMATION
{ if(!CheckPoint($3))
Error("Bad Rotation Vector",FATAL);
$$ = Rotate($3,$4);
if(output == NOPLOT)
Free(((transform *) $4)->TransString);
Free($3); FreeTransform($4); }
| EMPTY
{ $$ = MakeTransform(); }
;
PATH
: PATH SEP POINT
{ $$ = AddPath($1,$3);
Free($3); }
| POINT
{ $$ = MakePath($1); }
;
POINT
: SINTEGER SEP SINTEGER
{ $$ = MakePoint(SCALE($1),SCALE($3)); }
| SINTEGER error
{ Error("Odd number of values encountered",
FATAL);
$$ = MakePoint(SCALE($1),0.0);}
;
SINTEGER
: SEPLIST INTEGERD
{ $$ = $2; }
| SEPLIST '-' INTEGERD
{ $$ = - $3; }
;
INTEGER
: SEPLIST INTEGERD
{ $$ = $2; }
| SEPLIST '-' INTEGERD
{ Error("Expected Positive Integer",FATAL);
$$ = $3; }
;
INTEGERD
: INTEGERD DIGIT
{ if ($1 > (0x800000 / 10)) {
Error("Integers may not exceed 2**24",
FATAL);
$$ = 0;
}
else
$$ = ($1*10)+$2-'0'; }
| DIGIT
{ $$ = $1 - '0'; }
;
SHORTNAME
: C
| C C
{ $$ = Concat($1,$2,0);
Free($1); Free($2); }
| C C C
{ $$ = Concat($1,$2,$3,0);
Free($1); Free($2); Free($3); }
| C C C C
{ $$ = Concat($1,$2,$3,$4,0);
Free($1); Free($2);
Free($3); Free($4); }
;
C
: DIGIT
{ $$ = MakeString($1); }
| UPPERCHAR
{ $$ = MakeString($1); }
;
SEPLIST
: SEPLIST SEP
| EMPTY
;
SEP
: UPPERCHAR
| BLANK
| OTHERCHAR
;
UPPERCHAR
: 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G'
| 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N'
| 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U'
| 'V' | 'W' | 'X' | 'Y' | 'Z'
;
DIGIT
: '0' | '1' | '2' | '3' | '4'
| '5' | '6' | '7' | '8' | '9'
;
NAME
: NAME NAMECHAR
{ $$ = Concat($1,$2,0);
Free($1); Free($2); }
| NAMECHAR
;
NAMECHAR
: BASECHAR
| '"'
{ $$ = MakeString('"'); }
;
TEXT
: TEXT TEXTCHAR
{ $$ = Concat($1,$2,0);
Free($1); Free($2); }
| EMPTY
{ $$ = null; }
;
TEXTCHAR
: BLANK
{ $$ = MakeString($1); }
| BASECHAR
;
USERLIST
: USERLIST USERCHAR
{ $$ = Concat($1,$2,0);
Free($1); Free($2); }
| EMPTY
{ $$ = null; }
;
USERCHAR
: BLANK
{ $$ = MakeString($1); }
| BASECHAR
| '"'
{ $$ = MakeString('"'); }
;
BASECHAR
: DIGIT
{ $$ = MakeString($1); }
| UPPERCHAR
{ $$ = MakeString($1); }
| OTHERCHAR
{ $$ = MakeString($1); }
| '('
{ $$ = MakeString('('); }
| ')'
{ $$ = MakeString(')'); }
| '-'
{ $$ = MakeString('-'); }
;
SP
: BLANK BLANKLIST
;
BLANKLIST
: BLANKLIST BLANK
| EMPTY
;
GARBAGE
: DIGIT
| UPPERCHAR
| '-' | '(' | ')'
;
SEMI
: ';' BLANKLIST
;
EMPTY
:
;
%%
#include "scanner.c"