#ifndef lint
char mp_sccsid[] = "@(#)yaccpar	1.4 (Berkeley) 02/25/90";
#endif
#line 2 "missionPlan.y"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include "mpdefs.h"
#include "MissionPlan.h"
#include "BehaviorFactory.h"
#include "Syslog.h"

Boolean debug = False;


/* Function prototypes*/
int mp_error(char *errorBuf);
int mp_lex();
int mp_parse();

char parseErrorBuf[512];

const int eofReturn = -1;
const int errorReturn = 1;
const int okReturn = 0;

/* Function prototypes */
int mplanFileLineNo();


void clearInputs();

BehaviorStack *_behaviorStack;
BehaviorFactory *_behaviorFactory = BehaviorFactory::instanceOf();
Behavior *_behavior = 0;

AttributeInputs attributeInputs;

#line 40 "missionPlan.y"
typedef union 
{
  int integer;
  char *string;
} YYSTYPE;
#line 48 "missionPlan.tab.c"
#define Word 257
#define BehaviorTag 258
#define YYERRCODE 256
short mp_lhs[] = {                                        -1,
    0,    1,    1,    2,    4,    4,    5,    3,
};
short mp_len[] = {                                         2,
    1,    2,    1,    3,    1,    2,    4,    3,
};
short mp_defred[] = {                                      0,
    0,    0,    0,    3,    0,    0,    2,    0,    0,    5,
    8,    0,    4,    6,    0,    7,
};
short mp_dgoto[] = {                                       2,
    3,    4,    5,    9,   10,
};
short mp_sindex[] = {                                   -257,
 -255,    0, -257,    0, -254, -119,    0,  -56, -125,    0,
    0, -251,    0,    0,  -52,    0,
};
short mp_rindex[] = {                                      0,
    0,    0,    8,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,
};
short mp_gindex[] = {                                      0,
    0,    6,    0,    0,    1,
};
#define YYTABLESIZE 132
short mp_table[] = {                                      13,
    1,    6,    8,   11,   12,   15,   16,    1,    7,   14,
    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,    8,
};
short mp_check[] = {                                     125,
  258,  257,  257,  123,   61,  257,   59,    0,    3,    9,
   -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,   -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,
   -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,   -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,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,  257,
};
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
#define YYMAXTOKEN 258
#if YYDEBUG
char *yyname[] = {
"end-of-file",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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"Word",
"BehaviorTag",
};
char *yyrule[] = {
"$accept : MissionPlan",
"MissionPlan : Behaviors",
"Behaviors : Behaviors Behavior",
"Behaviors : Behavior",
"Behavior : StartBehavior Attributes '}'",
"Attributes : Attribute",
"Attributes : Attributes Attribute",
"Attribute : Word '=' Word ';'",
"StartBehavior : BehaviorTag Word '{'",
};
#endif
#define yyclearin (mp_char=(-1))
#define yyerrok (mp_errflag=0)
#ifndef YYSTACKSIZE
#ifdef YYMAXDEPTH
#define YYSTACKSIZE YYMAXDEPTH
#else
#define YYSTACKSIZE 300
#endif
#endif
int mp_debug;
int mp_nerrs;
int mp_errflag;
int mp_char;
short *mp_ssp;
YYSTYPE *mp_vsp;
YYSTYPE mp_val;
YYSTYPE mp_lval;
#define yystacksize YYSTACKSIZE
short mp_ss[YYSTACKSIZE];
YYSTYPE mp_vs[YYSTACKSIZE];
#line 158 "missionPlan.y"

extern char *mp_text;

int mp_error(char *errorMsg)
{
  sprintf(parseErrorBuf, 
	  "Line %d: %s\noffending text: \"%s\"", 
	  mplanFileLineNo(), errorMsg, mp_text);
  
  return 0;
}


void clearInputs()
{

  for (int i = 0; i < attributeInputs.size(); i++) {
    Attribute::Input *input;
    attributeInputs.get(i, &input);
    delete input;
  }

  attributeInputs.clear();
}


void MissionPlan::parse(FILE *fp, BehaviorStack *behaviorStack, 
			Boolean *error, char *errorMsg)
{
  int ret;
  extern FILE *mp_in;

  _behaviorStack = behaviorStack;

  if (_behaviorStack) {
    _behaviorStack->clear();
  }

  *error = False;
  mp_in = fp;
  
  if ((ret = mp_parse()) != okReturn)
  {
    /* Error or end-of-file */
    if (ret == errorReturn)
    {
      *error = True;
      strcpy(errorMsg, parseErrorBuf);
    }
  }
  
  clearInputs();
  return;
}

