%{
/************************************************
  Team: Jon Gregory, Gor Nishanov
  Project #2 Part 2
    for RPI course 66-648 Compiler Design Theory

  java.y:

    to do: try finally, static initializer and interfaces

    */

#include <stdlib.h>
#define YYERROR_VERBOSE 1

#define REPORT(cond,code)

#include <iostream.h>
#include <new.h>
#include <assert.h>
#include <string.h>

#include "tree.h"

Environment env;
int yyerror(char *s);
int yylex();

%}

%union {
  int modifier;
  int opval;
  Class * clazz;
  Field * field;
  Package * pkg;

  Type   * type;
  Method * method;

  ExprList * exprs;
  StmtList * stmts;

  Expression * expr;
  Statement  * stmt;

  IdentProxy id;
}

%token <id> ident
%type  <id> SimpleName oIdent

%type <expr> QualifiedName
%type <expr> Name

%type <type> ClassOrInterfaceType ClassType InterfaceType
%type <type> Type ReferenceType ArrayType

%type <method> MethodDeclarator ConstructorDeclarator

%type <stmt> MethodBody ConstructorBody

%type <expr> VariableDeclaratorId VariableDeclarator FieldAccess

%token <expr> _this_ _super_ 

%type <expr> NewClassInstance oArgList Expression ThisOrSuper
%type <expr> VariableInitializer ArrayInitializer 
%type <expr> StatementExpression  Assignment PreIncDec PostIncDec
%type <expr> MethodInvocation
%type <expr> ConstantExpression UnaryNotPM CastExpr

%type <exprs> ArgList VariableDeclarators
%type <exprs> oVariableInitializers VariableInitializers

%type <stmt> ExplicitConstructorInvocation
%type <stmt> Block oBlockStatements BlockStatement Statement
%type <stmt> LocalVariableDeclarationStatement
%type <stmt> LocalVariableDeclaration
%type <stmt> StatementNoShortIf  
%type <stmt> StatementWithoutTrailingSubstatement
%type <stmt> LabeledStatementNoShortIf
%type <stmt> IfThenElseStatementNoShortIf
%type <stmt> WhileStatementNoShortIf
%type <stmt> ForStatementNoShortIf 
%type <stmt> LabeledStatement
%type <stmt> IfThenStatement
%type <stmt> IfThenElseStatement
%type <stmt> WhileStatement
%type <stmt> ForStatement 
%type <stmt> ExpressionStatement
%type <stmt> SwitchStatement
%type <stmt> DoStatement
%type <stmt> BreakStatement
%type <stmt> ContinueStatement
%type <stmt> ReturnStatement
%type <stmt> SynchronizedStatement
%type <stmt> ThrowStatement SwitchBlock
%type <stmt> TryStatement EmptyStatement SwitchLabel
%type <stmt> oForInit ForInit ;

%type <expr> oForUpdate ForUpdate oForExpression
%type <expr> StatementExpressionList

%type <stmts> BlockStatements 
%type <stmts> SwitchLabels SwitchBlockStatementGroups SwitchBlockStatementGroup

%type <expr> AssignExpression ArrayAccess Postfix AddExpr
%type <expr> Primary NoNewArray ArrayCreation Unary MulExpr
%type <expr> ShiftExpr RelExpr EqualExpr AndExpr XorExpr OrExpr
%type <expr> AndAlso OrElse CondExpr LeftHandSide

%type <expr> SaveElem /* small kludge */

%token <expr> Literal  /* IntegerLiteral FloatingPointLiteral BooleanLiteral
                          CharacterLiteral StringLiteral  NullLiteral */

%token _new_ _instanceof_ _interface_
%token _if_ _else_ _switch_ _case_ _default_ _while_ 
%token _do_ _for_ _break_ _continue_ _return_ _throw_ 
%token _try_  _catch_ _finally_

%token _class_ _extends_ _implements_ _package_ _import_ _throws_

%token _andand_ _oror_

%token <type> PrimitiveType /* bool int ... */
%token <type> _void_

%token <opval> IncDec        /* ++ -- */
%token <opval> MulOp         /* * / % */
%token <opval> AddOp         /* + - */
%token <opval> NegNot        /* ! ~ */
%token <opval> ShiftOp       /* << >> >>> */
%token <opval> RelOp         /* < > <= >= */
%token <opval> EqualOp       /* == != */
%token <opval> AssOp         /* = *= /= %= += -= <<= >>= >>>= &= ^= |= */

