📄 parse_yy.y
字号:
/****************************************************/
/* File: parse.y */
/* The CMINUS Yacc specification file */
/****************************************************/
%{
#define YYPARSER /* distinguishes Yacc output from other code files */
#include "globals.h"
#include "util.h"
#include "scan.h"
#include "scan_lex.h"
#include "parse.h"
static char * savedFunName; /* for use in assignments */
static char * savedIdName;
static int savedLineNo; /* ditto */
static TreeNode * savedTree; /* stores syntax tree for later return */
%}
%token ENDFILE ERROR
%token IF,ELSE,RETURN,WHILE,INT,VOID
%token ID NUM
%token PLUS,MINUS,TIMES,OVER,LT,LTEQ,GT,GTEQ,EQ,NOEQ,ASSIGN,SEMI,COMMA,LPAREN,RPAREN,LBRA,RBRA,LBRACE,RBRACE
%union { TreeNode * ptree;
TokenType type;
}
%left COMMA
%right ASSIGN
%left EQ NOEQ
%left LT LTEQ GT GTEQ
%left PLUS MINUS
%left TIMES OVER
%left LPAREN,RPAREN,LBRA,RBRA,LBRACE,RBRACE
%right ELSE
%include {
void yyerror(const char * message);
TreeNode * parse(void);
}
%% /* Grammar for CMINUS */
program : dec_list
{ savedTree = $1;}
;
dec_list : dec_list dec
{ TreeNode * t = $1;
if (t != NULL)
{ while (t->sibling != NULL)
t = t->sibling;
t->sibling = $2;
$$ = $1; }
else $$ = $2;
}
| dec
{ $$ = $1; }
;
dec : var_dec { $$ = $1; }
| fun_dec { $$ = $1; }
| fun_def { $$ = $1; }
;
id : ID { savedIdName = copyString(tokenString); }
;
fid : { savedFunName = savedIdName; }
;
var_dec : type_spec id_list SEMI
{ if($1 == Void)
;
// err
else
{
$$ = newDecNode(VarK);
$$ -> type = $1;
$$ -> child[0] = $2;
}
}
;
id_list : id_list COMMA var
{
TreeNode * t = $1;
if (t != NULL)
{ while (t->sibling != NULL)
t = t->sibling;
t->sibling = $3;
$$ = $1; }
else $$ = $3;
} // i,str[5],j
| var { $$ = $1; }
| id_list COMMA id ASSIGN simple_exp
{
TreeNode * new_node = newExpNode(AssignK);
TreeNode * t = $1;
if (t != NULL)
{ while (t->sibling != NULL)
t = t->sibling;
t->sibling = new_node;
$$ = $1; }
else $$ = new_node;
}
| id ASSIGN simple_exp
{
$$ = newExpNode(AssignK);
$$ -> child[0] = newExpNode(IdK);
$$ -> child[0] -> attr.name = savedIdName;
$$ -> child[1] = $3;
}
;
type_spec : INT { $$ = Integer; }
| VOID { $$ = Void; }
;
fun_def : type_spec id fid LPAREN params RPAREN comp_stmt
{ $$ = newDecNode(FunK);
$$ -> attr.name = savedFunName;
$$ -> type = $1;
$$ -> child[0] = $5;
$$ -> child[1] = $7;
}
| id fid LPAREN params RPAREN comp_stmt
{ $$ = newDecNode(FunK);
$$ -> attr.name = savedFunName;
$$ -> type = Void;
$$ -> child[0] = $4;
$$ -> child[1] = $6;
}
;
fun_dec : type_spec id fid LPAREN params RPAREN SEMI
{ $$ = newDecNode(FunK);
$$ -> attr.name = savedFunName;
$$ -> type = $1;
$$ -> child[0] = $5;
$$ -> child[1] = NULL;
}
| id fid LPAREN params RPAREN SEMI
{ $$ = newDecNode(FunK);
$$ -> attr.name = savedFunName;
$$ -> type = Void;
$$ -> child[0] = $4;
$$ -> child[1] = NULL;
}
;
params : param_list
{ $$ = $1; }
|
{ $$ = NULL; }
;
param_list : param_list COMMA param
{ TreeNode * t = $1;
if (t != NULL)
{ while (t->sibling != NULL)
t = t->sibling;
t->sibling = $3;
$$ = $1; }
else $$ = $3;
}
| param
{ $$ = $1; }
;
param : type_spec
{ $$ = newParamNode(VarK);
$$ -> type = $1;
}
| type_spec id
{ $$ = newParamNode(VarK);
$$ -> type = $1;
$$ -> attr.name = savedIdName;
}
| type_spec id LBRA RBRA
{ $$ = newParamNode(ArrayK);
$$ -> type = $1;
$$ -> attr.name = savedIdName;
}
| type_spec id LBRA simple_exp RBRA
{ $$ = newParamNode(ArrayK);
$$ -> type = $1;
$$ -> attr.name = savedIdName;
$$ -> child[0] = $4;
}
;
comp_stmt : LBRACE local_dec stmt_list RBRACE
{ $$ = newStmtNode(CompoundK);
$$ -> child[0] = $2;
$$ -> child[1] = $3;
}
;
local_dec : local_dec var_dec
{ TreeNode * t = $1;
if (t != NULL)
{ while (t->sibling != NULL)
t = t->sibling;
t->sibling = $2;
$$ = $1; }
else $$ = $2;
}
|
{ $$ = NULL; }
;
stmt_list : stmt_list stmt
{ TreeNode * t = $1;
if (t != NULL)
{ while (t->sibling != NULL)
t = t->sibling;
t->sibling = $2;
$$ = $1; }
else $$ = $2;
}
|
{ $$ = NULL; }
;
stmt : exp_stmt { $$ = $1; }
| sele_stmt { $$ = $1; }
| iter_stmt { $$ = $1; }
| return_stmt { $$ = $1; }
| comp_stmt { $$ = $1; }
;
exp_stmt : exp SEMI
{ $$ = $1; }
| SEMI
{ $$ = NULL; }
;
sele_stmt : IF LPAREN exp RPAREN stmt %prec ELSE
{ $$ = newStmtNode(SelectionK);
$$ -> child[0] = $3;
$$ -> child[1] = $5;
}
| IF LPAREN exp RPAREN stmt ELSE stmt
{ $$ = newStmtNode(SelectionK);
$$ -> child[0] = $3;
$$ -> child[1] = $5;
$$ -> child[2] = $7;
}
;
iter_stmt : WHILE LPAREN exp RPAREN stmt
{ $$ = newStmtNode(IterationK);
$$ -> child[0] = $3;
$$ -> child[1] = $5;
}
;
return_stmt : RETURN SEMI
{ $$ = newStmtNode(ReturnK);
$$ -> child[0] = NULL;
}
| RETURN exp SEMI
{ $$ = newStmtNode(ReturnK);
$$ -> child[0] = $2;
}
;
exp : var ASSIGN exp
{ $$ = newExpNode(AssignK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
}
| simple_exp
{ $$ = $1; }
;
var : id
{ $$ = newExpNode(IdK);
$$ -> attr.name = savedIdName;
}
| id LBRA simple_exp RBRA
{ $$ = newExpNode(IdK);
$$ -> attr.name = savedIdName;
$$ -> child[0] = $3;
}
;
simple_exp : simple_exp LT simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = LT;
$$ -> type = Boolean;
}
|simple_exp LTEQ simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = LTEQ;
$$ -> type = Boolean;
}
|simple_exp GT simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = GT;
$$ -> type = Boolean;
}
|simple_exp GTEQ simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = GTEQ;
$$ -> type = Boolean;
}
|simple_exp EQ simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = EQ;
$$ -> type = Boolean;
}
|simple_exp NOEQ simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = NOEQ;
$$ -> type = Boolean;
}
|simple_exp PLUS simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = PLUS;
}
|simple_exp MINUS simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = MINUS;
}
|simple_exp TIMES simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = TIMES;
}
|simple_exp OVER simple_exp
{ $$ = newExpNode(OpK);
$$ -> child[0] = $1;
$$ -> child[1] = $3;
$$ -> attr.op = OVER;
}
| factor
{ $$ = $1; }
;
factor : LPAREN exp RPAREN
{ $$ = $2; }
| var
{ $$ = $1; }
| call
{ $$ = $1; }
| NUM
{ $$ = newExpNode(ConstK);
$$ -> type = Integer;
$$ -> attr.val.i = atoi(tokenString);
}
;
call : var LPAREN args RPAREN
{ $$ = newExpNode(CallK);
$$ -> attr.name = $1 -> attr.name;
$$ -> child[0] = $3;
}
;
arg_list : arg_list COMMA exp
{ TreeNode * t = $1;
if (t != NULL)
{ while (t->sibling != NULL)
t = t->sibling;
t->sibling = $3;
$$ = $1; }
else $$ = $3;
}
| exp
{ $$ = $1; }
;
args : arg_list
{ $$ = $1; }
|
{ $$ = NULL; }
;
%%
void yyerror(const char * message)
{ fprintf(listing,"Syntax error at line %d: %s\n",lineno,message);
fprintf(listing,"Current token: ");
printToken(yychar,tokenString);
Error = TRUE;
}
/* yylex calls getToken to make Yacc output
* compatible with ealier versions of the CMINUS 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -