www.pudn.com > subpas.rar > parse.y


/****************************************************/ 
/* File: parse.Y                                    */ 
/* The Sub_Pascal  Yacc/Bison specification file    */ 
/* FGQ                                              */ 
/****************************************************/ 
%{ 
#define YYPARSER /* distinguishes Yacc output from other code files */ 
#include "globals.h" 
#include "util.h" 
#include "scan.h" 
#include "parse.h" 
 
static ArrayAttr * savedArray; 
static char * savedName; /* for use in assignments */ 
static char * savedProName; 
static char * savedMainName; 
static int savedLow; 
static int savedHigh; 
static int savedType; 
static int savedLineno; 
static TreeNode * savedTree; /* stores syntax tree for later return */ 
 
%} 
 
%token AND ARRAY BOOLEAN DO ELSE END MYFALSE FUNCTION IF  
%token INTEGER MYBEGIN NOT OF OR PROCEDURE PROGRAM REAL THEN MYTRUE VAR WHILE 
%token ID NUM REALNUM 
%token ASSIGNOP DOT SEMI COLON COMMA LSP RSP LP RP EQ NE LT LE GT GE PLUS MINUS TIMES OVER DIV MOD 
 
%union { TreeNode * ptree; 
         DataType dtype;  
         TokenType tt; 
       } 
        
%type  program  identifier_list declarations declaration subprogram_declarations subprogram_declaration  
              subprogram_head arguments parameter_list compound_statement optional_statements statement_list statement  
              variable procedure_statement expression_list expression simple_expression term factor id 
%type  type standard_type 
%type     relop addop mulop sign 
 
%left OR     
%left AND  
%left PLUS MINUS 
%left DIV MOD 
%left TIMES OVER 
 
%include { 
  void yyerror(const char * message); 
  TreeNode * parse(void); 
} 
 
%% /* Grammar for sub_pascal */ 
 
program : PROGRAM ID  {savedMainName = copyString(tokenString);} 
		  LP identifier_list RP SEMI 
          declarations 
          subprogram_declarations 
          compound_statement 
            { 
              $$ = newProNode(MainP); 
              $$->child[1] = $8; 
              $$->sibling = $9; 
              $$->child[2] = $10; 
              $$->name = savedMainName; 
              savedTree = $$; 
            }  
          ;  
           
identifier_list : ID { $$ = newExpNode(IdK); 
                       $$->name = copyString(tokenString);     
                     } 
                   | identifier_list COMMA id 
                      { TreeNode * t = $1; 
						$3 = newExpNode(IdK); 
						$3->name = savedName; 
		 
                        if (t != NULL){ 
                          while (t->sibling != NULL) 
                            t = t->sibling; 
                          t->sibling = $3; 
                          $$ = $1; } 
                        else $$ = $3; 
                      }                   
                   ; 
id :ID  { savedName = copyString(tokenString); 
		  $$=NULL;} 
   ; 
declarations : VAR  declaration SEMI{ $$=$2; } 
                |   {$$=NULL;} 
                ; 
declaration : declaration SEMI identifier_list COLON type 
                  { TreeNode * t = $1; 
                    if (t != NULL){ 
                      while (t->sibling != NULL) 
                        t = t->sibling; 
                      t->sibling = $3; 
                      $$ = $1; } 
                    else $$ = $3; 
                    t = $3; 
                    while(t != NULL){ 
                      t->type=$5; 
                      if($5 == Array) t->attr.arrayattr=savedArray; 
                      t=t->sibling; 
                    }                
                  } 
               | identifier_list COLON type 
                   { TreeNode * t = $1; 
                     while(t != NULL){ 
                        t->type=$3; 
                        if($3 == Array) t->attr.arrayattr=savedArray; 
                        t=t->sibling;  
                     } 
                     $$ = $1; 
                  } 
               ; 
type : standard_type  {$$=$1;} 
        | ARRAY LSP NUM {savedLow=atoi(tokenString);} 
              DOT DOT NUM  {savedHigh=atoi(tokenString);} 
              RSP OF  standard_type 
         { 
            $$=Array; 
            savedArray = (ArrayAttr *)malloc(sizeof(ArrayAttr)); 
            savedArray->type = $11; 
            savedArray->low = savedLow; 
            savedArray->high = savedHigh; 
            savedArray->count = savedHigh - savedLow + 1; 
         } 
        ; 
standard_type : INTEGER {$$=Integer;} 
                 | REAL {$$=Real;} 
                 | BOOLEAN {$$=Boolean;} 
                 ; 