#line 213 "missionPlan.tab.c"
#define YYABORT goto yyabort
#define YYACCEPT goto yyaccept
#define YYERROR goto yyerrlab
int
mp_parse()
{
    register int yym, yyn, yystate;
#if YYDEBUG
    register char *yys;
    extern char *getenv();

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

    mp_nerrs = 0;
    mp_errflag = 0;
    mp_char = (-1);

    mp_ssp = mp_ss;
    mp_vsp = mp_vs;
    *mp_ssp = yystate = 0;

yyloop:
    if (yyn = mp_defred[yystate]) goto yyreduce;
    if (mp_char < 0)
    {
        if ((mp_char = mp_lex()) < 0) mp_char = 0;
#if YYDEBUG
        if (mp_debug)
        {
            yys = 0;
            if (mp_char <= YYMAXTOKEN) yys = yyname[mp_char];
            if (!yys) yys = "illegal-symbol";
            printf("mp_debug: state %d, reading %d (%s)\n", yystate,
                    mp_char, yys);
        }
#endif
    }
    if ((yyn = mp_sindex[yystate]) && (yyn += mp_char) >= 0 &&
            yyn <= YYTABLESIZE && mp_check[yyn] == mp_char)
    {
#if YYDEBUG
        if (mp_debug)
            printf("mp_debug: state %d, shifting to state %d\n",
                    yystate, mp_table[yyn]);
#endif
        if (mp_ssp >= mp_ss + yystacksize - 1)
        {
            goto yyoverflow;
        }
        *++mp_ssp = yystate = mp_table[yyn];
        *++mp_vsp = mp_lval;
        mp_char = (-1);
        if (mp_errflag > 0)  --mp_errflag;
        goto yyloop;
    }
    if ((yyn = mp_rindex[yystate]) && (yyn += mp_char) >= 0 &&
            yyn <= YYTABLESIZE && mp_check[yyn] == mp_char)
    {
        yyn = mp_table[yyn];
        goto yyreduce;
    }
    if (mp_errflag) goto mp_inrecovery;
#ifdef lint
    goto yynewerror;
#endif
yynewerror:
    mp_error("syntax error");
#ifdef lint
    goto yyerrlab;
#endif
yyerrlab:
    ++mp_nerrs;
mp_inrecovery:
    if (mp_errflag < 3)
    {
        mp_errflag = 3;
        for (;;)
        {
            if ((yyn = mp_sindex[*mp_ssp]) && (yyn += YYERRCODE) >= 0 &&
                    yyn <= YYTABLESIZE && mp_check[yyn] == YYERRCODE)
            {
#if YYDEBUG
                if (mp_debug)
                    printf("mp_debug: state %d, error recovery shifting\
 to state %d\n", *mp_ssp, mp_table[yyn]);
#endif
                if (mp_ssp >= mp_ss + yystacksize - 1)
                {
                    goto yyoverflow;
                }
                *++mp_ssp = yystate = mp_table[yyn];
                *++mp_vsp = mp_lval;
                goto yyloop;
            }
            else
            {
#if YYDEBUG
                if (mp_debug)
                    printf("mp_debug: error recovery discarding state %d\n",
                            *mp_ssp);
#endif
                if (mp_ssp <= mp_ss) goto yyabort;
                --mp_ssp;
                --mp_vsp;
            }
        }
    }
    else
    {
        if (mp_char == 0) goto yyabort;
#if YYDEBUG
        if (mp_debug)
        {
            yys = 0;
            if (mp_char <= YYMAXTOKEN) yys = yyname[mp_char];
            if (!yys) yys = "illegal-symbol";
            printf("mp_debug: state %d, error recovery discards token %d (%s)\n",
                    yystate, mp_char, yys);
        }
#endif
        mp_char = (-1);
        goto yyloop;
    }
yyreduce:
#if YYDEBUG
    if (mp_debug)
        printf("mp_debug: state %d, reducing by rule %d (%s)\n",
                yystate, yyn, yyrule[yyn]);
#endif
    yym = mp_len[yyn];
    mp_val = mp_vsp[1-yym];
    switch (yyn)
    {
case 1:
#line 52 "missionPlan.y"
{
}
break;
case 2:
#line 57 "missionPlan.y"
{
}
break;
case 3:
#line 62 "missionPlan.y"
{
}
break;
case 4:
#line 67 "missionPlan.y"
{
  dprintf("Finished parsing Behavior %s\n", _behavior->name());

  Boolean error = False;
  for (int i = 0; i < attributeInputs.size(); i++) {
    Attribute::Input *input;
    attributeInputs.get(i, &input);

    if (_behavior->attributes.parse(input) == -1) {
      error = True;
    }
  }

  if (error) {
    sprintf(parseErrorBuf, "Parse failed for one or more attribute inputs");
    return errorReturn;
  }

  if (_behavior->attributes.verify() == -1) {
    sprintf(parseErrorBuf, "verify() failed for behavior %s\n", 
	    _behavior->name());
    error = True;
  }

  if (!_behavior->validInput()) {
    sprintf(parseErrorBuf, "validInput() failed for behavior %s\n", 
	    _behavior->name());

    error = True;    
  }

  if (!error ) {

    /* Add to stack*/
    _behaviorStack->add(&_behavior);
  }
  else {
    return errorReturn;
  }
}
break;
case 5:
#line 110 "missionPlan.y"
{
  dprintf("Attributes\n");
}
break;
case 6:
#line 116 "missionPlan.y"
{
  dprintf("Attributes\n");
}
break;
case 7:
#line 122 "missionPlan.y"
{
  dprintf("Got Attribute:  %s = %s\n", mp_vsp[-3].string , mp_vsp[-1].string );

  Attribute::Input *input = new Attribute::Input(mp_vsp[-3].string , mp_vsp[-1].string );

  if (_behavior->attributes.parse(input) == -1) {
    sprintf(parseErrorBuf, 
	    "Line %d: Invalid attribute for behavior %s: \"%s\"", 
	    mplanFileLineNo(), _behavior->name(), input->name);

    return errorReturn;
  }

  attributeInputs.add(&input);
}
break;
case 8:
#line 140 "missionPlan.y"
{
  dprintf("StartBehavior %s\n", mp_vsp[-1].string );
  const char *behaviorName = mp_vsp[-1].string ;

  clearInputs();

  if ((_behavior = _behaviorFactory->create(behaviorName)) == 0) {

    sprintf(parseErrorBuf, "Line %d: Unknown behavior type name: \"%s\"\n",
	    mplanFileLineNo(), behaviorName);

    return errorReturn;
  }
}
break;
#line 458 "missionPlan.tab.c"
    }
    mp_ssp -= yym;
    yystate = *mp_ssp;
    mp_vsp -= yym;
    yym = mp_lhs[yyn];
    if (yystate == 0 && yym == 0)
    {
#ifdef YYDEBUG
        if (mp_debug)
            printf("mp_debug: after reduction, shifting from state 0 to\
 state %d\n", YYFINAL);
#endif
        yystate = YYFINAL;
        *++mp_ssp = YYFINAL;
        *++mp_vsp = mp_val;
        if (mp_char < 0)
        {
            if ((mp_char = mp_lex()) < 0) mp_char = 0;
#if YYDEBUG
            if (mp_debug)
            {
                yys = 0;
                if (mp_char <= YYMAXTOKEN) yys = yyname[mp_char];
                if (!yys) yys = "illegal-symbol";
                printf("mp_debug: state %d, reading %d (%s)\n",
                        YYFINAL, mp_char, yys);
            }
#endif
        }
        if (mp_char == 0) goto yyaccept;
        goto yyloop;
    }
    if ((yyn = mp_gindex[yym]) && (yyn += yystate) >= 0 &&
            yyn <= YYTABLESIZE && mp_check[yyn] == yystate)
        yystate = mp_table[yyn];
    else
        yystate = mp_dgoto[yym];
#ifdef YYDEBUG
    if (mp_debug)
        printf("mp_debug: after reduction, shifting from state %d \
to state %d\n", *mp_ssp, yystate);
#endif
    if (mp_ssp >= mp_ss + yystacksize - 1)
    {
        goto yyoverflow;
    }
    *++mp_ssp = yystate;
    *++mp_vsp = mp_val;
    goto yyloop;
yyoverflow:
    mp_error("yacc stack overflow");
yyabort:
    return (1);
yyaccept:
    return (0);
}
