/**************************************************    
 * This is a prettyprinting parser implementation *    
 * file generated by pretzel. (It's Bison code!)  *    
 *                                                *    
 *************************************************/    

%{                                                     

  /* this is needed for the yyprint function below */  
#include<stdio.h>                                      

  /* include the attribute definitions */              
#include"attr.h"                                     

  /* include the output definitions */                 
#include"output.h"                                   

  /* enable parser debugging */                        
#define YYDEBUG 1                                      

  /* redefine the semantic value */                    
#define YYSTYPE Attribute*                             

  /* enable calls of YYPRINT */                        
#define YYPRINT(file, type, value) yyprint (file, type, value)

  /* this is the prototype for yyprint */              
static void                                            
yyprint(FILE *file, int type, YYSTYPE value);          

  /* make sure that our local copy of yylex is         
   * declared with name `yylex' and as a static        
   * function. This should trick the parser into       
   * calling the scanner object stored in              
   * `static_scanner' (see below). */                  

  /* undefine yylex to make sure it isn't renamed      
   * by any command line option (e.g. -P). */          
#undef yylex                                           
  /* declare our local `dummy' yylex */                
static int yylex(YYSTYPE *rvalue);                     
  /* make sure any newer versions of Bison don't       
   * redeclare it differently */                       
#define YYLEX_DECL                                     
%}                                                     

/*************************************************     
 * various user definitions start here:          *     
 *************************************************/    

/* pretzel formatted grammar for simple PASCAL. */


%{
#define PSCAN_NAME pascan
#define PSCAN_INIT_NAME pascan_init
%}


%token SEMI
%token BEG
%token END
%token MATH           // token should only be used in math mode
%token SIMP           // other simple tokens
%token OPEN
%token CLOSE
%token ALPHA
%token OMEGA
%token UNTIL
%token INTRO
%token PROC
%token COLON
%token ELSE
%token COMMENT
%token ID_TYPE
%token RECORD
%token CASE


/*************************************************     
 * some pretzel definitions start here:          *     
 ************************************************/     

%{                                                     

  /* include own header only in default case: */       
#ifndef PPARSE_NAME                                    
#include "Ppparse.h"                                 
#endif                                                 

  /* this is a definition of the yyerror routine */    
yyerror (const char *s)                                
{  /* ignore error messages by BISON */                
   /* trick! use s do get around warning `s not used'. */
   if (1==0) fprintf(stderr, "%s", s);               
   return 0;                                           
}                                                      

  /* enable parser debugging */                        
#define YYDEBUG 1                                      

  /* variable to hold the parsed attribute */          
static Attribute *rest=create(null);                   

  /* include the scanner only in the default case: */  
#ifndef PSCAN_NAME                                     
#define PSCAN_NAME Ppscan                              
#include "Ppscan.h"                                  
#endif                                                 

  /* trick the yyparse function to use the scan member 
   * of the scanner class: */                          
static Pscan* static_scanner = NULL;                   
static int yylex( YYSTYPE *rvalue )                    
{                                                      
    return(static_scanner->scan(rvalue));              
}                                                      

%}                                                     

%pure_parser                                           


%%

stmt_list		: stmt		{rest=$$=$1;}
		| stmt_list stmt		{rest=$$=join($1,$2);}
;

stmt		: COMMENT		{  int i;
			rest=$$=
			join(
				join(
				create(cancel),
				(lookup() ? $1 :
								create(id))),
				create(null));
		delete i;
		}
		| proc		{rest=$$=$1;}
		| SEMI		{ 
			rest=$$=
			join(
				join(
				create(cancel),
				$1),
				create(force));
		
		}
		| BEG stmt_list END		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				join(
				join(
				$1,
				create(indent)),
				create(force)),
				$2),
				create(cancel)),
				create(outdent)),
				create(force)),
				$3);
		
		}
		| math		{rest=$$=$1;}
;

math		: MATH		{rest=$$=$1;}
		| math math		{rest=$$=join($1,$2);}
		| simp		{rest=$$=$1;}
		| COLON		{rest=$$=$1;}
		| OPEN decl_list CLOSE		{rest=$$=join($1,join($2,$3));}
		| RECORD stmt_list END		{rest=$$=join($1,join($2,$3));}
;

simp		: SIMP		{rest=$$=$1;}
		| identifier		{ 
			rest=$$=
			join(
				join(
				create("\\\\{"),
				$1),
				create("}"));
		
		}
;

identifier		: ID_TYPE		{rest=$$=$1;}
		| identifier ID_TYPE		{rest=$$=join($1,$2);}
;

decl_list		: math		{rest=$$=$1;}
		| INTRO math		{rest=$$=join($1,$2);}
		| decl_list SEMI math		{ 
			rest=$$=
			join(
				join(
				join(
				$1,
				$2),
				create(" ")),
				$3);
		
		}
		| decl_list SEMI INTRO math		{rest=$$=join($1,join($2,join($3,$4)));}
;

stmt		: ALPHA math OMEGA stmt		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(" ")),
				$3),
				create(indent)),
				create(force)),
				$4),
				create(outdent));
		
		}
		| ALPHA math OMEGA stmt ELSE stmt		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(" ")),
				$3),
				create(indent)),
				create(force)),
				$4),
				create(outdent)),
				create(force)),
				$5),
				create(indent)),
				create(force)),
				$6),
				create(outdent));
		
		}
		| CASE math OMEGA stmt_list END		{rest=$$=join($1,join($2,join($3,join($4,$5))));}
		| BEG stmt_list UNTIL math		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				$1,
				create(indent)),
				create(force)),
				$2),
				create(cancel)),
				create(outdent)),
				create(force)),
				$3),
				create(" ")),
				$4);
		
		}
;

proc		: proc INTRO math SEMI		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				$1,
				$2),
				$3),
				$4),
				create(force));
		
		}
		| PROC		{rest=$$=$1;}
;

stmt		: INTRO math SEMI		{ 
			rest=$$=
			join(
				join(
				join(
				$1,
				$2),
				$3),
				create(force));
		
		}
;

%%
/*************************************************     
 * additional pretzel code starts here:          *     
 *************************************************/    

#ifndef PPARSE_NAME                                    
#define PPARSE_NAME Ppparse                            
#endif                                                 

PPARSE_NAME::PPARSE_NAME()                             
{                                                      
}                                                      
PPARSE_NAME::~PPARSE_NAME()                            
{                                                      
    static_scanner = NULL;                             
}                                                      
int PPARSE_NAME::prettyprint(istream* is, ostream* os) 
{                                                      
    Latex_cweb_output ppoutput(*os);                   
    return(prettyprint(is, &ppoutput));                
}                                                      
int PPARSE_NAME::prettyprint(istream* is, Output* outp)
{                                                      
    int ret_val = 0;                                   
    PSCAN_NAME ppscanner(is);                          
    static_scanner = &ppscanner;                       
    ret_val=yyparse();                                 
    while (!(is->eof())) {                             
        char c;                                        
        is->get(c);                                    
    }                                                  
    rest->print(*outp);                                
    return(ret_val);                                   
}                                                      

void PPARSE_NAME::debug_on() { yydebug = 1; }          
void PPARSE_NAME::debug_off() { yydebug = 0; }         

  /* This is a routine to print the semantic value */
static void 
yyprint(FILE *file, int type, YYSTYPE value) {
  Latex_cweb_output os(cerr);
  value->print(os);
}
/*************************************************     
 * optional user defined C code follows here:    *     
 *************************************************/    

