tiger 抽象语法树生成

在语法分析基础上添加语义动作,生成tiger语言抽象语法树。

官网给出框架和构造函数代码,仅仅需要在tiger.y添加相应语义动作,实现比较容易。

文法:
文法稍作改变,增加了tydecs和fundecs来对应书中要求的nametylist和functionlist。由此产生了两个新shift/reduce conflict, 但均无害。

/**********************************************************
 * Author        : lh
 * Email         : [email protected]
 * Create time   : 2017-03-01 16:27
 * Last modified : 2017-03-02 09:51
 * Filename      : tiger.y
 * Description   : 
 * *******************************************************/

%{
#include 
#include "util.h"
#include "symbol.h" 
#include "errormsg.h"
#include "absyn.h"

#define YYDEBUG 1

int yylex(void); /* function prototype */

void yyerror(char *s)
{
    EM_error(EM_tokPos, "%s", s);
}

A_exp absyn_root;
%}


%union {
    int pos;
    int ival;
    string sval;
    A_exp exp;
    A_var var;
    A_expList expList;
    A_efieldList efieldList;
    A_decList decList;
    A_dec dec;
    A_ty ty;
    A_nametyList nametyList;
    A_fundecList fundecList;
    A_namety namety;
    A_fundec fundec;
    A_fieldList fieldList;
    A_field field;
}

%token  ID STRING
%token  INT

%token 
  COMMA COLON SEMICOLON LPAREN RPAREN LBRACK RBRACK 
  LBRACE RBRACE DOT 
  PLUS MINUS TIMES DIVIDE EQ NEQ LT LE GT GE
  AND OR ASSIGN
  ARRAY IF THEN ELSE WHILE FOR TO DO LET IN END OF 
  BREAK NIL
  FUNCTION VAR TYPE 

%left SEMICOLON
%right THEN ELSE DOT DO OF
%right ASSIGN
%left OR
%left AND
%nonassoc EQ NEQ LT LE GT GE
%left PLUS MINUS
%left TIMES DIVIDE
%left UMINUS


%type <exp> program exp funcall
%type  lvalue
%type  expseq paraseq
%type  asseq
%type  decs
%type  dec vardec
%type  tydecs
%type  fundecs
%type  tydec
%type  fundec
%type  ty
%type  tyfields tyfield

%start program

%%

program : exp    {absyn_root=$1;}

exp : lvalue            {$$ = A_VarExp(EM_tokPos, $1);}
	| lvalue ASSIGN exp {$$ = A_AssignExp(EM_tokPos, $1, $3);}
	| INT				{$$ = A_IntExp(EM_tokPos, $1);}	
	| STRING			{$$ = A_StringExp(EM_tokPos, $1);}
	| NIL				{$$ = A_NilExp(EM_tokPos);}

    | LPAREN RPAREN         {$$ = A_SeqExp(EM_tokPos, NULL);}
	| LPAREN expseq RPAREN	{$$ = A_SeqExp(EM_tokPos, $2);}

    | MINUS exp %prec UMINUS {$$ = A_OpExp(EM_tokPos, A_minusOp, A_IntExp(EM_tokPos, 0), $2);}
	| exp PLUS exp		{$$ = A_OpExp(EM_tokPos, A_plusOp, $1, $3);}
	| exp MINUS exp		{$$ = A_OpExp(EM_tokPos, A_minusOp, $1, $3);}
	| exp TIMES exp		{$$ = A_OpExp(EM_tokPos, A_timesOp, $1, $3);}
	| exp DIVIDE exp	{$$ = A_OpExp(EM_tokPos, A_divideOp, $1, $3);}

    | exp EQ exp    {$$ = A_OpExp(EM_tokPos, A_eqOp, $1, $3);}
	| exp NEQ exp	{$$ = A_OpExp(EM_tokPos, A_neqOp, $1, $3);}
	| exp LT exp	{$$ = A_OpExp(EM_tokPos, A_ltOp, $1, $3);}
	| exp LE exp	{$$ = A_OpExp(EM_tokPos, A_leOp, $1, $3);}
	| exp GT exp	{$$ = A_OpExp(EM_tokPos, A_gtOp, $1, $3);}
	| exp GE exp	{$$ = A_OpExp(EM_tokPos, A_geOp, $1, $3);}

    | exp AND exp   {$$ = A_IfExp(EM_tokPos, $1, $3, A_IntExp(EM_tokPos, 0));}
	| exp OR exp	{$$ = A_IfExp(EM_tokPos, $1, A_IntExp(EM_tokPos, 1), $3);}

    | funcall   {$$ = $1;}

    | ID LBRACK exp RBRACK OF exp   {$$ = A_ArrayExp(EM_tokPos, S_Symbol($1), $3, $6);}
	| ID LBRACE RBRACE				{$$ = A_RecordExp(EM_tokPos, S_Symbol($1), NULL);}
	| ID LBRACE asseq RBRACE		{$$ = A_RecordExp(EM_tokPos, S_Symbol($1), $3);}

    | IF exp THEN exp                   {$$ = A_IfExp(EM_tokPos, $2, $4, NULL);}
	| IF exp THEN exp ELSE exp			{$$ = A_IfExp(EM_tokPos, $2, $4, $6);}
	| WHILE exp DO exp					{$$ = A_WhileExp(EM_tokPos, $2, $4);}
	| FOR ID ASSIGN exp TO exp DO exp	{$$ = A_ForExp(EM_tokPos, S_Symbol($2), $4, $6, $8);}
	| BREAK								{$$ = A_BreakExp(EM_tokPos);}

    | LET decs IN END           {$$ = A_LetExp(EM_tokPos, $2, A_SeqExp(EM_tokPos, NULL));}
	| LET decs IN expseq END	{$$ = A_LetExp(EM_tokPos, $2, A_SeqExp(EM_tokPos, $4));}

    | LPAREN error RPAREN   {$$ = A_SeqExp(EM_tokPos, NULL);}
	| error SEMICOLON exp	{$$ = $3;}
    ;