subprogram_declarations : subprogram_declarations  subprogram_declaration SEMI  
                          {TreeNode* t=$1; 
                           if (t != NULL){ 
                              while (t->sibling != NULL) 
                                  t = t->sibling; 
                               t->sibling = $2; 
                               $$ = $1; } 
                              else $$ = $2;                
                          } 
                          |{  $$=NULL;  }  
                           ; 
subprogram_declaration : subprogram_head 
                          declarations 
                          compound_statement 
                          { 
                            $$ = newProNode(SubP); 
                            $$->name = savedProName; 
                            $$->type = savedType; 
                            $$->child[0] = $1; 
                            $$->child[1] = $2; 
                            $$->child[2] = $3;                         
                          } 
                        ;   
subprogram_head : FUNCTION  ID {savedProName=copyString(tokenString);} 
                     arguments  COLON  standard_type SEMI 
                     {  $$=$4; 
                        savedType=$6;                        
                      } 
                  | PROCEDURE  ID  {savedProName=copyString(tokenString);} 
                    arguments SEMI 
                    {   $$=$4; 
                        savedType=Void; 
                    } 
                  ; 
arguments : LP parameter_list RP  {$$ = $2; } 
            |  {$$ = NULL;} 
            ; 
parameter_list : identifier_list  COLON  type 
                  { TreeNode * t = $1; 
                    while(t != NULL){ 
                      t->type=$3; 
                      t->attr.paramkind=ByVal; 
                      t=t->sibling;  
                    } 
                    $$=$1; 
                  } 
                  | parameter_list  SEMI  identifier_list  COLON  type 
                  { TreeNode * t = $1; 
                    if (t != NULL){ 
                      while (t->sibling != NULL) 
                        t = t->sibling; 
                      t->sibling = $3; 
                      $$ = $1; } 
                    else $$ = $3; 
                    t = $3; 
                    while(t != NULL){ 
                      t->type=$5; 
                      t->attr.paramkind=ByVal; 
                      t=t->sibling; 
                    }                
                  } 
                  |VAR identifier_list  COLON  type 
                  { TreeNode * t = $2; 
                    while(t != NULL){ 
                      t->type=$4; 
                      t->attr.paramkind=ByRefer; 
                      t=t->sibling;  
                    } 
                    $$=$2; 
                  }                  
                  | parameter_list  SEMI VAR identifier_list  COLON  type 
                  { TreeNode * t = $1; 
                    if (t != NULL){ 
                      while (t->sibling != NULL) 
                        t = t->sibling; 
                      t->sibling = $4; 
                      $$ = $1; } 
                    else $$ = $4; 
                    t = $4; 
                    while(t != NULL){ 
                      t->type=$6; 
                      t->attr.paramkind=ByRefer; 
                      t=t->sibling; 
                    }                
                  }                  
                  |  {$$ = NULL;} 
                  ; 
compound_statement : MYBEGIN 
                     optional_statements 
                     END 
                     {$$=$2;} 
                    ;  
optional_statements : statement_list SEMI {$$=$1;} 
					   |statement_list {$$=$1;} 	  
                       | {$$=NULL;} 
                       ; 
statement_list : statement{$$=$1;} 
                  | statement_list  SEMI  statement 
                  { TreeNode * t = $1; 
                    if (t != NULL){ 
                      while (t->sibling != NULL) 
                        t = t->sibling; 
                      t->sibling = $3; 
                      $$ = $1; } 
                    else $$ = $3; 
                  } 
                  ; 
statement : variable  ASSIGNOP {savedLineno = lineno;} expression 
              {$$ = newStmtNode(AssignK); 
               $$->child[0]=$1; 
               $$->child[1]=$4; 
               $$->lineno = savedLineno; 
              } 
             | procedure_statement 
              {$$ = $1;} 
             | compound_statement {$$ = $1;} 
             | IF  expression  THEN  statement  ELSE  statement 
              {$$ = newStmtNode(IfK); 
               $$->child[0] = $2; 
               $$->child[1] = $4; 
               $$->child[2] = $6; 
              } 
             | WHILE  expression  DO  statement 
              {$$ = newStmtNode(WhileK); 
               $$->child[0]=$2; 
               $$->child[1]=$4;  
              } 
             ; 
variable : ID {$$=newExpNode(IdK); 
               $$->name=copyString(tokenString); 
              } 
            | ID  {savedName=copyString(tokenString);} 
              LSP expression RSP  
             {$$=newExpNode(IdK); 
              $$->name=savedName; 
              $$->type=Array; 
              $$->child[0]=$4; 
             } 
            ; 
