#ifndef lint
/*static char yysccsid[] = "from: @(#)yaccpar	1.9 (Berkeley) 02/21/93";*/
static char yyrcsid[] = "$Id: skeleton.c,v 1.4 1993/12/21 18:45:32 jtc Exp $";
#endif
#define YYBYACC 1
#define YYMAJOR 1
#define YYMINOR 9
#define yyclearin (yychar=(-1))
#define yyerrok (yyerrflag=0)
#define YYRECOVERING (yyerrflag!=0)
#define YYPREFIX "yy"
#line 29 "parse.y"
#include "dmd/rgb.h"
#include "dmd/memory.h"
#include "dmd/tools.h"
#include "mogul.h"

#define MIN_PLOT_SIZE 0.01
#define MAX_PLOT_SIZE 1.e10

char *MogulParserMsg = NULL;

static char *helpString =
  "commands:\n"
  "\tadd atom <select>\n"
  "\t    bond <select>\n"
  "\t    box\n"
  "\t    label <string> <position> <height>\n"
  "\t    line <position> <position>\n"
  "\tcamera position = <position>\n"
  "\t       view = <direction>\n"
  "\t       up = <direction>\n"
  "\tattributes(atom <string>) = {attr1 = value1 [, attr2 = value2 [...]]}\n"
  "\tattributes(bond(<string>,<string>)) = {attr1 = value1 [, attr2 = value2 [...]]}\n"
  "\tattributes(plot) = {attr1 = value1 [, attr2 = value2 [...]]}\n"
  "\thelp\n"
  "\t<identifier> = <number>\n"
  "\n"
  "attributes = values:\n"
  "\tbond radius = <number>\n"
  "\tcolor = <string>\n"
  "\tmode = filled | outlined | solid | translucent | minimal | moon | stick\n"
  "\tperspective = <number>\n"
  "\tradius = <number>\n"
  "\tsize = <number> | <number>,<number>\n"
  "\n"
  "other basic data types:\n"
  "\t<direction> == [dx,dy,dz] | <<number> * <direction>\n"
  "\t<position> == (x,y,z) | <atom n> | <geometry center> | <camera center> |\n"
  "\t              <plot center> | [point] + [direction]\n"
  "\t<string> == \"in double quotes\"\n"
  ;

static char *copyrightString = 
  "mogul version 2.0, Copyright (C) 1996 David Deaven.\n"
  "\tmogul comes with ABSOLUTELY NO WARRANTY.\n"
  "\tThis is free software, and you are welcome to redistribute\n"
  "\tit under the conditions of the Free Software Foundation\n"
  "\tversion 2 or (at your option) later.\n"
  ;

struct MogulParserRec {
	MogulRules rules;
	struct symtab_s *symtab;
	StringPool pool;
};

struct symtab_s {
	char *name;
	int type;
	union {
	  double r;
	  double (*r_fun)(void);
	  double (*r_fun_r)(double);
	} value;
	struct symtab_s *next;
};

struct lex_s {
	enum {SRC_FILE, SRC_STRING} type;
	union {
	  FILE *f;
	  char *s;
	} source;
	int ch;		/* chars read */
	int line;	/* lines read */
	int c, lastc;	/* this character, last read character */
	int eof;
};

enum context_type {INITIAL_CONTEXT, IF_CONTEXT, FOR_CONTEXT, WHILE_CONTEXT};
struct context_s {
	int flameon;	/* executing? */
	enum context_type type;
};

struct select_s {
        unsigned int n;		/* how many selctions */
        int *which;		/* list of selections */
};

static struct {
	/* initialized */
	struct lex_s lex;
	char *prompt;
	int autoRender;
	MogulPlot plot;
	MogulDevice device;
	MogulParser parser;
	int ncontext;
	int nerror;
	struct context_s *context;
	Geometry *g;
	NeighborList *nl;

	/* scratch */
	struct {
	  double p[3];
	  struct ruleAttributes *lrule;
	  struct plotAttributes *lplot;
	} tmp;
} global;

int yylex(void);
int yyerror(char *s);
int yyparse(void);

static void prompt()
{
	if(global.prompt)
	{
	  printf("%s", global.prompt);
	  fflush(stdout);
	}
}

static struct symtab_s *new_symtab(MogulParser parser, char *name, int type)
{
	struct symtab_s *s = NewPointer(s);
	s->type = type;
	s->name = name;
	s->next = parser->symtab;
	parser->symtab = s;
	return s;
}

static struct symtab_s *find_symtab(MogulParser parser, char *name)
{
	struct symtab_s *s;
	for(s = parser->symtab; s; s = s->next) {
	  if(!strcmp(name, s->name)) return s;
	}
	return NULL;
}

static void push_context(int flameon, enum context_type type)
{
	global.context =
	  ResizePointerArray(global.context, global.ncontext + 1);
	global.context[global.ncontext].flameon = flameon;
	global.context[global.ncontext].type = type;
	global.ncontext++;
}

#if 0
static int pop_context(void)
{
	if(global.ncontext <= 1) return -1;
	global.ncontext--;
	return 0;
}
#endif

static int flameon(void)
{
	int i;
	for(i=0; i<global.ncontext; i++)
	  if(!global.context[i].flameon) return 0;
	return 1;
}

static void delete_context(void)
{
	myfree(global.context); global.context = NULL;
	global.ncontext = 0;
}

static double check_range(double v, double vmin, double vmax)
{
	if(v < vmin) v = vmin;
	if(v > vmax) v = vmax;
	return v;
}

/* Return a newly allocated number specification.
 */
static struct select_s *select_range(int i, int j)
{
	int n;
	struct select_s *s = NewPointer(s);
	if(i < 0 || j < 0 || j < i) {
	  s->n = 0;
	  s->which = NULL;
	}
	else {
	  s->n = j - i;
	  s->which = imalloc(s->n > 0 ? s->n : 1);
	  for(n=i; n<j; n++)
	    s->which[n - i] = n;
	}
	return s;
}

/* Free a specification.
 */
static void delete_select(struct select_s *s)
{
	myfree(s->which);
	myfree(s);
}

static int is_selected(int i, struct select_s *s)
{
	int j;
	for(j=0; j<s->n; j++) if(s->which[j] == i) return 1;
	return 0;
}

/* Concatenate two specifications, freeing them in the process.
 */
static struct select_s *select_union(struct select_s *s1, struct select_s *s2)
{
	int i, m, n = s1->n + s2->n;
	s1->which = ResizePointerArray(s1->which, n);
	for(i=m=s1->n; i<n; i++) {
	  if(!is_selected(i, s1)) s1->which[m++] = s2->which[i - s1->n];
	}
	s1->n = m;
	delete_select(s2);
	return s1;
}

static double *set3(double dst[3], double src[3])
{
	int i;
	for(i=0; i<3; i++) dst[i] = src[i];
	return dst;
}

static double *add3(double dst[3], double src[3])
{
	int i;
	for(i=0; i<3; i++) dst[i] += src[i];
	return dst;
}

static double *mul31(double dst[3], double a)
{
	int i;
	for(i=0; i<3; i++) dst[i] *= a;
	return dst;
}

