/**************************************************    
 * 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:          *     
 *************************************************/    


%token PREDICATE

%token CHUNK

%token SEMI
%token OPEN
%token CLOSE
%token DOTDOT
%token DOT
%token BECOMES
%token BLOCK
%token COMMA
%token ARROW
%token COLON

%token SKIP
%token ABORT
%token ARRAY
%token OF
%token DO
%token OD
%token IF
%token FI

%token SWAP

%token OPENBLOCK
%token CLOSEBLOCK

%token UNARY_OP
%token MINUS
%token BINARY_OP

%token ACCESS
%token TYPE
%token ID
%token NUMBER

/*************************************************     
 * 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;}
		| predicate stmt		{ 
			rest=$$=
			join(
				join(
				$1,
				create(force)),
				$2);
		
		}
		| predicate stmt predicate		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				$1,
				create(force)),
				$2),
				create(force)),
				$3);
		
		}
		| stmt predicate		{ 
			rest=$$=
			join(
				join(
				$1,
				create(force)),
				$2);
		
		}
		| stmt SEMI stmt_list		{ 
			rest=$$=
			join(
				join(
				join(
				$1,
				$2),
				create(force)),
				$3);
		
		}
		| predicate stmt SEMI stmt_list		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				$1,
				create(force)),
				$2),
				$3),
				create(force)),
				$4);
		
		}
;

predicate		: PREDICATE		{rest=$$=$1;}
		| PREDICATE predicate		{ 
			rest=$$=
			join(
				join(
				$1,
				create(force)),
				$2);
		
		}
;

stmt		: selection		{rest=$$=$1;}
		| repetition		{rest=$$=$1;}
		| block		{rest=$$=$1;}
		| SWAP simple_expr DOT simple_expr DOT simple_expr		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				$3),
				$4),
				$5),
				$6);
		
		}
		| SKIP		{rest=$$=$1;}
		| ABORT		{rest=$$=$1;}
		| CHUNK		{rest=$$=$1;}
		| assign		{rest=$$=$1;}
;

assign		: expr_list BECOMES expr_list		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(" ")),
				create(indent)),
				create(opt5)),
				create(outdent)),
				$3);
		
		}
;

expr_list		: expr		{rest=$$=$1;}
		| expr COMMA expr_list		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				$1,
				$2),
				create(" ")),
				create(opt9)),
				$3);
		
		}
;

simple_expr		: ID		{rest=$$=$1;}
		| NUMBER		{rest=$$=$1;}
		| OPEN expr CLOSE		{rest=$$=join($1,join($2,$3));}
;

expr		: simple_expr		{rest=$$=$1;}
		| ID DOT simple_expr		{rest=$$=join($1,join($2,$3));}
		| UNARY_OP simple_expr		{rest=$$=join($1,$2);}
		| expr binary_op expr		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(" ")),
				$3);
		
		}
;

binary_op		: BINARY_OP		{rest=$$=$1;}
		| MINUS		{rest=$$=$1;}
;

unary_op		: UNARY_OP		{rest=$$=$1;}
		| MINUS		{rest=$$=$1;}
;

repetition		: DO guarded_list OD		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(force)),
				$3);
		
		}
;

selection		: IF guarded_list FI		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(force)),
				$3);
		
		}
;

guarded_list		: guarded_stmt		{rest=$$=$1;}
		| guarded_stmt BLOCK guarded_list		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				$1,
				create(force)),
				$2),
				create(" ")),
				$3);
		
		}
;

guarded_stmt		: expr ARROW stmt_list		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(indent)),
				create(force)),
				$3),
				create(outdent));
		
		}
;

block		: OPENBLOCK decls stmt_list CLOSEBLOCK		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				join(
				join(
				join(
				$1,
				create(indent)),
				create(force)),
				$2),
				create(force)),
				$3),
				create(outdent)),
				create(force)),
				$4);
		
		}
;

decls		: decl		{rest=$$=$1;}
		| decl decls		{rest=$$=join($1,$2);}
;

decl		: ACCESS type_decls SEMI		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(" ")),
				$3),
				create(force));
		
		}
;

type_decls		: type_decl		{rest=$$=$1;}
		| type_decl COMMA type_decls		{ 
			rest=$$=
			join(
				join(
				join(
				$1,
				$2),
				create(" ")),
				$3);
		
		}
;

type_decl		: expr_list COLON type		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(" ")),
				$3);
		
		}
;

type		: TYPE		{rest=$$=$1;}
		| ARRAY bounds OF TYPE		{ 
			rest=$$=
			join(
				join(
				join(
				join(
				join(
				join(
				$1,
				create(" ")),
				$2),
				create(" ")),
				$3),
				create(" ")),
				$4);
		
		}
;

bounds		: OPEN expr DOTDOT expr CLOSE		{rest=$$=join($1,join($2,join($3,join($4,$5))));}
;

%%
/*************************************************     
 * 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:    *     
 *************************************************/    

