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;
}