#line 284 "parse.y"
typedef union {
  double number;
  double point[3];
  unsigned long mode;
  char *string;
  Color color;
  struct select_s *select;
  struct symtab_s *sym;
  struct ruleAttributes *lrule;
  struct plotAttributes *lplot;
} YYSTYPE;
#line 277 "y.tab.c"
#define NUM 257
#define STRING 258
#define IDENTIFIER 259
#define R_VAR 260
#define R_FUN 261
#define R_FUN_R 262
#define ADD 263
#define ATTRIBUTES 264
#define OUTLINED 265
#define MOON 266
#define STICK 267
#define MINIMAL 268
#define ALL 269
#define NONE 270
#define ATOM 271
#define CENTER 272
#define BOND 273
#define TRUE 274
#define FALSE 275
#define CAMERA 276
#define VIEW 277
#define NAME 278
#define PERSPECTIVE 279
#define SIZE 280
#define COLOR 281
#define RADIUS 282
#define PLOT 283
#define GEOMETRY 284
#define BOX 285
#define POSITION 286
#define UP 287
#define SOLID 288
#define TRANSLUCENT 289
#define FOREGROUND 290
#define BACKGROUND 291
#define LINE 292
#define HELP 293
#define LABEL 294
#define FILLED 295
#define MODE 296
#define YYERRCODE 256
short yylhs[] = {                                        -1,
    0,    0,    0,   13,   13,   14,   14,   14,   14,   14,
   14,   14,   14,   14,   14,   14,   14,   14,   15,   14,
   17,   14,   18,   14,   10,   11,   12,   16,   16,   20,
   20,   20,   20,   20,   20,   19,   19,   21,   21,   21,
   21,   21,    2,    2,    2,    2,    2,    2,    2,    3,
    3,    3,    3,    3,    3,    9,    9,    9,    8,    8,
    6,    5,    5,    5,    5,    5,    5,    5,    5,    4,
    4,    1,    1,    1,    1,    1,    1,    1,    1,    1,
    1,    1,    7,    7,    7,    7,    7,
};
short yylen[] = {                                         2,
    0,    2,    2,    1,    2,    3,    3,    2,    5,    4,
    4,    4,    4,    1,    3,    3,    3,    4,    0,    6,
    0,    6,    0,    6,    5,    9,    4,    1,    3,    0,
    3,    4,    3,    4,    3,    1,    3,    7,    3,    3,
    3,    3,    7,    4,    4,    4,    4,    3,    3,    7,
    2,    2,    3,    3,    3,    4,    3,    4,    1,    3,
    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
    3,    1,    3,    3,    3,    3,    1,    3,    4,    3,
    1,    1,    1,    4,    5,    3,    3,
};
short yydefred[] = {                                      1,
    0,    3,    0,    0,    0,    0,    0,    0,    0,   14,
    4,    0,    0,    0,    2,    0,    0,    0,    0,    0,
    0,    0,    8,    0,    0,    0,    0,    0,    0,   19,
   21,   23,    5,   72,   77,    0,    0,   81,   82,    0,
    0,    0,   17,    0,    0,    0,   59,    0,    0,    0,
    0,   83,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
   18,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
   27,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,   78,    0,   80,    0,    0,   76,   75,   57,    0,
    0,   60,    0,    0,   49,    0,    0,    0,    0,    0,
    0,    0,   86,   87,    0,   25,    0,   51,   52,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,   28,
    0,    0,    0,    0,    0,    0,   36,   79,   56,   58,
    0,   44,   46,   47,   45,    0,   84,    0,   55,    0,
   75,   53,    0,    0,    0,    0,    0,    0,   20,    0,
   22,    0,    0,    0,    0,   24,    0,    0,   85,    0,
    0,    0,   35,    0,    0,    0,   63,   67,   69,   66,
   68,   64,   65,   62,    0,   70,   29,    0,    0,    0,
   41,   42,   37,    0,    0,    0,    0,    0,    0,    0,
   43,   26,    0,   71,    0,   50,    0,   38,
};
short yydgoto[] = {                                       1,
   95,   77,   96,  195,  196,  183,  184,   46,   47,   12,
   13,   14,   15,   16,   61,  139,   62,   63,  146,  140,
  147,
};
short yysindex[] = {                                      0,
  -10,    0,  -47,  -42,  -12,   -3, -152,    4, -106,    0,
    0,   14,   27,   33,    0,   70,   74,   74,   72,   74,
   62,   62,    0,  -25,  -56, -119,   75,   86,   97,    0,
    0,    0,    0,    0,    0,   91,  122,    0,    0,   74,
  232,  232,    0,  156, -216,  125,    0,  125,   52, -111,
  -30,    0,  -39,   25,  -56,  147,  100,   46,  -25,   46,
   51,   77,   93,  166,   74,  163,   74,   74,   74,   74,
    0,  152,  -31,   62,   52,  310,   87,   74,  -63,  -48,
  -44,   46,  182,   74,  -45,  101,  -56,   68,  134,  -56,
    0, -228,   46,   74,  327,  192,  182,  192, -147, -147,
 -112,    0,  170,    0,   19,   19,    0,    0,    0,  108,
    2,    0,  141,   74,    0,  114,  175,  177,  179,  192,
  -40,  180,    0,    0,  232,    0,   40,    0,    0,  336,
  178,  366,   46,   74,  -35,  187,  195,  -50,  -38,    0,
  -32,  196,  200,  201,  202,  -28,    0,    0,    0,    0,
  372,    0,    0,    0,    0,  203,    0,  -56,    0,   74,
    0,    0,   80,  209,  -56,   74,  210, -150,    0, -147,
    0,   74,   84,  -56,  -56,    0, -112,   74,    0,  153,
  378,   74,    0,  197,  232, -150,    0,    0,    0,    0,
    0,    0,    0,    0,  154,    0,    0,  232,   74,  232,
    0,    0,    0,  352,  239,   74,  232,  154, -150,  148,
    0,    0,  -11,    0,   74,    0,  359,    0,
};
short yyrindex[] = {                                      0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  274,  276,    0,    0,    0,  278,    0,  279,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,  284,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,  285,  289,  290,  -26,  -26,
    0,    0,    0,    0,   -2,    7,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,   36,
    0,    0,    0,    0,  291,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,   30,    0,    0,    0,    0,    0,    0,  -26,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,  -24,  -23,    0,    0,    0,    0,    0,
    0,    0,    0,    0,  -22,    0,    0,  -21,    0,  -20,
    0,    0,    0,    0,    0,    0,  -19,  -18,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,
};
short yygindex[] = {                                      0,
  298,    3,   -4,  116,  110,  -65,    8,  295,  249,    0,
    0,    0,    0,    0,    0,  224,    0,    0,    0,  162,
  160,
};
#define YYTABLESIZE 513
short yytable[] = {                                      11,
   40,   70,   68,   53,   67,  170,   69,   74,   40,   49,
  168,  170,   82,   17,   49,  177,   73,   30,   18,   61,
   31,   33,   40,   39,   32,   34,   51,   19,   53,   50,
   70,   68,   54,   67,   50,   69,   20,   74,   74,   54,
   74,   74,   74,   26,   87,   48,   73,   73,  128,   73,
   73,   73,   72,   83,   73,   98,   88,   74,  129,   74,
   70,   97,   89,  150,   49,   69,   73,   87,   73,   54,
   54,   54,   54,  167,   30,   48,   48,  120,   48,   33,
  111,  216,   87,  158,   50,   93,  169,   31,  131,   54,
   74,   75,  171,   32,  124,   48,  176,  127,   30,   73,
   61,   31,   33,   40,   39,   32,   34,   40,  201,  202,
   82,   50,   43,   40,  187,  188,  189,  190,   21,  191,
   22,   45,   74,  199,   67,  135,   69,  115,  162,   82,
   64,   73,   23,  136,  137,   58,   94,  192,  193,   24,
   91,   25,   70,   68,  194,   67,   59,   69,  138,   70,
   68,   55,   67,   56,   69,   70,   68,   60,   67,   78,
   69,   65,  123,   57,   79,  180,  142,  143,   74,  149,
   27,   80,   81,   99,  126,  152,   87,  144,  145,   28,
   29,  104,   70,   68,  114,   67,   90,   69,  104,   70,
   68,  215,   67,  205,   69,   87,   71,   70,   68,  100,
   67,   52,   69,  104,   70,   68,  102,   67,  117,   69,
  148,   70,   68,  109,   67,  101,   69,   34,  159,  134,
   35,   36,   37,  118,   82,   34,   52,  119,   35,   36,
   37,   84,  122,  134,   38,   39,  153,  156,  154,   87,
  155,  157,   38,   39,   85,    2,  164,  165,    3,    4,
    5,    6,    7,    8,   74,  166,  172,   74,   74,   74,
  173,  174,  175,   73,  179,    9,   73,   73,   73,  182,
  186,   74,   74,   70,   68,   74,   67,  209,   69,  212,
   73,   73,   10,   15,   73,   16,   54,    6,    7,   54,
   54,   54,   48,   10,   12,   48,   48,   48,   11,   13,
    9,  208,   34,   54,   54,   35,   36,   37,   34,   48,
   48,   35,   36,   37,   41,   42,   48,   44,  214,   38,
   39,   92,  112,  141,   34,   38,   39,   35,   36,   37,
   34,  197,    0,   35,   36,   37,  203,   66,    0,    0,
   34,   38,   39,   35,   36,   37,   76,   38,   39,    0,
   86,   70,   68,  114,   67,    0,   69,   38,   39,    0,
    0,    0,  103,    0,  105,  106,  107,  108,  133,   68,
  110,   67,  113,   69,    0,  116,  104,  133,   68,    0,
   67,  121,   69,    0,    0,  125,    0,    0,    0,    0,
  130,  132,  211,   70,   68,    0,   67,    0,   69,  218,
   70,   68,    0,   67,    0,   69,    0,   70,   68,  160,
   67,  151,   69,   70,   68,  178,   67,    0,   69,   70,
   68,  206,   67,    0,   69,    0,    0,    0,    0,    0,
  161,  163,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,  181,    0,    0,
    0,    0,    0,  185,    0,    0,    0,    0,    0,  198,
  200,    0,    0,    0,    0,  204,    0,    0,    0,  207,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,  210,    0,    0,    0,
    0,    0,    0,  213,    0,    0,    0,    0,    0,    0,
    0,    0,  217,
};
short yycheck[] = {                                      10,
   40,   42,   43,   60,   45,   44,   47,   10,   40,   40,
   61,   44,   43,   61,   40,   44,   10,   44,   61,   44,
   44,   44,   44,   44,   44,   44,   24,   40,   60,   60,
   42,   43,   25,   45,   60,   47,   40,   40,   41,   10,
   43,   44,   45,   40,   43,   10,   40,   41,  277,   43,
   44,   45,  269,   51,  271,   60,   54,   60,  287,   62,
   42,   59,   55,   62,   40,   47,   60,   43,   62,   40,
   41,   42,   43,  124,   61,   40,   41,   82,   43,   10,
   73,   93,   43,   44,   60,   40,  125,   61,   93,   60,
   93,   40,  125,   61,   87,   60,  125,   90,  125,   93,
  125,  125,  125,  125,  125,  125,  125,   40,  174,  175,
   43,   60,   41,   40,  265,  266,  267,  268,  271,  270,
  273,   60,  125,   40,   45,  273,   47,   41,  133,   43,
   40,  125,  285,  281,  282,   61,   91,  288,  289,  292,
   41,  294,   42,   43,  295,   45,   61,   47,  296,   42,
   43,  271,   45,  273,   47,   42,   43,   61,   45,  271,
   47,   40,   62,  283,  276,  158,  279,  280,   44,   62,
  277,  283,  284,  123,   41,   62,   43,  290,  291,  286,
  287,   41,   42,   43,   44,   45,   40,   47,   41,   42,
   43,   44,   45,   41,   47,   43,   41,   42,   43,  123,
   45,  258,   47,   41,   42,   43,   41,   45,  272,   47,
   41,   42,   43,   62,   45,  123,   47,  257,   41,   42,
  260,  261,  262,  272,   43,  257,  258,  272,  260,  261,
  262,  271,  278,   42,  274,  275,   62,  278,   62,   43,
   62,   62,  274,  275,  284,  256,  282,   61,  259,  260,
  261,  262,  263,  264,  257,   61,   61,  260,  261,  262,
   61,   61,   61,  257,   62,  276,  260,  261,  262,   61,
   61,  274,  275,   42,   43,  278,   45,  124,   47,   41,
  274,  275,  293,   10,  278,   10,  257,   10,   10,  260,
  261,  262,  257,   10,   10,  260,  261,  262,   10,   10,
   10,  186,  257,  274,  275,  260,  261,  262,  257,  274,
  275,  260,  261,  262,   17,   18,   22,   20,  209,  274,
  275,  276,   74,  100,  257,  274,  275,  260,  261,  262,
  257,  170,   -1,  260,  261,  262,  177,   40,   -1,   -1,
  257,  274,  275,  260,  261,  262,   49,  274,  275,   -1,
   53,   42,   43,   44,   45,   -1,   47,  274,  275,   -1,
   -1,   -1,   65,   -1,   67,   68,   69,   70,   42,   43,
   73,   45,   75,   47,   -1,   78,   41,   42,   43,   -1,
   45,   84,   47,   -1,   -1,   88,   -1,   -1,   -1,   -1,
   93,   94,   41,   42,   43,   -1,   45,   -1,   47,   41,
   42,   43,   -1,   45,   -1,   47,   -1,   42,   43,   44,
   45,  114,   47,   42,   43,   44,   45,   -1,   47,   42,
   43,   44,   45,   -1,   47,   -1,   -1,   -1,   -1,   -1,
  133,  134,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,  160,   -1,   -1,
   -1,   -1,   -1,  166,   -1,   -1,   -1,   -1,   -1,  172,
  173,   -1,   -1,   -1,   -1,  178,   -1,   -1,   -1,  182,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,  199,   -1,   -1,   -1,
   -1,   -1,   -1,  206,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,  215,
};
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
#define YYMAXTOKEN 296
#if YYDEBUG
char *yyname[] = {
"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,"'('","')'","'*'","'+'","','","'-'",0,"'/'",0,0,0,0,0,0,0,0,0,
0,0,0,"'<'","'='","'>'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
"'['",0,"']'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",
"'|'","'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"NUM","STRING","IDENTIFIER","R_VAR","R_FUN",
"R_FUN_R","ADD","ATTRIBUTES","OUTLINED","MOON","STICK","MINIMAL","ALL","NONE",
"ATOM","CENTER","BOND","TRUE","FALSE","CAMERA","VIEW","NAME","PERSPECTIVE",
"SIZE","COLOR","RADIUS","PLOT","GEOMETRY","BOX","POSITION","UP","SOLID",
"TRANSLUCENT","FOREGROUND","BACKGROUND","LINE","HELP","LABEL","FILLED","MODE",
};
char *yyrule[] = {
"$accept : program",
"program :",
"program : program statement",
"program : program error",
"statement : '\\n'",
"statement : command '\\n'",
"command : ADD ATOM select",
"command : ADD BOND select",
"command : ADD BOX",
"command : ADD LABEL string point number",
"command : ADD LINE point point",
"command : CAMERA POSITION '=' point",
"command : CAMERA VIEW '=' direction",
"command : CAMERA UP '=' direction",
"command : HELP",
"command : IDENTIFIER '=' number",
"command : R_VAR '=' number",
"command : R_FUN '(' ')'",
"command : R_FUN_R '(' number ')'",
"$$1 :",
"command : latom '=' $$1 '{' attr_list '}'",
"$$2 :",
"command : lbond '=' $$2 '{' attr_list '}'",
"$$3 :",
"command : lplot '=' $$3 '{' plot_attr_list '}'",
"latom : ATTRIBUTES '(' ATOM string ')'",
"lbond : ATTRIBUTES '(' BOND '(' string ',' string ')' ')'",
"lplot : ATTRIBUTES '(' PLOT ')'",
"attr_list : attr",
"attr_list : attr_list ',' attr",
"attr :",
"attr : RADIUS '=' number",
"attr : BOND RADIUS '=' number",
"attr : MODE '=' mode",
"attr : MODE '|' '=' mode",
"attr : COLOR '=' color",
"plot_attr_list : plot_attr",
"plot_attr_list : plot_attr_list ',' plot_attr",
"plot_attr : SIZE '=' '(' number ',' number ')'",
"plot_attr : SIZE '=' number",
"plot_attr : PERSPECTIVE '=' number",
"plot_attr : FOREGROUND '=' color",
"plot_attr : BACKGROUND '=' color",
"point : '(' number ',' number ',' number ')'",
"point : '<' ATOM number '>'",
"point : '<' GEOMETRY CENTER '>'",
"point : '<' CAMERA CENTER '>'",
"point : '<' PLOT CENTER '>'",
"point : point '+' direction",
"point : '(' point ')'",
"direction : '[' number ',' number ',' number ']'",
"direction : CAMERA VIEW",
"direction : CAMERA UP",
"direction : number '*' direction",
"direction : direction '*' number",
"direction : '(' direction ')'",
"select_item : '<' ATOM number '>'",
"select_item : '<' ALL '>'",
"select_item : '<' ATOM string '>'",
"select : select_item",
"select : select ',' select_item",
"color : string",
"mode_item : FILLED",
"mode_item : OUTLINED",
"mode_item : SOLID",
"mode_item : TRANSLUCENT",
"mode_item : MINIMAL",
"mode_item : MOON",
"mode_item : NONE",
"mode_item : STICK",
"mode : mode_item",
"mode : mode '|' mode_item",
"number : NUM",
"number : number '+' number",
"number : number '-' number",
"number : number '*' number",
"number : number '/' number",
"number : R_VAR",
"number : R_FUN '(' ')'",
"number : R_FUN_R '(' number ')'",
"number : '(' number ')'",
"number : TRUE",
"number : FALSE",
"string : STRING",
"string : '<' GEOMETRY NAME '>'",
"string : '<' ATOM number NAME '>'",
"string : '<' number '>'",
"string : string '+' string",
};
#endif
#ifdef YYSTACKSIZE
#undef YYMAXDEPTH
#define YYMAXDEPTH YYSTACKSIZE
#else
#ifdef YYMAXDEPTH
#define YYSTACKSIZE YYMAXDEPTH
#else
#define YYSTACKSIZE 500
#define YYMAXDEPTH 500
#endif
#endif
int yydebug;
int yynerrs;
int yyerrflag;
int yychar;
short *yyssp;
YYSTYPE *yyvsp;
YYSTYPE yyval;
YYSTYPE yylval;
short yyss[YYSTACKSIZE];
YYSTYPE yyvs[YYSTACKSIZE];
#define yystacksize YYSTACKSIZE
#line 641 "parse.y"

