Files
2025-02-Compiler/src/cminus.y
2025-12-05 02:09:12 +09:00

345 lines
7.7 KiB
Plaintext

/****************************************************/
/* File: tiny.y */
/* The TINY Yacc/Bison specification file */
/* Compiler Construction: Principles and Practice */
/* Kenneth C. Louden */
/****************************************************/
%{
#define YYPARSER /* distinguishes Yacc output from other code files */
#include "globals.h"
#include "util.h"
#include "scan.h"
#include "parse.h"
#define YYSTYPE TreeNode *
static char * savedName; /* for use in assignments */
static int savedNumber;
static int savedLineNo; /* ditto */
static TreeNode * savedTree; /* stores syntax tree for later return */
static int yylex(void); // added 11/2/11 to ensure no conflict with lex
int yyerror(char * message);
%}
%token IF ELSE WHILE RETURN INT VOID
%token EQ NE LT LE GT GE LPAREN RPAREN LBRACE LCURLY RBRACE RCURLY SEMI COMMA
%token ID NUM
%left PLUS MINUS
%left TIMES OVER
%right ASSIGN
%nonassoc THEN
%nonassoc ELSE
%token ERROR
%% /* Grammar for C-MINUS */
program : declaration_list
{savedTree = $1;};
declaration_list : declaration_list declaration {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL) {
t = t->sibling;
}
t->sibling = $2;
$$ = $1;
} else { $$ = $2; };
}
| declaration { $$ = $1; }
;
declaration : var_declaration {$$ = $1; } | func_declaration { $$ = $1; };
name_specifier : ID {
savedName = copyString(tokenString);
savedLineNo = lineno;
};
number_specifier : NUM {
savedNumber = atoi(tokenString);
savedLineNo = lineno;
};
var_declaration : type_specifier name_specifier SEMI {
$$ = newDeclNode(VarK);
$$->lineno = savedLineNo;
$$->attr.name = savedName;
$$->type = $1->type;
free($1);
} | type_specifier name_specifier LBRACE number_specifier RBRACE SEMI {
$$ = newDeclNode(ArrVarK);
$$->lineno = savedLineNo;
if ($1->type == Integer)
$$->type = IntegerArray;
else
$$->type = Void;
$$->attr.name = savedName;
free($1);
$$->child[0] = newExpNode(ConstK);
$$->child[0]->type = Integer;
$$->child[0]->attr.val = savedNumber;
};
type_specifier : INT {
$$ = newTypeNode(TypeNameK);
$$->type = Integer;
}
| VOID {
$$ = newTypeNode(TypeNameK);
$$->type = Void;
};
func_declaration : type_specifier name_specifier {
$$ = newDeclNode(FuncK);
$$->lineno = savedLineNo;
$$->attr.name = savedName;
$$->type = $1->type; /* 타입 바로 복사 */
} LPAREN params RPAREN compound_stmt {
$$ = $3;
$$->child[0] = $5; /* params */
$$->child[1] = $7; /* compound_stmt */
};
params : param_list { $$ = $1; } | VOID {
$$ = newDeclNode(NonArrParamK);
$$->type = Void;
};
param_list : param_list COMMA param {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL) {
t = t->sibling;
}
t->sibling = $3;
$$ = $1;
} else {
$$ = $3;
};
} | param {$$ = $1; };
param : type_specifier name_specifier {
$$ = newDeclNode(NonArrParamK);
$$->attr.name = savedName;
$$->type = $1->type;
} | type_specifier name_specifier LBRACE RBRACE {
$$ = newDeclNode(ArrParamK);
$$->attr.name = savedName;
if ($1->type == Integer)
$$->type = IntegerArray;
else
$$->type = Void;
};
compound_stmt : LCURLY local_declarations statement_list RCURLY {
$$ = newStmtNode(CompK);
$$->lineno = lineno;
$$->child[0] = $2;
$$->child[1] = $3;
};
local_declarations : local_declarations var_declaration {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL)
t = t->sibling;
t->sibling = $2;
$$ = $1;
} else $$ = $2;
} | { $$ = NULL; };
statement_list : statement_list statement {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL)
t = t->sibling;
t->sibling = $2;
$$ = $1;
} else $$ = $2;
} | { $$ = NULL; };
statement : expression_stmt { $$ = $1; }
| compound_stmt { $$ = $1; }
| selection_stmt { $$ = $1; }
| iteration_stmt { $$ = $1; }
| return_stmt { $$ = $1; }
;
expression_stmt : expression SEMI { $$ = $1; }
| SEMI { $$ = NULL; }
;
selection_stmt : IF LPAREN expression RPAREN statement %prec THEN {
$$ = newStmtNode(IfK);
$$->lineno = lineno;
$$->child[0] = $3;
$$->child[1] = $5;
} | IF LPAREN expression RPAREN statement ELSE statement {
$$ = newStmtNode(IfK);
$$->lineno = lineno;
$$->child[0] = $3;
$$->child[1] = $5;
$$->child[2] = $7;
};
iteration_stmt : WHILE LPAREN expression RPAREN statement {
$$ = newStmtNode(IterK);
$$->lineno = lineno;
$$->child[0] = $3;
$$->child[1] = $5;
};
return_stmt : RETURN SEMI {
$$ = newStmtNode(ReturnK);
$$->lineno = lineno;
} | RETURN expression SEMI {
$$ = newStmtNode(ReturnK);
$$->lineno = lineno;
$$->child[0] = $2;
};
expression : var ASSIGN expression {
$$ = newExpNode(AssignK);
$$->lineno = lineno;
$$->type = $3->type;
$$->child[0] = $1;
$$->child[1] = $3;
} | simple_expression { $$ = $1; };
var : name_specifier {
$$ = newExpNode(IdK);
$$->attr.name = savedName;
} | name_specifier {
$$ = newExpNode(ArrIdK);
$$->attr.name = savedName;
} LBRACE expression RBRACE {
$$ = $2;
$$->child[0] = $4;
};
simple_expression : additive_expression relop additive_expression {
$$ = $2;
$$->lineno = $2->lineno;
$$->child[0] = $1;
$$->child[1] = $3;
$$->type = Integer;
} | additive_expression { $$ = $1; };
relop : LE {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = LE;
} | LT {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = LT;
} | GT {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = GT;
} | GE {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = GE;
} | EQ {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = EQ;
} | NE {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = NE;
};
additive_expression : additive_expression addop term {
$$ = $2;
$$->lineno = $2->lineno;
$$->child[0] = $1;
$$->child[1] = $3;
} | term { $$ = $1; };
addop : PLUS {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = PLUS;
} | MINUS {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = MINUS;
};
term : term mulop factor {
$$ = $2;
$$->lineno = $2->lineno;
$$->child[0] = $1;
$$->child[1] = $3;
} | factor { $$ = $1; };
mulop : TIMES {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = TIMES;
} | OVER {
$$ = newExpNode(OpK);
$$->lineno = lineno;
$$->attr.op = OVER;
};
factor : LPAREN expression RPAREN { $$ = $2; }
| var { $$ = $1; }
| call { $$ = $1; }
| NUM {
$$ = newExpNode(ConstK);
$$->lineno = lineno;
$$->type = Integer;
$$->attr.val = atoi(tokenString);
}
;
call : name_specifier {
$$ = newExpNode(CallK);
$$->lineno = lineno;
$$->attr.name = savedName;
} LPAREN args RPAREN {
$$ = $2;
$$->child[0] = $4;
};
args : arg_list { $$ = $1; } | { $$ = NULL; } ;
arg_list : arg_list COMMA expression {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL)
t = t->sibling;
t->sibling = $3;
$$ = $1;
} else $$ = $3;
} | expression { $$ = $1; } ;
%%
int yyerror(char * message)
{ fprintf(listing,"Syntax error at line %d: %s\n",lineno,message);
fprintf(listing,"Current token: ");
printToken(yychar,tokenString);
Error = TRUE;
return 0;
}
/* yylex calls getToken to make Yacc/Bison output
* compatible with ealier versions of the TINY scanner
*/
static int yylex(void)
{ return getToken(); }
TreeNode * parse(void)
{ yyparse();
return savedTree;
}