%token <modifier> _static_       /* special handling in StaticInitialization */
%token <modifier> _synchronized_ /* used in sychronized statement */
	/* all other modifiers are represented by the token Modifier1 */
%token <modifier> Modifier1      /* public protected private abstract
                         final native transient volatile */

%type <modifier> oModifiers Modifiers Modifier
 
%type <clazz> ClassDeclaration InterfaceDeclaration 
%type <clazz> TypeDeclaration TypeDeclarations

%type <name> oSuper

  /* Maybe it's good to allow method declaration in
		 the form int a() {...};
     Though, it is not in the syntax. Sun's java compiler
     eats this without a glitch */

%%
Goal3: CompilationUnit;

Modifier: _static_       {$$ = $1;}
        | _synchronized_ {$$ = $1;}
        | Modifier1      {$$ = $1;}
        ;

oModifiers: {$$ = 0;}
          | Modifiers {$$ = $1;}
          ;

Modifiers: Modifier {$$ = $1;} 
         | Modifiers Modifier {
             REPORT( $1 & $2 , ER_REPEATED_MODIFIER);
             $$ = $1 | $2; }
         ;


/****************** Names ***************************/

Name: SimpleName    {$$ = new IdentifierExpression($1); }
    | QualifiedName {$$ = $1; };

SimpleName: ident ;
QualifiedName:  Name '.' ident { $$ = new FieldExpression($1,$3); };

/****************** Packages **************************/

CompilationUnit:
          PackageDeclaration oImportDeclarations oTypeDeclarations

oImportDeclarations: ImportDeclarations {} 
                   | /* e */            {};
oTypeDeclarations:   TypeDeclarations   {}
                 | /* e */              {};

ImportDeclarations
:            ImportDeclaration
|            ImportDeclarations ImportDeclaration
;

TypeDeclaration: ClassDeclaration
|                InterfaceDeclaration 
|                ';'                   {$$ = 0;};

TypeDeclarations
:            TypeDeclaration
|            TypeDeclarations TypeDeclaration
;

PackageDeclaration:  _package_ Name ';' {env.pkg = new Package($2); }
|                               /* e */ {env.pkg = new Package(0); };

ImportDeclaration
:            SingleTypeImportDeclaration
|            TypeImportOnDemandDeclaration
;

SingleTypeImportDeclaration:   _import_ Name ';' {env.pkg->imports.add($2) };

TypeImportOnDemandDeclaration:  _import_ Name '.' MulOp ';' {
  assert($4 == MUL);
  env.pkg->imports.add( new FieldExpression($2, Identifier::star) );
};

/******************* Classes ************************/

ClassDeclaration:
   oModifiers _class_ ident {env.addNewClass(new Class($3,$1));}  
   oSuper oInterfaces ClassBody {};

oSuper: {env.clazz->super = Type::Object; }
      | _extends_ ClassType {env.clazz->super = $2;};

oInterfaces: /* e */ {} 
           | _implements_ InterfaceTypeList {};

InterfaceTypeList:      InterfaceType {env.clazz->interfaces.add($1); }
| InterfaceTypeList ',' InterfaceType {env.clazz->interfaces.add($3); };

ClassBody:   '{' oClassBodyDeclarations '}' ;

oClassBodyDeclarations: /* e */ | ClassBodyDeclarations;

ClassBodyDeclarations: ClassBodyDeclaration
|                      ClassBodyDeclarations ClassBodyDeclaration ;

ClassBodyDeclaration:  ClassMemberDeclaration
|                      StaticInitializer
|                      ConstructorDeclaration ;

ClassMemberDeclaration: FieldDeclaration
|                       MethodDeclaration ;

/* 19.8.2 */

FieldDeclaration:  oModifiers Type VariableDeclarators ';' {
  env.clazz->fields.add( 
    new DeclarationStatement($1,new TypeExpression($2), 
                                new ExpressionStatement($3->first))); 
};

/****************** Declaration *********************/

VariableDeclarators:  VariableDeclarator { $$ = new ExprList($1); }
| VariableDeclarators ',' VariableDeclarator {$$=$1; $$->add($3); } 
;

VariableDeclarator: 
  VariableDeclaratorId { $$ = $1; }
| VariableDeclaratorId AssOp VariableInitializer {
  assert($2 == ASSIGN);  
  $1 = new BinaryAssignExpression(ASSIGN, $1, $3);
};

VariableDeclaratorId: 
  ident { $$ = new IdentifierExpression($1); }