#include <stdio.h>
#include <string.h>
#include <ctype.h>

static struct {
  char *s;
  int n;
} lextable[] = {
  {"add", ADD},
  {"all", ALL},
  {"atom", ATOM},
  {"attributes", ATTRIBUTES},
  {"background", BACKGROUND},
  {"bond", BOND},
  {"box", BOX},
  {"camera", CAMERA},
  {"center", CENTER},
  {"color", COLOR},
  {"exit", 0},
  {"false", FALSE},
  {"filled", FILLED},
  {"foreground", FOREGROUND},
  {"geometry", GEOMETRY},
  {"help", HELP},
  {"label", LABEL},
  {"line", LINE},
  {"minimal", MINIMAL},
  {"moon", MOON},
  {"mode", MODE},
  {"name", NAME},
  {"none", NONE},
  {"outlined", OUTLINED},
  {"perspective", PERSPECTIVE},
  {"plot", PLOT},
  {"position", POSITION},
  {"quit", 0},
  {"radius", RADIUS},
  {"size", SIZE},
  {"solid", SOLID},
  {"stick", STICK},
  {"translucent", TRANSLUCENT},
  {"true", TRUE},
  {"up", UP},
  {"view", VIEW},
  {"?", HELP},
  {NULL, 0}
};

/* Built-in functions.
 */