procedure_statement : ID{$$ = newStmtNode(CallK); 
                         $$->name=copyString(tokenString); 
                        } 
                       | ID   {pushName(copyString(tokenString));} 
                         LP  expression_list  RP 
                        {$$ = newStmtNode(CallK); 
                         $$->name=popName(); 
                         $$->child[0] = $4; 
                        } 
                       ; 
expression_list : expression {$$ = $1;} 
				| expression_list  COMMA  expression 
                  { TreeNode * t = $1; 
                    if (t != NULL){ 
                      while (t->sibling != NULL) 
                        t = t->sibling; 
                      t->sibling = $3; 
                      $$ = $1; } 
                    else $$ = $3; 
                  }  
                 | {$$=NULL;}               
               ; 
expression :	simple_expression {$$ = $1;} 
				| simple_expression  relop  simple_expression 
					{$$=newExpNode(OpK); 
					$$->child[0]=$1; 
					$$->child[1]=$3; 
					$$->attr.op=$2; 
				} 
				; 
simple_expression : term {$$=$1;} 
                   | simple_expression  addop  term 
                    {$$=newExpNode(OpK); 
                     $$->child[0]=$1; 
                     $$->child[1]=$3; 
                     $$->attr.op=$2; 
                    } 
                   ; 
term : factor {$$=$1;} 
		| sign  factor 
		{$$=newExpNode(SignK); 
		 $$->child[0]=$2; 
		 $$->attr.op=$1; 
		} 
        | term  mulop  factor  
        {$$=newExpNode(OpK); 
         $$->child[0]=$1; 
         $$->child[1]=$3; 
         $$->attr.op=$2; 
        } 
		 ;          
factor : ID {$$=newExpNode(IdK); 
             $$->name=copyString(tokenString); 
            } 
         | ID {pushName(copyString(tokenString));} 
           LP  expression_list  RP 
            {$$=newStmtNode(CallK); 
             $$->name=popName(); 
             $$->child[0]=$4;  
            } 
         | ID {pushName(copyString(tokenString));} 
           LSP  expression  RSP 
            {$$=newExpNode(IdK); 
             $$->type = Array;  
             $$->name=popName(); 
             $$->child[0]=$4;    
            } 
         | NUM  
          {$$=newExpNode(NumK); 
           $$->type = Integer; 
           $$->attr.intval=atoi(tokenString); 
          } 
         | REALNUM 
          {$$=newExpNode(RealNumK); 
           $$->type = Real; 
           $$->attr.realval=atof(tokenString); 
          } 
         | MYTRUE {$$=newExpNode(BoolK); 
				   $$->type = Boolean;	 
				   $$->attr.intval=1;} 
         | MYFALSE{$$=newExpNode(BoolK); 
				   $$->type = Boolean;	 
				   $$->attr.intval=0;} 
         | LP  expression  RP  {$$=$2;} 
         | NOT   factor 
		 {$$=newExpNode(OpK); 
		  $$->child[0]=$2; 
		  $$->attr.op=NOT; 
		 } 
		 ; 
relop :  EQ  {$$=EQ;} 
        |NE  {$$=NE;} 
        |LT  {$$=LT;} 
        |LE  {$$=LE;} 
        |GT  {$$=GT;} 
        |GE  {$$=GE;} 
        ; 
addop :  PLUS   {$$=PLUS;} 
        |MINUS  {$$=MINUS;} 
        |OR		{$$=OR;} 
        ; 
mulop : TIMES  {$$=TIMES;} 
        |OVER  {$$=OVER;} 
        |DIV   {$$=DIV;} 
        |MOD   {$$=MOD;} 
        |AND   {$$=AND;}	 
        ;  
sign :  PLUS    {$$=PLUS;} 
        |MINUS  {$$=MINUS;}                                                                                
        ;  
%% 
 
void yyerror(const char * message) 
{ printf("error:(line %d) %s. (Current token:%s)\n",lineno,message,tokenString); 
  Error = TRUE; 
} 
 
/* yylex calls getToken to make Yacc/Bison output 
 * compatible with ealier versions of the TINY scanner 
 */ 
#ifdef YYPROTOTYPE 
int YYCDECL yygettoken(void) 
#else 
int YYCDECL yygettoken() 
#endif 
{ 
	return yylex(); 
} 
 
static TokenType yylex(void) 
{ return getToken(); } 
 
TreeNode * parse(void) 
{ yyparse(); 
  return savedTree; 
}