在我的另外两篇文章中介绍了语法分析树建立的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
};
运行截图:
parser.lex完成词法分析的工作,parser.y完成语法分析的工作。tree主要是创建树、遍历树的函数的实现,以及数据结构的设计。