static double f_reset(void)
{
	DeleteMogulRules(global.parser->rules);
	global.parser->rules = NewMogulRules();
	MogulClearObjects(global.plot);
	return 0.0;
}

static double f_render(void)
{
	if(global.device)
	  MogulRender(global.plot, global.device);
	return 0.0;
}

static double f_plotExtent(void)
{
	double r, c[3];
	MogulObjectExtent(global.plot, c, &r);
	return r;
}

/* Get the next character from the lexical source.
 * Comments are filtered out here.
 */
static int lex_get_char(struct lex_s *lex)
{
	int comment = 0;

	do {

	  lex->lastc = lex->c;
	  lex->c = EOF;

	  switch(lex->type) {
	    case SRC_FILE:
	      lex->c = fgetc(lex->source.f);
	      if(lex->c != EOF) (lex->ch)++;
	      break;

	    case SRC_STRING:
	      if(lex->eof || lex->source.s[lex->ch] == '\0') {
		if(lex->eof)
		  lex->c = EOF;
		else {
		  /* add an extra newline the first time */
		  lex->c = '\n';
		  lex->eof = 1;
		}
	      }
	      else {
		lex->c = lex->source.s[(lex->ch)++];
	      }
	      break;
	  }

	  if(lex->c == '\n') (lex->line)++;

	  if(comment && lex->lastc == '\n') comment = 0;

	  if (lex->c == '#' && lex->lastc == '\n') comment = 1;

	} while(comment);

	return lex->c;
}

