上一章我们已经写好了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(