| VariableDeclaratorId '[' ']' { $$ = new ArrayAccessExpression($1,0); };

VariableInitializer: Expression {$$ = $1; }
                   | ArrayInitializer {$$ = $1;};

/* 19.8.3 */


MethodDeclaration: MethodHeader MethodBody {
  env.method->body = $2;
};

MethodHeader: oModifiers _void_ MethodDeclarator Throws 
  {env.method->modifiers = $1; env.method->type = $2;} 
| oModifiers Type MethodDeclarator Throws 
  {env.method->modifiers = $1; env.method->type = $2;}
;

MethodDeclarator: ident '(' {env.addMethod( new Method($1) ); }
                            oFormalParameterList ')'
|                 MethodDeclarator '[' ']' {++env.method->dims;};

oFormalParameterList: /* e */ {} | FormalParameterList {};

FormalParameterList:  FormalParameter {}
|                     FormalParameterList ',' FormalParameter {};

FormalParameter:      Type VariableDeclaratorId {
  env.method->params.add(new Parameter($2, $1));
};

Throws: /* e */ | _throws_ ClassTypeList

ClassTypeList:  ClassType {env.method->throwz.add($1); }
|               ClassTypeList ',' ClassType {env.method->throwz.add($3); };
MethodBody:  Block {$$ = $1;}
          | ';' {$$ = env.empty_block;} ;

/* 19.8.4 */

StaticInitializer: _static_ Block {env.clazz->inits.add($2); };

/* 19.8.5 Productions from 8.6: Constructor Declarations */

ConstructorDeclaration:
  oModifiers ConstructorDeclarator Throws ConstructorBody {
    env.method -> modifiers = $1;
    env.method -> type = Type::Void;
    env.method ->body = $4;
};

ConstructorDeclarator: // Later check SimpleName = ClassName
             SimpleName '(' {env.method = new Method($1); }
                            oFormalParameterList ')';

ConstructorBody: '{' ExplicitConstructorInvocation oBlockStatements '}'
  { $$ = new CompoundStatement( $2->glue($3) ); } 
| '{' oBlockStatements '}' { $$ = new CompoundStatement($2); } ; // !! def ctor

ThisOrSuper: _this_ | _super_ ;

ExplicitConstructorInvocation: ThisOrSuper  '(' oArgList ')' ';' {
  $$ = new ExpressionStatement(
             new MethodExpression($1, Identifier::init, $3)); 
};

/* 19.9 Productions from p.9: Interfaces */

InterfaceDeclaration:
  oModifiers _interface_ ident {
    env.addNewClass(new Class($3,$1 | ACC_INTERFACE));}
           ExtendsInterfaces InterfaceBody ;

ExtendsInterfaces: _extends_ InterfaceType {env.clazz->interfaces.add($2); }
| ExtendsInterfaces ',' InterfaceType      {env.clazz->interfaces.add($3); };

InterfaceBody:
             '{' oInterfaceMemberDeclarations '}' ;

oInterfaceMemberDeclarations: 
   /* e */ | InterfaceMemberDeclarations;

InterfaceMemberDeclarations:
             InterfaceMemberDeclaration
|            InterfaceMemberDeclarations InterfaceMemberDeclaration ;

InterfaceMemberDeclaration:
             ConstantDeclaration
|            AbstractMethodDeclaration ;

ConstantDeclaration:
             FieldDeclaration;

AbstractMethodDeclaration:
             MethodHeader ';' ;

/* 19.10 Productions from 10: Arrays */

ArrayInitializer: '{' ',' '}' {$$ = new ArrayExpression(0); }
| '{' oVariableInitializers  '}' {$$ = new ArrayExpression($2->first);};

oComma: | ',' ;
oVariableInitializers: {$$ = new ExprList(); }
                     | VariableInitializers oComma {$$ = $1;};

VariableInitializers: VariableInitializer {$$ = new ExprList($1); }
| VariableInitializers ',' VariableInitializer {$$=$1; $1->add($3); };


/****************** Statement ***********************/


ReferenceType: ClassOrInterfaceType | ArrayType;

ClassOrInterfaceType: Name {$$ = Type::NewClass($1->toIdent()); };
ClassType:     ClassOrInterfaceType;
InterfaceType: ClassOrInterfaceType;

ArrayType: PrimitiveType '[' ']' {$$ = Type::NewArray($1); }
|          Name '[' ']' { $$ = Type::NewArray(Type::NewClass($1->toIdent())); }
|          ArrayType '[' ']' {$$ = Type::NewArray($1); };