lvalue  : ID                        {$$ = A_SimpleVar(EM_tokPos,S_Symbol($1));}
		| lvalue DOT ID				{$$ = A_FieldVar(EM_tokPos, $1, S_Symbol($3));}
		| lvalue LBRACK exp RBRACK	{$$ = A_SubscriptVar(EM_tokPos, $1, $3);}
		| ID LBRACK exp RBRACK		{$$ = A_SubscriptVar(EM_tokPos, A_SimpleVar(EM_tokPos, S_Symbol($1)), $3);}
        ;   


expseq  : exp                   {$$ = A_ExpList($1, NULL);}
		| exp SEMICOLON expseq	{$$ = A_ExpList($1, $3);}
        ;


funcall : ID LPAREN RPAREN          {$$ = A_CallExp(EM_tokPos, S_Symbol($1), NULL);}
		| ID LPAREN paraseq RPAREN	{$$ = A_CallExp(EM_tokPos, S_Symbol($1), $3);}
        ;

paraseq : exp               {$$ = A_ExpList($1, NULL);}
		| exp COMMA paraseq	{$$ = A_ExpList($1, $3);}
        ;

asseq   : ID EQ exp             {$$ = A_EfieldList(A_Efield(S_Symbol($1), $3), NULL);}
		| ID EQ exp COMMA asseq	{$$ = A_EfieldList(A_Efield(S_Symbol($1), $3), $5);}
        ;


decs    : dec decs  {$$ = A_DecList($1, $2);}
		|			{$$ = NULL;}
        ;

dec : tydecs    {$$ = A_TypeDec(EM_tokPos, $1);}
	| vardec	{$$ = $1;}
	| fundecs	{$$ = A_FunctionDec(EM_tokPos, $1);}
    ;

tydecs  : tydec         {$$ = A_NametyList($1, NULL);}
		| tydec tydecs	{$$ = A_NametyList($1, $2);}
        ;

tydec   : TYPE ID EQ ty {$$ = A_Namety(S_Symbol($2), $4);}
        ;

ty  : ID                        {$$ = A_NameTy(EM_tokPos, S_Symbol($1));}
	| LBRACE tyfields RBRACE	{$$ = A_RecordTy(EM_tokPos, $2);}
	| ARRAY OF ID				{$$ = A_ArrayTy(EM_tokPos, S_Symbol($3));}
    ; 

tyfields: tyfield   {$$ = $1;}
		|			{$$ = NULL;}
        ;

tyfield : ID COLON ID                   {$$ = A_FieldList(A_Field(EM_tokPos, S_Symbol($1), S_Symbol($3)), NULL);}
		| ID COLON ID COMMA tyfield		{$$ = A_FieldList(A_Field(EM_tokPos, S_Symbol($1), S_Symbol($3)), $5);}
        ;

vardec  : VAR ID ASSIGN exp             {$$ = A_VarDec(EM_tokPos, S_Symbol($2), NULL, $4);}
		| VAR ID COLON ID ASSIGN exp	{$$ = A_VarDec(EM_tokPos, S_Symbol($2), S_Symbol($4), $6);}
        ;

fundecs : fundec            {$$ = A_FundecList($1, NULL);}
		| fundec fundecs	{$$ = A_FundecList($1, $2);}
        ;

fundec  : FUNCTION ID LPAREN tyfields RPAREN EQ exp             {$$ = A_Fundec(EM_tokPos, S_Symbol($2), $4, NULL, $7);}
		| FUNCTION ID LPAREN tyfields RPAREN COLON ID EQ exp	{$$ = A_Fundec(EM_tokPos, S_Symbol($2), $4, S_Symbol($7), $9);}
        ;



你可能感兴趣的:(tiger,compiler)