编译原理:使用flex和bison工具实现语法分析树的建立

在我的另外两篇文章中介绍了语法分析树建立的Java实现,这次使用flex和bison在Unix环境下完成语法分析树的建立

flex介绍

bison介绍

关于flex和bison的使用和语法在这里就不详细的介绍了。

如果你的Unix环境没有装这两个工具可以使用如下命令进行安装(机器需要连接网)

sudo apt-get install bison
sudo apt-get install flex
按照提示属于“y”即可完成安装

parser.lex

%{
#include "parser.tab.h"
#include "tree.h"
#include 

int line=1; 
int tempTag;
int getTag(char *);

%}

DIGIT 	[0-9]
LETTER	[A-Za-z]
SPACE	\ |\t
LINE	\n
NUM	{DIGIT}+
ID	{LETTER}({LETTER}|{DIGIT})*


%%

{LINE}	{line++;}
{SPACE}	{}

[=]	{yylval=createLeaf(SET,yytext); return SET;}
[!]	{yylval=createLeaf(NOT,yytext); return NOT;}
[+]	{yylval=createLeaf(ADD,yytext); return ADD;}
[-]	{yylval=createLeaf(SUB,yytext); return SUB;}
[*]	{yylval=createLeaf(MUL,yytext); return MUL;}
[/]	{yylval=createLeaf(DIV,yytext); return DIV;}
[>]	{yylval=createLeaf(GT,yytext); return GT;}
[<]	{yylval=createLeaf(LT,yytext); return LT;}
[>][=]	{yylval=createLeaf(GE,yytext); return GE;}
[<][=]	{yylval=createLeaf(LE,yytext); return LE;}
[=][=]	{yylval=createLeaf(EQ,yytext); return EQ;}
[!][=]	{yylval=createLeaf(NE,yytext); return NE;}
[&][&]	{yylval=createLeaf(AND,yytext); return AND;}
[|][|]	{yylval=createLeaf(OR,yytext); return OR;}

[;]	{yylval=createLeaf(SC,yytext); return SC;}
[(]	{yylval=createLeaf(LP,yytext); return LP;}
[)]	{yylval=createLeaf(RP,yytext); return RP;}
[{]	{yylval=createLeaf(LB,yytext); return LB;}
[}]	{yylval=createLeaf(RB,yytext); return RB;}
\[	{yylval=createLeaf(LSB,yytext); return LSB;}
\]	{yylval=createLeaf(RSB,yytext); return RSB;}

{NUM}	{
		yylval=createLeaf(NUM,yytext); 
		return NUM;
	}
{ID}	{
		tempTag=getTag(yytext); 
		yylval=createLeaf(tempTag,yytext);
		return tempTag;
	}

.	{printf("lexical error: line %d, %s\n", line, yytext);}

%%

int getTag(char *s)
{
	if(strcmp(s,"if")==0)
		return IF;
	else if(strcmp(s,"else")==0)
		return ELSE;
	else if(strcmp(s,"while")==0)
		return WHILE;
	else if(strcmp(s,"do")==0)
		return DO;
	else if(strcmp(s,"break")==0)
		return BREAK;
	else if(strcmp(s,"true")==0)
		return TRUE;
	else if(strcmp(s,"false")==0)
		return FALSE;
	else if(strcmp(s,"int")==0)
		return INT;
	else if(strcmp(s,"bool")==0)
		return BOOL;
	else 
		return ID;
}
parser.y

%{

#include "tree.h"
#include 
#include 

struct Node *cldArray[10];
int cldN;
int nTag;

void yyerror (char const *s);
int yylex();

%}

//set attribute type
%define api.value.type {struct Node *}

/* declare tokens */
%token  IF 256  ELSE 257  WHILE 258  DO 259  BREAK 260   TRUE 261  FALSE 262  INT 263  BOOL 264  AND 265  OR 266  NOT 267  EQ 268  NE 269  GT 270  GE 271  LT 272  LE 273  SET 274  ADD 275  SUB 276  MUL 277  DIV 278  SC 279  LP 280  RP 281  LB 282  RB 283  LSB 284  RSB 285  ID 286  NUM 287 

%token  EPS 317
   
   
   	
%%
 
program: block {nTag=PRO; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray); treePrint($$);};

block: LB decls stmts RB {nTag=BLO; cldN=4; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; cldArray[3]=$4; $$=createNode(nTag, cldN, cldArray);};

decls: {nTag=DECLS; cldN=1; cldArray[0]=createEmpty(); $$=createNode(nTag, cldN, cldArray);}
  | decls decl {nTag=DECLS; cldN=2; cldArray[0]=$1; cldArray[1]=$2; $$=createNode(nTag, cldN, cldArray);};

stmts: {nTag=STMTS; cldN=1; cldArray[0]=createEmpty(); $$=createNode(nTag, cldN, cldArray);}
  | stmts stmt {nTag=STMTS; cldN=2; cldArray[0]=$1; cldArray[1]=$2; $$=createNode(nTag, cldN, cldArray);};
 
decl: type ID SC {nTag=DECL; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);};