Type:      PrimitiveType | ReferenceType ;

Block:       '{' oBlockStatements '}' {$$ = new CompoundStatement($2); };

oBlockStatements: {$$ = 0;} 
                | BlockStatements {$$ = $1->first; };

BlockStatements:  BlockStatement {$$ = new StmtList($1); }
| BlockStatements BlockStatement {$$ = $1; $$->add($2); };

BlockStatement: LocalVariableDeclarationStatement
|               Statement ;

LocalVariableDeclarationStatement: LocalVariableDeclaration ';' ;

LocalVariableDeclaration:
   Type VariableDeclarators {
     $$ = new DeclarationStatement(0,new TypeExpression($1),
                 new ExpressionStatement($2->first)); };

Statement:   StatementWithoutTrailingSubstatement
|            LabeledStatement
|            IfThenStatement
|            IfThenElseStatement
|            WhileStatement
|            ForStatement ;

StatementNoShortIf:  StatementWithoutTrailingSubstatement
|                    LabeledStatementNoShortIf
|                    IfThenElseStatementNoShortIf
|                    WhileStatementNoShortIf
|                    ForStatementNoShortIf ;

StatementWithoutTrailingSubstatement
:            Block
|            EmptyStatement
|            ExpressionStatement
|            SwitchStatement
|            DoStatement
|            BreakStatement
|            ContinueStatement
|            ReturnStatement
|            SynchronizedStatement
|            ThrowStatement
|            TryStatement ;

EmptyStatement: ';' {$$ = new EmptyStatement(); };

LabeledStatement: ident ':' Statement {$$ = $3; $$->addLabel($1); };

LabeledStatementNoShortIf:
  ident ':' StatementNoShortIf {$$ = $3; $$->addLabel($1);};

ExpressionStatement:
  StatementExpression ';' {$$ = new ExpressionStatement($1); };

StatementExpression:  Assignment
|                     PreIncDec
|                     PostIncDec
|                     MethodInvocation
|                     NewClassInstance ;

IfThenStatement:
  _if_ '(' Expression ')' Statement {$$=new IfStatement($3,$5,0);};
IfThenElseStatement:
  _if_ '(' Expression ')' StatementNoShortIf _else_ Statement 
                           {$$=new IfStatement($3,$5,$7);};
IfThenElseStatementNoShortIf:
  _if_ '(' Expression ')' StatementNoShortIf _else_ StatementNoShortIf 
                           {$$=new IfStatement($3,$5,$7);};

SwitchStatement:
  _switch_ '(' Expression ')' SwitchBlock 
    {$$ = new SwitchStatement($3,$5)};

SwitchBlock:
  '{' SwitchBlockStatementGroups 
                 oSwitchLabels '}'  {$$=new CompoundStatement($2->first);}
| '{' oSwitchLabels '}'             {$$=new CompoundStatement(0);};

oSwitchLabels: /* e */ | SwitchLabels {};

SwitchBlockStatementGroups:  
  SwitchBlockStatementGroup {$$ = $1;}
| SwitchBlockStatementGroups 
  SwitchBlockStatementGroup {$$=$1; $$->glueList($1); };

SwitchBlockStatementGroup:  
  SwitchLabels BlockStatements {$$=$1; $$->glueList($1); };

SwitchLabels: SwitchLabel {$$ = new StmtList($1); }
|             SwitchLabels SwitchLabel {$$=$1; $$->add($2);};

SwitchLabel: _case_ ConstantExpression ':' {$$ = new CaseStatement($2); }
|            _default_ ':'                 {$$ = new CaseStatement(0); };

WhileStatement:  
  _while_ '(' Expression ')' Statement {$$ = new WhileStatement($3,$5);};

WhileStatementNoShortIf:  _while_ '(' Expression ')' StatementNoShortIf 
                                       {$$ = new WhileStatement($3,$5);};

DoStatement:  _do_ Statement _while_ '(' Expression ')' ';' 
                                       {$$ = new DoStatement($2,$5);};

ForStatement: _for_ '(' oForInit ';' oForExpression ';' oForUpdate ')'
  Statement                             {$$ = new ForStatement($3,$5,$7,$9); };

ForStatementNoShortIf:
 _for_ '(' oForInit ';' oForExpression ';' oForUpdate ')'
   StatementNoShortIf                   {$$ = new ForStatement($3,$5,$7,$9); };