static void lex_unget_char(struct lex_s *lex, int c)
{
	if(lex->type == SRC_FILE) ungetc(c, lex->source.f);

	if(c == '\n') --(lex->line);

	if(lex->eof) 
	  lex->eof = 0;
	else
	  --(lex->ch);
}

static int lex_double(struct lex_s *lex, double *d)
{
	int c, l = 0;
	char buf[64];

	while((c = lex_get_char(lex)) != EOF &&
	      strchr("+-.e01234567890", c) && l < 62) buf[l++] = c;

	if(c != EOF) lex_unget_char(lex, c);

	buf[l] = '\0';
	if(sscanf(buf, "%lf", d) == 1) return 1;

	return 0;
}

static int match_keyword(char *keyword)
{
	int i, which = -1, n = 0;
	unsigned int l = strlen(keyword);

	for(i=0; lextable[i].s != NULL; i++) {
	  if(strncmp(keyword, lextable[i].s, l) == 0) {
	    n++;
	    which = i;
	  }
	}

	if(n == 1) return which;

	return -1;
}

#define isokforid(CHAR) (isalnum(CHAR) || (CHAR) == '.' || (CHAR) == '_')

/* This lexical analyzer is a modified version of that found in
 * Stallmans's "mfcalc" program in the BNU bison manual.
 */
#if defined(DEBUG) && 0
int yylex(void)
{
	int x_yylex(void);
	int code = x_yylex();
	switch(code) {
	  case NUM: printf("<NUM %g>", yylval.number); break;
	  case STRING: printf("<STRING \"%s\">", yylval.string); break;
	  case IDENTIFIER: printf("<IDENTIFIER %s>", yylval.sym->name); break;
	  case R_VAR: printf("<R_VAR %s (%g)>", yylval.sym->name, yylval.sym->value.r); break;
	  case R_FUN: printf("<R_FUN %s()>", yylval.sym->name); break;
	  case R_FUN_R: printf("<R_FUN_R %s(x)>", yylval.sym->name); break;
	  case '\n': putchar(code); break;
	  default:
	    if(code < 128 && isprint(code)) printf("<'%c' (code %d)>", (char) code, code);
	    else printf("<code %d>", code);
	    break;
	}
	fflush(stdout);
	return code;
}
int x_yylex(void)
#else
int yylex(void)
#endif
{
	int i, c, which;
	double sign = 1.0;

	static int buflen = 0;
	static char *buf = NULL;

	while((c = lex_get_char(&global.lex)) == ' ' || c == '\t');

	if(c == EOF) return 0;

	/* These can start a number, or be codes of their own.
	 */
	if(c == '+' || c == '-') 
	{
	  int csave = c;
	  c = lex_get_char(&global.lex);
	  if(c == '.' || isdigit(c)) {
	    sign = (csave == '-' ? -1.0 : + 1.0);
	  }
	  else {
	    lex_unget_char(&global.lex, c);
	    return csave;
	  }
	}

	if(c == '.' || isdigit(c))
	{
	  lex_unget_char(&global.lex, c);
	  if(lex_double(&global.lex, &yylval.number) == 1) {
	    yylval.number *= sign;
	    return NUM;
	  }
	  return 0;
	}

	if(isalpha(c))
	{
	  i = 0;
	  while(c != EOF && isokforid(c))
	  {
	    if(i >= buflen) {
	      buflen += 64;
	      buf = ResizePointerArray(buf, buflen);
	    }
	    buf[i++] = c;
	    c = lex_get_char(&global.lex);
	  }

	  lex_unget_char(&global.lex, c);
	  buf[i] = '\0';

	  /* If this is a keyword, return the proper code */
	  if((which = match_keyword(buf)) >= 0) return lextable[which].n;

	  /* Else, it may be an already defined symbol */
	  yylval.sym = find_symtab(global.parser, buf);
	  if(yylval.sym) return yylval.sym->type;

	  /* Finally, it must be a new identifier */
	  yylval.sym = new_symtab(global.parser, AddToStringPool(global.parser->pool, buf), 0);
	  return IDENTIFIER;
	}

	if(c == '"')
	{
	  i = 0;
	  do {
	    c = lex_get_char(&global.lex);
	    if(i >= buflen) {
	      buflen += 64;
	      buf = ResizePointerArray(buf, buflen);
	    }
	    if(c == '\\') {
	      int cc = lex_get_char(&global.lex);
	      switch(cc) {
		case 't': cc = '\t'; break;
		case 'n': cc = '\n'; break;
		default: break;
	      }
	      buf[i++] = cc;
	    }
	    else
	      buf[i++] = c;

	  } while(c != EOF && c != '"');

	  buf[i - 1] = '\0';
	  yylval.string = AddToStringPool(global.parser->pool, buf);
	  return STRING;
	}

	return c;
}

int yyerror(char *s)
{
	static char buf[128];

	if(global.lex.type == SRC_FILE && global.lex.source.f == stdin)
	  sprintf(buf, "%s\n", s);
	else if(global.lex.type == SRC_STRING)
	{
	  int first, last, c;
	  first = global.lex.ch - 16;
	  if(first < 0) first = 0;
	  for(last = first; last < first + 32; last++)
	    if(global.lex.source.s[last] == '\0' ||
	       global.lex.source.s[last] == '\n') break;
	  c = global.lex.source.s[last];
	  global.lex.source.s[last] = '\0';

	  sprintf(buf, "%s (line %d) near \"%s\"\n", s,
	    global.lex.line + 1, global.lex.source.s + first);
	  global.lex.source.s[last] = c;
	}
	else
	  sprintf(buf, "%s (line %d)\n", s, global.lex.line + 1);

	global.nerror++;
	MogulParserMsg = buf;

	return 0;
}

static int do_parse(MogulParser parser, MogulPlot plot, MogulDevice device)
{
	int r = 0, own_nl = 0;

	global.lex.line = global.lex.ch = 0;
	global.lex.eof = 0;
	global.lex.c = '\n'; /* to be stored as the last read character */

	global.plot = plot;
	global.device = device;
	global.parser = parser;
	global.autoRender = 0;

	if(global.g && global.nl == NULL) {
	  global.nl = nlalloc(1.e10);
	  newnl(global.g, global.nl);
	  own_nl = 1;
	}

	global.context = NULL;
	global.ncontext = 0;
	global.nerror = 0;
	push_context(1, INITIAL_CONTEXT);

	if(global.lex.type == SRC_FILE && global.lex.source.f == stdin) {
	  printf("%s", copyrightString);
	  global.prompt = "mogul> ";
	}
	else
	  global.prompt = NULL;

	prompt();
	r = yyparse();

	if(own_nl) nlfree(global.nl);
	delete_context();

	if(r || global.nerror) MogulErrno = MoErrParserError;

	return (r || global.nerror ? -1 : 0);
}