type: type LSB NUM RSB {nTag=TYP; cldN=4; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; cldArray[3]=$4; $$=createNode(nTag, cldN, cldArray);}
  | basic {nTag=TYP; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

basic: INT {nTag=BASIC; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);}
  | BOOL {nTag=BASIC; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

stmt: loc SET bexpr SC {nTag=STMT; cldN=4; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; cldArray[3]=$4; $$=createNode(nTag, cldN, cldArray);}
  | IF LP bexpr RP stmt {nTag=STMT; cldN=5; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; cldArray[3]=$4; cldArray[4]=$5; $$=createNode(nTag, cldN, cldArray);}
  | IF LP bexpr RP stmt ELSE stmt {nTag=STMT; cldN=7; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; cldArray[3]=$4; cldArray[4]=$5; cldArray[5]=$6; cldArray[6]=$7; $$=createNode(nTag, cldN, cldArray);}
  | WHILE LP bexpr RP stmt {nTag=STMT; cldN=5; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; cldArray[3]=$4; cldArray[4]=$5; $$=createNode(nTag, cldN, cldArray);}
  | DO stmt WHILE LP bexpr RP SC {nTag=STMT; cldN=7; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; cldArray[3]=$4; cldArray[4]=$5; cldArray[5]=$6; cldArray[6]=$7; $$=createNode(nTag, cldN, cldArray);}
  | BREAK SC {nTag=STMT; cldN=2; cldArray[0]=$1; cldArray[1]=$2; $$=createNode(nTag, cldN, cldArray);}
  | block {nTag=STMT; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

loc: loc LSB aexpr RSB {nTag=LOC; cldN=4; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; cldArray[3]=$4; $$=createNode(nTag, cldN, cldArray);}
  | ID {nTag=LOC; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

bexpr: bexpr OR join {nTag=BEXP; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | join {nTag=BEXP; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

join: join AND equality {nTag=JOIN; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | equality {nTag=JOIN; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

equality: equality EQ rel {nTag=EQU; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | equality NE rel {nTag=EQU; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | rel {nTag=EQU; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

rel: aexpr LT aexpr {nTag=REL; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);} 
  | aexpr LE aexpr {nTag=REL; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | aexpr GT aexpr {nTag=REL; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | aexpr GE aexpr {nTag=REL; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | aexpr {nTag=REL; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

aexpr: aexpr ADD term {nTag=AEXP; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | aexpr SUB term {nTag=AEXP; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | term {nTag=AEXP; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

term: term MUL unary {nTag=TERM; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | term DIV unary {nTag=TERM; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | unary {nTag=TERM; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

unary: NOT unary {nTag=UNY; cldN=2; cldArray[0]=$1; cldArray[1]=$2; $$=createNode(nTag, cldN, cldArray);}
  | SUB unary {nTag=UNY; cldN=2; cldArray[0]=$1; cldArray[1]=$2; $$=createNode(nTag, cldN, cldArray);}
  | factor {nTag=UNY; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};

factor: LP bexpr RP {nTag=FAC; cldN=3; cldArray[0]=$1; cldArray[1]=$2; cldArray[2]=$3; $$=createNode(nTag, cldN, cldArray);}
  | loc {nTag=FAC; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};
  | NUM {nTag=FAC; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};
  | TRUE {nTag=FAC; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};
  | FALSE {nTag=FAC; cldN=1; cldArray[0]=$1; $$=createNode(nTag, cldN, cldArray);};



%%

int main()
{
  	yyparse();
  	return 0;
}

void yyerror (char const *s)
{
  	fprintf (stderr, "%s\n", s);
}
tree.c

#include "parser.tab.h"
#include "tree.h"
#include 
#include 
#include 


struct Node *createLeaf(int tag, char *text)
{
	struct Node *nd=(struct Node*)malloc(sizeof(struct Node));
	nd->ncld=0;
	nd->tag=tag;
	if(tag==ID || tag==NUM)
	{
		nd->value=(char*)malloc(sizeof(char)*strlen(text));
		strcpy(nd->value,text);
	}
	else
		nd->value=NULL;
	return nd;
}

struct Node *createNode(int tag, int ncld, struct Node *a[])
{
	int i;
	struct Node *nd=(struct Node*)malloc(sizeof(struct Node));
	nd->ncld=ncld;
	nd->tag=tag;
	nd->value=NULL;
	for(i=0; incld; i++)
		(nd->cld)[i]=a[i];
	return nd;
}

struct Node *createEmpty()
{
	struct Node *nd=(struct Node*)malloc(sizeof(struct Node));
	nd->ncld=0;
	nd->tag=EPS;
	nd->value=NULL;

	return nd;
}

void treePrintLevel(struct Node *nd, int lvl)
{
	int i;
	if(nd!=NULL)
	{
		for(i=0; i<4*lvl; i++)
			printf("-");
		
		if(nd->value==NULL)
			printf("<%d,->\n", nd->tag);
		else 
			printf("<%d,%s>\n", nd->tag, nd->value);
		
		for (i=0; incld; i++) {  
			treePrintLevel((nd->cld)[i], lvl+1);
		}
	}
}

void treePrint(struct Node *nd)
{
	treePrintLevel(nd, 0);
}
tree.h

struct Node
{
    int tag;
    char* value;

    struct Node *cld[10];
    int ncld;
};

struct Node *createLeaf(int tag, char *text);
struct Node *createNode(int tag, int ncld, struct Node *a[]);
struct Node *createEmpty();
void treePrint(struct Node * nd);

enum yyNTtype
{
    PRO = 300,  
    BLO = 301, 
    DECLS = 302,  
    DECL = 303,  
    STMTS = 304,  
    STMT = 305,  
    TYP = 306,  
    BASIC = 307,  
    LOC = 308,  
    BEXP = 309,  
    AEXP = 310,  
    JOIN = 311,  
    EQU = 312,  
    REL = 313,  
    TERM = 314,  
    UNY = 315,  
    FAC = 316 
};


打开终端输入:


运行截图:

编译原理:使用flex和bison工具实现语法分析树的建立_第1张图片
parser.lex完成词法分析的工作,parser.y完成语法分析的工作。tree主要是创建树、遍历树的函数的实现,以及数据结构的设计。

你可能感兴趣的:(编译原理,flex,bison,语法分析树)