oForInit:       {$$ = 0;} | ForInit ;
oForUpdate:     {$$ = 0;} | ForUpdate ;
oForExpression: {$$ = 0;} | Expression ;

ForInit:    StatementExpressionList  {$$ = new ExpressionStatement($1); }
|           LocalVariableDeclaration {$$ = $1;};

ForUpdate:  StatementExpressionList ;

StatementExpressionList: StatementExpression {$$ = $1; }
| StatementExpressionList ',' StatementExpression 
                                         {$$ = new CommaExpression($1, $3); };

oIdent: /* e */ {$$ = Identifier::nullstr} | ident {$$ = $1;};

BreakStatement:  _break_ oIdent ';'      {$$ = new BreakStatement($2); };

ContinueStatement: _continue_ oIdent ';' {$$ = new ContinueStatement($2); };

ReturnStatement:   _return_ ';'          {$$ = new ReturnStatement(0); }
               | _return_ Expression ';' {$$ = new ReturnStatement($2); };

ThrowStatement:    _throw_ Expression ';' {$$ = new ThrowStatement($2); };

SynchronizedStatement: _synchronized_ '(' Expression ')' Block 
  {$$ = new SynchronizedStatement($3, $5); }; 

TryStatement:  _try_ Block Catches {$$ = $2;} // !! not implemented yet
|              _try_ Block oCatches Finally {$$ = $2; };

oCatches: /* e */ | Catches ;

Catches:   CatchClause
|          Catches CatchClause ;

CatchClause:  _catch_ '(' FormalParameter ')' Block ;

Finally:     _finally_ Block ;


/************************* Expression ****************************/

Expression: AssignExpression;

Primary:    NoNewArray | ArrayCreation ;

NoNewArray:  Literal
|           _this_
|           '(' Expression ')' {$$ = new ExprExpression($2); }
|           NewClassInstance
|           FieldAccess
|           MethodInvocation
|           ArrayAccess ;

NewClassInstance: 
  _new_ ClassType '(' oArgList ')' {$$ = new NewInstanceExpression($2, $4); };

oArgList: {$$ = 0;}
        | ArgList {$$ = $1->first; };
ArgList: Expression {$$ = new ExprList($1); }
       | ArgList ',' Expression {$$ = $1; $$->add($3); };

ArrayCreation: _new_ Name {env.arrayElem = $2;} DimExprs oDims
|              _new_ PrimitiveType {env.arrayElem = new TypeExpression($2);} DimExprs oDims;

DimExprs: DimExpr | DimExprs DimExpr ;
DimExpr: '[' Expression ']' {
  env.arrayElem = new ArrayGenerateExpression(env.arrayElem, $2); };

oDims: | Dims;

Dims: '[' ']' {env.arrayElem = new ArrayGenerateExpression(env.arrayElem, 0);}
|Dims '[' ']' {env.arrayElem = new ArrayGenerateExpression(env.arrayElem, 0);};

FieldAccess:  Primary '.' ident {$$ = new FieldExpression($1,$3); }
|             _super_ '.' ident {$$ = new FieldExpression($1,$3); };

MethodInvocation:  Primary '.' ident '(' oArgList ')'
  {$$ = new MethodExpression($1,$3,$5); }
|                  Name    '(' oArgList ')'
  {$$ = new MethodExpression($1,$3); }
|                 _super_ '.' ident '(' oArgList ')'
  {$$ = new MethodExpression($1,$3,$5); }
;

ArrayAccess:   Name       '[' Expression ']' 
                              {$$ = new ArrayAccessExpression($1,$3); }
|              NoNewArray '[' Expression ']'
                              {$$ = new ArrayAccessExpression($1,$3); };

Postfix:  Primary
|         Name
|         PostIncDec ;

PostIncDec: Postfix IncDec { $$ = new PostIncDecExpression($2,$1); };

Unary:  AddOp Unary {$$ = new NegPosExpression($1, $2); }
|       PreIncDec
|       UnaryNotPM ;

PreIncDec: IncDec Unary {$$ = new PreIncDecExpression($1,$2); };

UnaryNotPM: Postfix
|           NegNot Unary {$$ = new UnaryExpression($1, $2->type, $2); }
|           CastExpr;

SaveElem: {$$ = env.arrayElem; }

CastExpr:'(' PrimitiveType {env.arrayElem = new TypeExpression($2);} oDims ')' 
  SaveElem Unary {$$ = new CastExpression($6,$7); }