MogulParser NewMogulParser(void)
{
	MogulParser parser = NewPointer(parser);

	static struct {char *name; double (*fun)(double);} fun_r[] = {
	  {"sin", sin}, {"cos", cos}, {"sqrt", sqrt}, {"acos", acos},
	  {"asin", asin}, {"tan", tan}, {"exp", exp}, {"log", log},
	  {NULL, NULL}
	};

	static struct {char *name; double (*fun)(void);} fun[] = {
	  {"reset", f_reset}, {"render", f_render}, {"plotExtent", f_plotExtent},
	  {NULL, NULL}
	};

	parser->rules = NewMogulRules();
	parser->symtab = NULL;
	{ int i;
	  struct symtab_s *sym;
	  for(i=0; fun[i].name; i++) {
	    sym = new_symtab(parser, fun[i].name, R_FUN);
	    sym->value.r_fun = fun[i].fun;
	  }
	  for(i=0; fun_r[i].name; i++) {
	    sym = new_symtab(parser, fun_r[i].name, R_FUN_R);
	    sym->value.r_fun_r = fun_r[i].fun;
	  }
	}
	parser->pool = NewStringPool();
	return parser;
}

void DeleteMogulParser(MogulParser parser)
{
	if(parser) {
	  struct symtab_s *sym, *nsym;
	  DeleteMogulRules(parser->rules);
	  DeleteStringPool(parser->pool);
	  sym = parser->symtab;
	  while(sym) {
	    nsym = sym->next;
	    myfree(sym);
	    sym = nsym;
	  }
	  myfree(parser);
	}
}

/* The geometry or device may be NULL.
 */
int MogulParseString(MogulParser parser,
  char *command, MogulPlot p, MogulDevice device, Geometry *g, NeighborList *nl)
{
	if(command == NULL) return 0;

	global.lex.type = SRC_STRING;
	global.lex.source.s = command;

	global.g = g;
	global.nl = nl;

	return do_parse(parser, p, device);
}

/* The geometry or device may be NULL.
 */
int MogulParseFile(MogulParser parser,
  char *fn, MogulPlot p, MogulDevice device, Geometry *g, NeighborList *nl)
{
	int r;
	FILE *f;

	if(fn == NULL) return 0;

	f = (strcmp(fn, "-") ? fopen(fn, "r") : stdin);
	if(f == NULL) {
	    fprintf(stderr, "mogul: cannot open %s for input\n", fn);
	    return 1;
	}
	global.lex.type = SRC_FILE;
	global.lex.source.f = f;

	global.g = g;
	global.nl = nl;

	r = do_parse(parser, p, device);

	if(f != stdin) fclose(f);

	return r;
}

#line 1119 "y.tab.c"
#define YYABORT goto yyabort
#define YYREJECT goto yyabort
#define YYACCEPT goto yyaccept
#define YYERROR goto yyerrlab
int
#if defined(__STDC__)
yyparse(void)
#else
yyparse()
#endif
{
    register int yym, yyn, yystate;
#if YYDEBUG
    register char *yys;
    extern char *getenv();

    if (yys = getenv("YYDEBUG"))
    {
        yyn = *yys;
        if (yyn >= '0' && yyn <= '9')
            yydebug = yyn - '0';
    }
#endif

    yynerrs = 0;
    yyerrflag = 0;
    yychar = (-1);

    yyssp = yyss;
    yyvsp = yyvs;
    *yyssp = yystate = 0;

yyloop:
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
    if (yychar < 0)
    {
        if ((yychar = yylex()) < 0) yychar = 0;
#if YYDEBUG
        if (yydebug)
        {
            yys = 0;
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
            if (!yys) yys = "illegal-symbol";
            printf("%sdebug: state %d, reading %d (%s)\n",
                    YYPREFIX, yystate, yychar, yys);
        }
#endif
    }
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
    {
#if YYDEBUG
        if (yydebug)
            printf("%sdebug: state %d, shifting to state %d\n",
                    YYPREFIX, yystate, yytable[yyn]);
#endif
        if (yyssp >= yyss + yystacksize - 1)
        {
            goto yyoverflow;
        }
        *++yyssp = yystate = yytable[yyn];
        *++yyvsp = yylval;
        yychar = (-1);
        if (yyerrflag > 0)  --yyerrflag;
        goto yyloop;
    }
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
    {
        yyn = yytable[yyn];
        goto yyreduce;
    }
    if (yyerrflag) goto yyinrecovery;
    yyerror("syntax error");
#ifdef lint
    goto yyerrlab;
#endif
yyerrlab:
    ++yynerrs;
yyinrecovery:
    if (yyerrflag < 3)
    {
        yyerrflag = 3;
        for (;;)
        {
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
            {
#if YYDEBUG
                if (yydebug)
                    printf("%sdebug: state %d, error recovery shifting\
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
#endif
                if (yyssp >= yyss + yystacksize - 1)
                {
                    goto yyoverflow;
                }
                *++yyssp = yystate = yytable[yyn];
                *++yyvsp = yylval;
                goto yyloop;
            }
            else
            {
#if YYDEBUG
                if (yydebug)
                    printf("%sdebug: error recovery discarding state %d\n",
                            YYPREFIX, *yyssp);
#endif
                if (yyssp <= yyss) goto yyabort;
                --yyssp;
                --yyvsp;
            }
        }
    }
    else
    {
        if (yychar == 0) goto yyabort;
#if YYDEBUG
        if (yydebug)
        {
            yys = 0;
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
            if (!yys) yys = "illegal-symbol";
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
                    YYPREFIX, yystate, yychar, yys);
        }
#endif
        yychar = (-1);
        goto yyloop;
    }
yyreduce:
#if YYDEBUG
    if (yydebug)
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
                YYPREFIX, yystate, yyn, yyrule[yyn]);
