add syntax
This commit is contained in:
328
src/cminus.y
Normal file
328
src/cminus.y
Normal file
@@ -0,0 +1,328 @@
|
||||
/****************************************************/
|
||||
/* 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
|
||||
|
||||
%}
|
||||
|
||||
%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;
|
||||
$$->type = IntegerArray;
|
||||
$$->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);
|
||||
$$->type = $1->type;
|
||||
$$->attr.name = savedName;
|
||||
};
|
||||
|
||||
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 = lineno;
|
||||
$$->child[0] = $1;
|
||||
$$->child[1] = $3;
|
||||
$$->type = Integer;
|
||||
} | additive_expression { $$ = $1; };
|
||||
|
||||
relop : LE {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->attr.op = LE;
|
||||
} | LT {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->attr.op = LT;
|
||||
} | GT {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->attr.op = GT;
|
||||
} | GE {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->attr.op = GE;
|
||||
} | EQ {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->attr.op = EQ;
|
||||
} | NE {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->attr.op = NE;
|
||||
};
|
||||
|
||||
additive_expression : additive_expression addop term {
|
||||
$$ = $2;
|
||||
$$->lineno = lineno;
|
||||
$$->child[0] = $1;
|
||||
$$->child[1] = $3;
|
||||
} | term { $$ = $1; };
|
||||
|
||||
addop : PLUS {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->attr.op = PLUS;
|
||||
} | MINUS {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->attr.op = MINUS;
|
||||
};
|
||||
|
||||
term : term mulop factor {
|
||||
$$ = $2;
|
||||
$$->lineno = lineno;
|
||||
$$->child[0] = $1;
|
||||
$$->child[1] = $3;
|
||||
} | factor { $$ = $1; };
|
||||
|
||||
mulop : TIMES {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->attr.op = TIMES;
|
||||
} | OVER {
|
||||
$$ = newExpNode(OpK);
|
||||
$$->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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user