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
- lex+yacc 构造语法树(二)
- lex+yacc 构造语法树(一)
- lex+yacc 构造语法树(三)
- Lex Yacc (二) 语法树
- Lex & Yacc 语法树应用
- Lex Yacc 使用方法(二)
- Lex Yacc (三) 语法树打印
- Lex与Yacc学习(九)之Yacc语法
- Lex和Yacc应用教程(四).语法树的应用
- Lex和Yacc使用教程(五).再识语法树
- Lex和Yacc使用教程(六).语法树打印
- Lex和Yacc应用教程(四).语法树的应用
- Lex和Yacc使用教程(五).再识语法树
- Lex和Yacc应用方法(六).语法树打印
- LEX AND YACC 使用(二)
- Lex和Yacc应用方法(二).再识Lex与Yacc
- Lex和Yacc应用方法(二).再识Lex与Yacc
- Lex和Yacc应用方法(二).再识Lex与Yacc
- 0400000059
- 经验分享:CSS div浮动(float,clear) 真的是太棒了
- mpg123 学习进阶1
- 黑马程序员_基础加强_JDK1.5新特性
- Android数据的四种存储方式SharedPreferences、SQLite、Content Provider和File (四) —— ContentProvider
- lex+yacc 构造语法树(二)
- 读书笔记:“集体智慧编程”之第八章:对数值进行预测(构建价格模型)
- OCP-1Z0-053-200题-160题-294
- mac-程序员必备工具(2)-iTerm2
- Python系列视频教程: Django【13讲】第八讲 数据库使用2
- OCP-1Z0-053-200题-159题-494
- C#实现邮件发送
- 解决触摸板synatipics与键盘驱动相冲突问题——win8.1
- OCP-1Z0-053-200题-158题-60