语法树

语法树能使程序具有层次性,使要翻译的程序更具有语义特点。比如,对于同一段程序中不同地方都出现的代码int a;在语法树中可以体现出其不同的状态和性质。

设计语法树中的结点的数据结构如下:

typedef struct ParseNode     //语法树结点数据结构

{

       int           NodeID;                              //结点序号

       char lexval[20];                           //用来存储结点信息

       int           val;                              //用来存储结点值

       int           NodeType;                           //结点类型

       PTOKENLIST                     NodeTokenList;//指向结点的符号表项地址

       struct ParseNode*  children;  //孩子指针

       struct ParseNode*  sublings;  //兄弟指针

}PARSENODE,*PPARSENODE;

该语法树拥有的操作有:

void printparsetree(PPARSENODE);            //打印语法树

PPARSENODE makeleaf(int, int, char*);   //创建叶结点

PPARSENODE makenode(PPARSENODE, PPARSENODE, int, int, char*);  //创建枝结点

void printparsenode(PPARSENODE);        //打印结点

void printnodechildren(PPARSENODE);     //打印孩子结点的序号

2、翻译模式的设计

根据语法树的结构,设计上下无关文法如下:

lines :      lines cstmt     { printparsetree($2); displaytokenlist(head); }

              |

              ;

cstmt      :      ID '(' ')' '{' sstmts '}'     { $$=$5; $1->NodeTokenList=storetoken($1->lexval,$1->val);  }

              ;

sstmts     :      sstmts     sstmt      { $$=makenode($1,$2,COMPOUND,0,"compound"); }

              |      sstmt                    { $$=$1; }

              ;

sstmt      :      type idlist ';'    { addtype($2,$1->NodeType);       $$=makenode($1,$2,VAR,0,"var");       }

              |      IF '(' expr ')' expr ';'      { $$=makenode($3,$5,IF,0,"if");   }

              ;

type :      INT                      { $$=makeleaf(INT,0,"integer");   }

              ;

idlist :      idlist',' ID       { $1->sublings=makeleaf(ID,$3->val,$3->lexval);       $1->sublings->NodeTokenList=storetoken($3->lexval,$3->val);$$=$1;     }

              |      ID                        { $$=makeleaf(ID,$1->val,$1->lexval); $$->NodeTokenList=storetoken($$->lexval,$$->val);  }

              ;

               

expr :      expr DUPEQU expr{ $$=makenode($1,$3,EXPR,0,"==");  }

              |      expr EQU expr       { flushtokenvalue($1,$3->val);       $$=makenode($1,$3,EXPR,0,"="); }

              |      expr ADD expr       { $$=makenode($1,$3,EXPR,$1->val+$3->val,"+");  }

              |      expr SUB expr       { $$=makenode($1,$3,EXPR,$1->val-$3->val,"-");  }

              |      expr MUL expr       { $$=makenode($1,$3,EXPR,$1->val*$3->val,"*");  }

              |      expr DIV expr { $$=makenode($1,$3,EXPR,$1->val/$3->val,"/");  }

              |      '(' expr ')'       { $$=makenode($2,NULL,EXPR,$2->val,"-");  }

              |      SUB expr %prec UMINUS       { $$=makenode($2,NULL,EXPR,0-$2->val,$2->lexval);     }

              |      NUMBER                     { $$=makeleaf(NUMBER,$1->val,$1->lexval);    }

              |      ID                        { $$=makeleaf(ID,$1->val,$1->lexval); $$->NodeTokenList=storetoken($$->lexval,$$->val);  }

              ;

 符号表

1、  符号表的数据结构

typedef struct tokenlist        //符号表结构

{

    char token[20];                    //符号名

    int           type;                            //符号类型

    int           value;                           //符号值

    struct      tokenlist * next ;     //指向下一个符号表项

}TOKENLIST,*PTOKENLIST;

2、  符号表上的操作

PTOKENLIST storetoken(char*, int);   //存储符号

PTOKENLIST findtoken(char*);          //寻找符号值

void deletetoken(char*);                 //删除符号表项,一般发生在符号的生命周期结束时

void addtype(PPARSENODE,int);               //为符号表项添加类型

void flushtokenvalue(PPARSENODE,int);   //更新符号表项的值

void displaytokenlist(PTOKENLIST);      //显示符号表

 Yacc Lex 程序的交互

1、变量的交互

通过Yacc程序里已经的定义的变量yylval来作为YaccLex程序的信使。

并定义

#ifndef YYSTYPE

#define YYSTYPE PPARSENODE

#endif

这里的YYSTYPEyylval的类型,在Yacc程序编译出来的.c文件里有这样的一段代码:

YYSTYPE YYNEAR yylval;

然后,在Lex程序中有这样的代码:

extern YYSTYPE    yylval;

即引用外部程序的yylval,因此YaccLex程序就这样联系起来了。

2、  程序的交互

Lex程序中引用由Yacc程序生成的.h程序,而Yacc程序引用Lex程序生成的.h程序。

比如,在myparsetree_yacc.y中引用了:

#include "myparsetree_lex.h"

而在myparsetree_lex.l中引用了:

#include "myparsetree_yacc.h"

myparsetree_lex.h是在Lex程序中编写的,myparsetree_yacc.h是在Yacc程序中编写的,都是在下面的这段代码里:

%include{

//  .h文件里包含的代码

}

 

结果如下:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值