#endif
    yym = yylen[yyn];
    yyval = yyvsp[1-yym];
    switch (yyn)
    {
case 4:
#line 334 "parse.y"
{ prompt(); }
break;
case 5:
#line 336 "parse.y"
{ if(global.autoRender && global.device)
		      MogulRender(global.plot, global.device);
		    prompt(); }
break;
case 6:
#line 342 "parse.y"
{ int i = 0, ii;
		    double x[3];
		    struct ruleAttributes *rule;

		    for(ii=0; yyvsp[0].select->n > 0 && ii<yyvsp[0].select->n; ii++) {
		      i = yyvsp[0].select->which[ii];
		      rule = MogulGetAtomRule(global.parser->rules, global.g->aname[i]);
		      mmul3(global.g->box, global.g->x + 3*i, x);
		      MogulAddAtom(global.plot, &(rule->attr), x, rule->u.atom.radius);
		    }
		  }
break;
case 7:
#line 354 "parse.y"
{ int ii, i = 0, j = 0, jnl, m;
		    double x1[3], x2[3], dx[3], r1, r2;
		    struct ruleAttributes *rule;

		    for(ii=0; yyvsp[0].select->n > 0 && ii<(yyvsp[0].select->n - 1); ii++)
		    {
		      i = yyvsp[0].select->which[ii];
		      mmul3(global.g->box, global.g->x + 3*i, x1);
		      r1 = MogulGetAtomRule(global.parser->rules, global.g->aname[i])->u.atom.radius;
		      for(jnl=global.nl->mrkr[i]; jnl<(global.nl->mrkr[i+1]); jnl++)
		      {
			j = getnlindex(global.nl->list[jnl]);
			if(is_selected(j, yyvsp[0].select)) {
			  r2 = MogulGetAtomRule(global.parser->rules, global.g->aname[j])->u.atom.radius;
			  rule = MogulGetBondRule(global.parser->rules,
			    global.g->aname[i], global.g->aname[j]);
			  if(Gdisp2(global.g, i, j, dx) < rule->u.bond.bondr * rule->u.bond.bondr)
			  {
			    /* mmul3(global.g->box, global.g->x + 3*j, x2); */
			    mtrn3(global.g->box, dx);
			    for(m=0; m<3; m++) x2[m] = x1[m] + dx[m];
			    MogulAddBondBetween(global.plot, &(rule->attr),
			      x1, r1, x2, r2, rule->u.bond.radius);
			  }
			}
		      }
		    }
		  }
break;
case 8:
#line 383 "parse.y"
{ if(global.g) {
		      struct commonAttributes attr;
		      MogulDefaultAttributes(global.plot, &attr);
		      attr.color = global.plot->attr.foreground;
		      MogulAddBox(global.plot, &attr, global.g);
		    }
		  }
break;
case 9:
#line 391 "parse.y"
{ struct commonAttributes attr;
		    MogulDefaultAttributes(global.plot, &attr);
		    attr.color = global.plot->attr.foreground;
		    MogulAddLabel(global.plot, &attr, yyvsp[-1].point, yyvsp[-2].string, yyvsp[0].number);
		  }
break;
case 10:
#line 397 "parse.y"
{ struct commonAttributes attr;
		    MogulDefaultAttributes(global.plot, &attr);
		    attr.color = global.plot->attr.foreground;
		    MogulAddLine(global.plot, &attr, yyvsp[-1].point, yyvsp[0].point);
		  }
break;
case 11:
#line 403 "parse.y"
{ CameraSetPosition(global.plot->camera, yyvsp[0].point); }
break;
case 12:
#line 405 "parse.y"
{ CameraSetView(global.plot->camera, yyvsp[0].point); }
break;
case 13:
#line 407 "parse.y"
{ CameraSetUp(global.plot->camera, yyvsp[0].point); }
break;
case 14:
#line 409 "parse.y"
{ printf("%s", helpString); }
break;
case 15:
#line 411 "parse.y"
{ yyvsp[-2].sym->type = R_VAR;
		    yyvsp[-2].sym->value.r = yyvsp[0].number;
		  }
break;
case 16:
#line 415 "parse.y"
{ yyvsp[-2].sym->value.r = yyvsp[0].number; }
break;
case 17:
#line 417 "parse.y"
{ yyvsp[-2].sym->value.r_fun(); }
break;
case 18:
#line 419 "parse.y"
{ yyvsp[-3].sym->value.r_fun_r(yyvsp[-1].number); }
break;
case 19:
#line 421 "parse.y"
{ global.tmp.lrule = yyvsp[-1].lrule; }
break;
case 21:
#line 424 "parse.y"
{ global.tmp.lrule = yyvsp[-1].lrule; }
break;
case 23:
#line 427 "parse.y"
{ global.tmp.lplot = yyvsp[-1].lplot; }
break;
case 25:
#line 434 "parse.y"
{ yyval.lrule = MogulGetAtomRule(global.parser->rules, yyvsp[-1].string); }
break;
case 26:
#line 438 "parse.y"
{ yyval.lrule = MogulGetBondRule(global.parser->rules, yyvsp[-4].string, yyvsp[-2].string); }
break;
case 27:
#line 442 "parse.y"
{ yyval.lplot = &(global.plot->attr); }
break;
case 31:
#line 454 "parse.y"
{ switch(global.tmp.lrule->type) {
		      case RULE_ATOM:
			global.tmp.lrule->u.atom.radius = yyvsp[0].number; break;
		      case RULE_BOND:
			global.tmp.lrule->u.bond.radius = yyvsp[0].number; break;
		      default: break;
		    }
		  }
break;
case 32:
#line 463 "parse.y"
{ switch(global.tmp.lrule->type) {
		      case RULE_BOND:
			global.tmp.lrule->u.bond.bondr = yyvsp[0].number; break;
		      default: break;
		    }
		  }
break;
case 33:
#line 470 "parse.y"
{ global.tmp.lrule->attr.mode = yyvsp[0].mode; }
break;
case 34:
#line 472 "parse.y"
{ global.tmp.lrule->attr.mode |= yyvsp[0].mode; }
break;
case 35:
#line 474 "parse.y"
{ global.tmp.lrule->attr.color = yyvsp[0].color; }
break;
case 38:
#line 482 "parse.y"
{ global.tmp.lplot->width = check_range(yyvsp[-3].number, MIN_PLOT_SIZE, MAX_PLOT_SIZE);
		    global.tmp.lplot->height = check_range(yyvsp[-1].number, MIN_PLOT_SIZE, MAX_PLOT_SIZE);
		  }
break;
case 39:
#line 486 "parse.y"
{ global.tmp.lplot->width = check_range(yyvsp[0].number, MIN_PLOT_SIZE, MAX_PLOT_SIZE);
		    global.tmp.lplot->height = check_range(yyvsp[0].number, MIN_PLOT_SIZE, MAX_PLOT_SIZE);
		  }
break;
case 40:
#line 490 "parse.y"
{ global.tmp.lplot->vdist = yyvsp[0].number; }
break;
case 41:
#line 492 "parse.y"
{ global.tmp.lplot->foreground = yyvsp[0].color; }
break;
case 42:
#line 494 "parse.y"
{ global.tmp.lplot->background = yyvsp[0].color; }
break;
case 43:
#line 500 "parse.y"
{ yyval.point[0] = yyvsp[-5].number;
		    yyval.point[1] = yyvsp[-3].number;
		    yyval.point[2] = yyvsp[-1].number; }
break;
case 44:
#line 504 "parse.y"
{ if(global.g && yyvsp[-1].number >= 0 && yyvsp[-1].number < global.g->n)
		      set3(yyval.point, mmul3(global.g->box, global.g->x + 3 * ((int) yyvsp[-1].number), global.tmp.p));
		    else {
		      yyerror("invalid atom number");
		      YYERROR;
		    }
		  }
break;
case 45:
#line 512 "parse.y"
{ int i;
		    for(i=0; i<3; i++) yyval.point[i] = 0.0;
		    if(global.g) {
		      for(i=0; i<global.g->n; i++) {
			yyval.point[0] += global.g->x[3*i];
			yyval.point[1] += global.g->x[3*i + 1];
			yyval.point[2] += global.g->x[3*i + 2];
		      }
		      for(i=0; i<3; i++) yyval.point[i] /= global.g->n;
		    }
		  }
break;
case 46:
#line 524 "parse.y"
{ set3(yyval.point, CameraGetPosition(global.plot->camera, global.tmp.p)); }
break;
case 47:
#line 526 "parse.y"
{
		  double r;
		  MogulObjectExtent(global.plot, yyval.point, &r);
		}
break;
case 48:
#line 531 "parse.y"
{ set3(yyval.point, yyvsp[-2].point); add3(yyval.point, yyvsp[0].point); }
break;
case 49:
#line 533 "parse.y"
{ set3(yyval.point, yyvsp[-1].point); }
break;
case 50:
#line 537 "parse.y"
{ yyval.point[0] = yyvsp[-5].number;
		    yyval.point[1] = yyvsp[-3].number;
		    yyval.point[2] = yyvsp[-1].number; }
break;
case 51:
#line 541 "parse.y"
{ set3(yyval.point, CameraGetView(global.plot->camera, global.tmp.p)); }
break;
case 52:
#line 543 "parse.y"
{ set3(yyval.point, CameraGetUp(global.plot->camera, global.tmp.p)); }
break;
case 53:
#line 545 "parse.y"
{ set3(yyval.point, yyvsp[0].point); mul31(yyval.point, yyvsp[-2].number); }
break;
case 54:
#line 547 "parse.y"
{ set3(yyval.point, yyvsp[-2].point); mul31(yyval.point, yyvsp[0].number); }
break;
case 55:
#line 549 "parse.y"
{ set3(yyval.point, yyvsp[-1].point); }
break;
case 56:
#line 556 "parse.y"
{ if(global.g && ((int) yyvsp[-1].number) >= 0 && ((int) yyvsp[-1].number) < global.g->n)
		      yyval.select = select_range((int) yyvsp[-1].number, (int) yyvsp[-1].number + 1);
		    else {
		      yyerror("invalid atom number");
		      YYERROR;
		    }
		  }
break;
case 57:
#line 564 "parse.y"
{ yyval.select = select_range(0, global.g ? global.g->n : 0); }
break;
case 58:
#line 566 "parse.y"
{ int i;
		    yyval.select = select_range(0, 0);
		    if(global.g) {
		      for(i=0; i<global.g->n; i++) {
			if(!strcmp(global.g->aname[i], yyvsp[-1].string))
			  yyval.select = select_union(yyval.select, select_range(i, i + 1));
		      }
		    }
		  }
break;
case 60:
#line 579 "parse.y"
{ yyval.select = select_union(yyvsp[-2].select, yyvsp[0].select); }
break;
case 61:
#line 583 "parse.y"
{ yyval.color = ColorFromName(yyvsp[0].string); }
break;
case 62:
#line 586 "parse.y"
{ yyval.mode = MA_FILLED; }
break;
case 63:
#line 587 "parse.y"
{ yyval.mode = MA_OUTLINE; }
break;
case 64:
#line 588 "parse.y"
{ yyval.mode = MA_SOLID; }
break;
case 65:
#line 589 "parse.y"
{ yyval.mode = MA_TRANSLUCENT; }
break;
case 66:
#line 590 "parse.y"
{ yyval.mode = MA_MINIMAL; }
break;
case 67:
#line 591 "parse.y"
{ yyval.mode = MA_MOON; }
break;
case 68:
#line 592 "parse.y"
{ yyval.mode = 0; }
break;
case 69:
#line 593 "parse.y"
{ yyval.mode = MA_STICK; }
break;
case 71:
#line 597 "parse.y"
{ yyval.mode = yyvsp[-2].mode | yyvsp[0].mode; }
break;
case 73:
#line 603 "parse.y"
{ yyval.number = yyvsp[-2].number + yyvsp[0].number; }
break;
case 74:
#line 604 "parse.y"
{ yyval.number = yyvsp[-2].number - yyvsp[0].number; }
break;
case 75:
#line 605 "parse.y"
{ yyval.number = yyvsp[-2].number * yyvsp[0].number; }
break;
case 76:
#line 606 "parse.y"
{ yyval.number = yyvsp[-2].number / yyvsp[0].number; }
break;
case 77:
#line 607 "parse.y"
{ yyval.number = yyvsp[0].sym->value.r; }
break;
case 78:
#line 608 "parse.y"
{ yyval.number = yyvsp[-2].sym->value.r_fun(); }
break;
case 79:
#line 609 "parse.y"
{ yyval.number = yyvsp[-3].sym->value.r_fun_r(yyvsp[-1].number); }
break;
case 80:
#line 610 "parse.y"
{ yyval.number = yyvsp[-1].number; }
break;
case 81:
#line 611 "parse.y"
{ yyval.number = 1.0; }
break;
case 82:
#line 612 "parse.y"
{ yyval.number = 0.0; }
break;
case 84:
#line 617 "parse.y"
{ yyval.string = global.g ? AddToStringPool(global.parser->pool, global.g->name) : ""; }
break;
case 85:
#line 619 "parse.y"
{ if(global.g && yyvsp[-2].number >= 0 && yyvsp[-2].number < global.g->n)
		      yyval.string = global.g->aname[(int) yyvsp[-2].number];
		    else {
		      yyerror("invalid atom numer");
		      YYERROR;
		    }
		  }
break;
case 86:
#line 627 "parse.y"
{ char buf[64];
		    sprintf(buf, "%g", yyvsp[-1].number);
		    yyval.string = AddToStringPool(global.parser->pool, buf);
		  }
break;
case 87:
#line 632 "parse.y"
{ char *buf = mymalloc(sizeof(char) * (strlen(yyvsp[-2].string) + strlen(yyvsp[0].string) + 1));
		    strcpy(buf, yyvsp[-2].string);
		    strcat(buf, yyvsp[0].string);
		    yyval.string = AddToStringPool(global.parser->pool, buf);
		    myfree(buf);
		  }
break;
#line 1670 "y.tab.c"
    }
    yyssp -= yym;
    yystate = *yyssp;
    yyvsp -= yym;
    yym = yylhs[yyn];
    if (yystate == 0 && yym == 0)
    {
#if YYDEBUG
        if (yydebug)
            printf("%sdebug: after reduction, shifting from state 0 to\
 state %d\n", YYPREFIX, YYFINAL);
#endif
        yystate = YYFINAL;
        *++yyssp = YYFINAL;
        *++yyvsp = yyval;
        if (yychar < 0)
        {
            if ((yychar = yylex()) < 0) yychar = 0;
#if YYDEBUG
            if (yydebug)
            {
                yys = 0;
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
                if (!yys) yys = "illegal-symbol";
                printf("%sdebug: state %d, reading %d (%s)\n",
                        YYPREFIX, YYFINAL, yychar, yys);
            }
#endif
        }
        if (yychar == 0) goto yyaccept;
        goto yyloop;
    }
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
        yystate = yytable[yyn];
    else
        yystate = yydgoto[yym];
#if YYDEBUG
    if (yydebug)
        printf("%sdebug: after reduction, shifting from state %d \
to state %d\n", YYPREFIX, *yyssp, yystate);
#endif
    if (yyssp >= yyss + yystacksize - 1)
    {
        goto yyoverflow;
    }
    *++yyssp = yystate;
    *++yyvsp = yyval;
    goto yyloop;
yyoverflow:
    yyerror("yacc stack overflow");
yyabort:
    return (1);
yyaccept:
    return (0);
}
