lex+yacc 构造语法树(二)

来源:互联网 发布:root权限获取软件 编辑:程序博客网 时间:2024/05/18 13:07

上一章我们已经写好了lex.l文件,接下来我们还要根据归约规则来确定所得到的token是由上一级的哪些token展开而成。

我们需要构造的small C语言的语法规则如下:


归约规则的声明格式参照yacc的格式,需要注意的是声明符号的左结合或右结合的时候要注意符号的优先级。

%{#include <stdlib.h>#include <stdio.h>#include <string.h>#include "lex.yy.c"#include "Node.h"#include "brothertree.c"Node* p;void yyerror(char *s);FILE *fout;%}%union{         struct Node *token_p;}%type <token_p> program extdefs extdef extvars spec stspec opttag var func paras para stmtblock stmts stmt estmt defs def decs dec init exp arrs args%token<token_p> INT ID SEMI COMMA LC RC STRUCT RETURN IF ELSE BREAK CONT FOR READ WRITE%left<token_p>SUB%right<token_p>MINUS TYPE ASSIGNOP BINARYOP11%left<token_p>  BINARYOP10%left<token_p>  BINARYOP9%left<token_p>  BINARYOP8%left<token_p>  BINARYOP7%left<token_p>  BINARYOP6%left<token_p>  BINARYOP5%left<token_p>  BINARYOP4%left<token_p>  BINARYOP3%left<token_p>  BINARYOP2%left<token_p>  BINARYOP1%right<token_p>UNARYOP %left<token_p>  DOT  LP RP LB RB%%program :            extdefs    { p=newNode("program",$1->No_Line);                       insert(p,$1);                       $$ =p;}        ;extdefs :            extdef extdefs  { p=newNode("extdefs",$1->No_Line);                            insert(p,$1);                            insert(p,$2);                            $$=p;}        |                   { p=newNode("NULL",0);                                $$=p;}        ;extdef  :             spec extvars SEMI  { p=newNode("extdef",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |  spec func stmtblock { p=newNode("extdef",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        ;extvars :           dec                 { p=newNode("extvars",$1->No_Line);                                 insert(p,$1);                                 $$=p;}        |  dec COMMA extvars   { p=newNode("extvars",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |                       { p=newNode("NULL",0);                                $$=p;}        ;spec    :           TYPE                 { p=newNode("spec",$1->No_Line);                                 insert(p,$1);                                 $$=p;}         |  stspec               { p=newNode("spec",$1->No_Line);                                 insert(p,$1);                                 $$=p;}              ;stspec  :           STRUCT opttag LC defs RC { p=newNode("stspec",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                insert(p,$5);                                $$=p;}        | STRUCT ID             { p=newNode("stspec",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}        ;opttag  :           ID                   { p=newNode("opttag",$1->No_Line);                                insert(p,$1);                                $$=p;}        |                       { $$=NULL;}        ;var     :             ID                   { p=newNode("var",$1->No_Line);                                insert(p,$1);                                $$=p;}        |  var LB INT RB       { p=newNode("var",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                $$=p;}        ;func    :           ID LP paras RP       { p=newNode("func",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                $$=p;}        ;paras   :           para COMMA paras     { p=newNode("paras",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |  para                 { p=newNode("paras",$1->No_Line);                                insert(p,$1);                                $$=p;}        |                        { p=newNode("NULL",0);                                $$=p;}        ;para    :             spec var            { p=newNode("para",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}         ;stmtblock :            LC defs stmts RC     { p=newNode("stmtblock",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                $$=p;}          ;stmts     :            stmt stmts          { p=newNode("stmts",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}          |                     { p=newNode("NULL",0);                                $$=p;}          ;stmt      :            exp SEMI            { p=newNode("stmt",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}          |  stmtblock           { p=newNode("stmt",$1->No_Line);                                insert(p,$1);                                $$=p;}          |  RETURN exp SEMI     { p=newNode("stmt",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}          | IF LP exp RP stmt estmt  { p=newNode("stmt",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                insert(p,$5);                                insert(p,$6);                                $$=p;}          | FOR LP exp SEMI exp SEMI exp RP stmt { p=newNode("stmt",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                insert(p,$5);                                insert(p,$6);                                insert(p,$7);                                insert(p,$8);                                insert(p,$9);                                $$=p;}          | CONT SEMI           { p=newNode("stmt",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}          | BREAK SEMI          { p=newNode("stmt",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}          | WRITE LP exp RP SEMI    { p=newNode("stmt",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                insert(p,$5);                                $$=p;}          | READ LP exp RP SEMI    { p=newNode("stmt",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                insert(p,$5);                                $$=p;}          ;estmt      :            ELSE stmt            { p=newNode("estmt",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}          |                      { p=newNode("NULL",0);                                $$=p;}          ;defs      :            def defs            { p=newNode("defs",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}          |                      { p=newNode("NULL",0);                                $$=p;}          ;def       :            spec decs SEMI      { p=newNode("def",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}          ;decs      :             dec COMMA decs     { p=newNode("decs",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}          | dec                { p=newNode("decs",$1->No_Line);                                insert(p,$1);                                $$=p;}          ;dec       :            var                { p=newNode("dec",$1->No_Line);                                insert(p,$1);                                $$=p;}          | var ASSIGNOP init  { p=newNode("dec",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}init      :             exp                { p=newNode("init",$1->No_Line);                                insert(p,$1);                                $$=p;}          |  LC args RC          { p=newNode("init",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}          ;exp       :             exp BINARYOP1 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |   exp BINARYOP2 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |   exp BINARYOP3 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |   exp BINARYOP4 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |   exp BINARYOP5 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |   exp BINARYOP6 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |   exp BINARYOP7 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |   exp BINARYOP8 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |   exp BINARYOP9 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}        |   exp BINARYOP10 exp     { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}      | exp BINARYOP11 exp{p = newNode("exp", $1->No_Line);                         insert(p, $1);                        insert(p, $2);                        insert(p, $3);                        $$ = p;}      | exp ASSIGNOP exp{p = newNode("exp", $1->No_Line);                    insert(p, $1);                   insert(p, $2);                   insert(p, $3);                                $$ = p;}      | exp SUB exp       {p = newNode("exp", $1->No_Line);                       insert(p, $1);                      insert(p, $2);                      insert(p, $3);                      $$ = p;}          |  UNARYOP exp        { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}        | SUB exp %prec MINUS{p = newNode("exp", $1->No_Line);                         insert(p, $1);                        insert(p, $2);                        $$ = p;}          |  LP exp RP          { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}          |  ID LP args RP      { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                $$=p;}          |   ID arrs           { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                $$=p;}          |   exp DOT ID      { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}          |  INT               { p=newNode("exp",$1->No_Line);                                insert(p,$1);                                $$=p;}          |                    { p=newNode("NULL",0);                                $$=p;}          ;arrs      :             LB exp RB arrs    { p=newNode("arrs",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                insert(p,$4);                                $$=p;}          |                     { p=newNode("NULL",0);                                $$=p;}          ; args      :  exp COMMA args    { p=newNode("args",$1->No_Line);                                insert(p,$1);                                insert(p,$2);                                insert(p,$3);                                $$=p;}          | exp                { p=newNode("args",$1->No_Line);                                insert(p,$1);                                $$=p;}          ;%%

以上过程实际上已经构成了语法树,比如当 exp COMMA args 归约成 args的时候,生成一个父节点args,并将exp,COMMA,args都作为新的父节点的子节点。但需要按照我们希望的方式打印出来还要另外设置函数。yacc的报错函数和main函数如下,其中引用的print和上面用的insert函数将于下一个章节给出:

void yyerror(char* s){         FILE* errdir=NULL;     errdir=fopen("stderr","w");     if(fout!=NULL)     fprintf(fout,"Error.");     fprintf(errdir,"line %d error.\n",No_Line);     fclose(fout);     fclose(errdir);     exit(1);}int main(int argc,char *argv[]){         FILE* fin=NULL;     extern FILE* yyin;     fin=fopen(argv[1],"r");      fout=fopen(argv[2],"w");     if(fin==NULL)     {          printf("cannot open reading file.\n");         return -1;     }     yyin=fin;     yyparse();     printTree(p,fout);     fclose(fin);     fclose(fout);     return 0;}


0 0
原创粉丝点击