|        '(' Name '[' ']' 
              {env.arrayElem = new ArrayGenerateExpression($2,0);} oDims ')' 
  SaveElem UnaryNotPM {$$ = new CastExpression($8,$9); }    
|          '(' Expression ')' UnaryNotPM {$$ = new CastExpression($2,$4); };

MulExpr: Unary | MulExpr MulOp Unary 
  {$$ = new BinaryArithmeticExpression($2,$1,$3); };

AddExpr: MulExpr | AddExpr AddOp MulExpr
  {$$ = new BinaryArithmeticExpression($2,$1,$3); };

ShiftExpr: AddExpr | ShiftExpr ShiftOp AddExpr
  {$$ = new BinaryShiftExpression($2,$1,$3); };

RelExpr: ShiftExpr
| RelExpr RelOp ShiftExpr {$$ = new BinaryCompareExpression($2,$1,$3); }
| RelExpr _instanceof_ ReferenceType 
   {$$ = new InstanceOfExpression($1, new TypeExpression($3) ); };

EqualExpr: RelExpr
| EqualExpr EqualOp RelExpr {$$ = new BinaryEqualityExpression($2,$1,$3); };

AndExpr:   EqualExpr
| AndExpr '&' EqualExpr {$$ = new BinaryBitExpression(BITAND,$1,$3);};

XorExpr:   AndExpr
| XorExpr '^' AndExpr {$$ = new BinaryBitExpression(BITXOR,$1,$3);};

OrExpr:    XorExpr
| OrExpr '|' XorExpr {$$ = new BinaryBitExpression(BITOR,$1,$3);};

AndAlso:   OrExpr
| AndAlso _andand_ OrExpr {$$ = new BinaryLogicalExpression(AND,$1,$3);};

OrElse:    AndAlso
| OrElse _oror_ AndAlso {$$ = new BinaryLogicalExpression(OR,$1,$3);};

CondExpr:   OrElse | OrElse '?' Expression ':' CondExpr 
  {$$ = new ConditionalExpression($1,$3,$5); };

LeftHandSide: Name | FieldAccess | ArrayAccess;

Assignment: LeftHandSide AssOp AssignExpression
  {$$ = new BinaryAssignExpression($2,$1,$3); };

AssignExpression:  Assignment | CondExpr;
ConstantExpression: Expression; // !! Check constness

%%

#include <stdio.h>
/*
void describe() {
  int i,d;
  static char* a[] = {"Default %s\n","[%s]","%s "};
  for(i = 1; i < sizeof(yytranslate)/sizeof(yytranslate[0]); ++i) {
    int yychar = YYTRANSLATE(i);
    int yyn = yypact[yystate] + yychar;
    if(yychar < 3) continue;
    if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar)
       {d = 0;}
    else {
      yyn = yytable[yyn];
      if(yyn == 0 || yyn == YYFLAG) continue;

      if( yyn < 0 ) d = 1;
      else d = 2;

      printf(a[d],yytname[yychar]);
    }
  }
}
*/
#include "scanner.c"

#ifdef YYBISON
const char* TokenName(int c) { return yytname[YYTRANSLATE(c)]; }
#else
const char* TokenName(int c) { return "Use Bison. Token Name unaccessible in Yacc";}
#endif

int main(int argc, char ** argv) {
  cout << "Main Begin" << endl;
#ifndef YYBISON
  printf("Please use bison (GNU's version of yacc)\n");
  printf("Please use bison (GNU's version of yacc)\n");
#else
  extern int yydebug;
#endif
  yydebug = argc == 2;
#ifdef YYBISON
  if (argc == 3) {
    int c; int curno = 0;
    printf("1:");
    while(c = yylex()) {
      if (curno != lineno) {printf("\n%d:",lineno); curno = lineno;}
      printf(" %s", TokenName(c));
    }
    printf("\n");
    return 0;
  }
#endif
  cout << "Before yyparse() " << endl;
  if(yyparse() == 0) printf("No Errors\n");
  cout << "----------- " << QuickNew::Avail() << endl;
  cout << env.pkg;
  QuickNew::finalize();
  cout << "After finalize" << endl;
}

int yyerror(char *s) {
  printf("Line %d: Unexpected token %s\n",lineno, TokenName(yychar));
  printf(s);
/*  printf("Possible alternative(s) is(are):");
  describe(); */
  printf("\n");
  exit(1);
  return 0;
}
