您的位置:首页 > 其它

用Yacc实现语法分析器-4-编译原理

2013-08-26 12:55 357 查看
Yacc实现语法分析器

一、实验目的
掌握语法分析器的构造原理,掌握Yacc的编程方法。

二、实验内容
Yacc编写一个语法分析程序,使之与词法分析器结合,能够根据语言的上下文无关文法,识别输入的单词序列是否文法的句子。

program → block

block→ { stmts }

stmts → stmt stmts | e

stmt → id= expr ;

| if ( bool ) stmt

| if ( bool) stmt else stmt

| while (bool) stmt

| do stmt while (bool ) ;

| break ;

| block

bool → expr < expr

| expr <= expr

| expr > expr

| expr >= expr

| expr

expr → expr + term

| expr - term

| term

term → term * factor

| term / factor

| factor

factor → ( expr ) | id| num 

三、实验步骤及结果
实验环境:unix
实验结果:按归约的先后顺序显示每次归约时所使用的产生式。
部分代码:
用于产生flex输入的代码




View Code

Test.l:[a-zA-Z_][a-zA-Z_0-9]* {return ID;}

[0-9]+\.[0-9]+ {return REAL;}

[0-9]+ {return NUM;}

"||" {return OR;}

"&&" {return AND;}

"|" {return '|';}

"&" {return '&';}

"<=" {return LE;}

"<" { return '<';}

">=" {return GE;}

">" {return '>';}

"!=" {return NE;}

"=" { return '=';}

"==" {return EQ;}

"\+"  {return '+';}

"\-" {return '-';}

"\*" {return '*';}

"\/" {return '/';}

"(" {return '(';}

")" {return ')';}

";" {return ';';}

"{" {return '{';}

"}" {return '}';}

"[" {return '['; }

"]" {return ']';}

Test.y:rel : expr '<' expr { printf("rel-->expr<expr\n"); }

| expr LE expr { printf("rel-->expr<=expr\n"); }

| expr GE expr { printf("rel-->expr>=expr\n"); }

| expr '>' expr { printf("rel-->expr>expr\n"); }

| expr { printf("rel-->expr\n"); }

;

expr : expr '+' term { printf("expr-->expr+term\n"); }

| expr '-' term { printf("expr-->expr-term\n"); }

| term { printf("expr-->term\n"); }

;

term : term '*' unary { printf("term-->term*unary\n"); }

| term '/' unary { printf("term-->term/unary\n"); }

| unary { printf("term-->unary\n"); }

;

unary : '!' unary { printf("unary-->!unary\n"); }

| '-' unary %prec UMINUS{ printf("unary-->-unary\n"); }

| factor { printf("unary-->factor\n"); }

;

factor : '(' bool ')' { printf("factor-->(bool)\n"); }

| loc { printf("factor-->loc\n"); }

| NUM { printf("factor-->num\n"); }

| REAL { printf("factor-->real\n"); }

| TRUE { printf("factor-->true\n"); }

| FALSE { printf("factor-->false\n"); }


Flex生成代码:




View Code

Test.l:[a-zA-Z_][a-zA-Z_0-9]* {return ID;}

[0-9]+\.[0-9]+ {return REAL;}

[0-9]+ {return NUM;}

"||" {return OR;}

"&&" {return AND;}

"|" {return '|';}

"&" {return '&';}

"<=" {return LE;}

"<" { return '<';}

">=" {return GE;}

">" {return '>';}

"!=" {return NE;}

"=" { return '=';}

"==" {return EQ;}

"\+"  {return '+';}

"\-" {return '-';}

"\*" {return '*';}

"\/" {return '/';}

"(" {return '(';}

")" {return ')';}

";" {return ';';}

"{" {return '{';}

"}" {return '}';}

"[" {return '['; }

"]" {return ']';}

Test.y:rel : expr '<' expr { printf("rel-->expr<expr\n"); }

| expr LE expr { printf("rel-->expr<=expr\n"); }

| expr GE expr { printf("rel-->expr>=expr\n"); }

| expr '>' expr { printf("rel-->expr>expr\n"); }

| expr { printf("rel-->expr\n"); }

;

expr : expr '+' term { printf("expr-->expr+term\n"); }

| expr '-' term { printf("expr-->expr-term\n"); }

| term { printf("expr-->term\n"); }

;

term : term '*' unary { printf("term-->term*unary\n"); }

| term '/' unary { printf("term-->term/unary\n"); }

| unary { printf("term-->unary\n"); }

;

unary : '!' unary { printf("unary-->!unary\n"); }

| '-' unary %prec UMINUS{ printf("unary-->-unary\n"); }

| factor { printf("unary-->factor\n"); }

;

factor : '(' bool ')' { printf("factor-->(bool)\n"); }

| loc { printf("factor-->loc\n"); }

| NUM { printf("factor-->num\n"); }

| REAL { printf("factor-->real\n"); }

| TRUE { printf("factor-->true\n"); }

| FALSE { printf("factor-->false\n"); }


Yacc生成部分代码:




View Code

#line 1334 "y.tab.c"

yyvsp -= yylen;

yyssp -= yylen;

YY_STACK_PRINT (yyss, yyssp);

*++yyvsp = yyval;

/* Now `shift' the result of the reduction.  Determine what state

that goes to, based on the state we popped back to and the rule

number reduced by.  */

yyn = yyr1[yyn];

yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;

if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)

yystate = yytable[yystate];

else

yystate = yydefgoto[yyn - YYNTOKENS];

goto yynewstate;

/*------------------------------------.

| yyerrlab -- here on detecting error |

`------------------------------------*/

yyerrlab:

/* If not already recovering from an error, report this error.  */

if (!yyerrstatus)

{

++yynerrs;

#if YYERROR_VERBOSE

yyn = yypact[yystate];

if (YYPACT_NINF < yyn && yyn < YYLAST)

{

YYSIZE_T yysize = 0;

int yytype = YYTRANSLATE (yychar);

const char* yyprefix;

char *yymsg;

int yyx;

/* Start YYX at -YYN if negative to avoid negative indexes in

YYCHECK.  */

int yyxbegin = yyn < 0 ? -yyn : 0;

/* Stay within bounds of both yycheck and yytname.  */

int yychecklim = YYLAST - yyn;

int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;

int yycount = 0;

yyprefix = ", expecting ";

for (yyx = yyxbegin; yyx < yyxend; ++yyx)

if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)

{

yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);

yycount += 1;

if (yycount == 5)

{

yysize = 0;

break;

}

}

yysize += (sizeof ("syntax error, unexpected ")

+ yystrlen (yytname[yytype]));

yymsg = (char *) YYSTACK_ALLOC (yysize);

if (yymsg != 0)

{

char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");

yyp = yystpcpy (yyp, yytname[yytype]);

if (yycount < 5)

{

yyprefix = ", expecting ";

for (yyx = yyxbegin; yyx < yyxend; ++yyx)

if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)

{

yyp = yystpcpy (yyp, yyprefix);

yyp = yystpcpy (yyp, yytname[yyx]);

yyprefix = " or ";

}

}

yyerror (yymsg);

YYSTACK_FREE (yymsg);

}

else

yyerror ("syntax error; also virtual memory exhausted");

}

else


例如,程序片断

{ i = 2; while (i <=100) { sum = sum + i; i = i + 2; } }
(注:原本是在windwos环境下编程,最后到unix环境下,发现速度快了,灵活性高了,同时方便了很多。(flex,bison))
test.l




View Code

%option noyywrap
%{
#include<stdlib.h>
#include<ctype.h>
#include<stdio.h>
%}
%%
"if" {return IF;}
"while" {return WHILE;}
"do" {return DO;}
"break" {return BREAK;}
"int"|"float"|"bool"|"char" {return BASIC;}
"true" {return TRUE;}
"false" {return FALSE;}
"else"  {return ELSE;}
[a-zA-Z_][a-zA-Z_0-9]* {return ID;}
[0-9]+\.[0-9]+ {return REAL;}
[0-9]+ {return NUM;}
"||" {return OR;}
"&&" {return AND;}
"|" {return '|';}
"&" {return '&';}
"<=" {return LE;}
"<" { return '<';}
">=" {return GE;}
">" {return '>';}
"!=" {return NE;}
"=" { return '=';}
"==" {return EQ;}
"\+"  {return '+';}
"\-" {return '-';}
"\*" {return '*';}
"\/" {return '/';}
"(" {return '(';}
")" {return ')';}
";" {return ';';}
"{" {return '{';}
"}" {return '}';}
"[" {return '['; }
"]" {return ']';}
"//".*  {}
[ \n\t] {}
%%


test.y




View Code

%{
#include<ctype.h>
#include<stdio.h>
%}
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%token NUM AND BASIC BREAK DO ELSE EQ FALSE GE
%token ID IF INDEX LE MINUS NE OR REAL TRUE WHILE
KET
%token  RIGHT_BRA
%%
program : block { printf("program-->block\n"); }
;
block : '{' decls stmts '}' { printf("block-->{decls stmts}\n"); }
;
decls : decls decl { printf("decls-->decls decl\n"); }
| /*empty*/
;
decl : type ID ';' { printf("decl-->type id;\n"); }
;
type : type '[' NUM ']' { printf("type-->type[num]\n"); }
| BASIC { printf("type-->basic\n"); }
;
stmts : stmts stmt { printf("stmts-->stmts stmt\n"); }
| /*empty*/
;
stmt : DO stmt WHILE '(' bool ')' ';' { printf("stmt-->do stmt while(bool);\n"); }
| IF '(' bool ')' stmt { printf("stmt--if(bool)stmt\n"); }
| IF '(' bool ')' stmt ELSE stmt { printf("stmt-->if(bool)stmt else stmt\n"); }
| WHILE '(' bool ')' stmt { printf("stmt-->while(bool)stmt\n"); }
| BREAK ';' { printf("stmt-->break;\n"); }
| block { printf("stmt-->block\n"); }
| loc '=' bool ';' { printf("stmt-->loc=bool;\n"); }
;
loc : loc '[' bool ']' { printf("loc-->loc[bool]\n"); }
| ID { printf("loc-->id\n"); }
;
bool : bool OR join { printf("bool-->bool||join\n"); }
| join { printf("bool-->join\n"); }
;
join : join AND equality { printf("join-->join&&equality\n"); }
| equality { printf("join-->equality\n"); }
;
equality : equality EQ rel { printf("equality-->equality==rel\n"); }
| equality NE rel { printf("equality-->equality!=rel\n"); }
| rel { printf("equality-->rel\n"); }
;
rel : expr '<' expr { printf("rel-->expr<expr\n"); }
| expr LE expr { printf("rel-->expr<=expr\n"); }
| expr GE expr { printf("rel-->expr>=expr\n"); }
| expr '>' expr { printf("rel-->expr>expr\n"); }
| expr { printf("rel-->expr\n"); }
;
expr : expr '+' term { printf("expr-->expr+term\n"); }
| expr '-' term { printf("expr-->expr-term\n"); }
| term { printf("expr-->term\n"); }
;
term : term '*' unary { printf("term-->term*unary\n"); }
| term '/' unary { printf("term-->term/unary\n"); }
| unary { printf("term-->unary\n"); }
;
unary : '!' unary { printf("unary-->!unary\n"); }
| '-' unary %prec UMINUS{ printf("unary-->-unary\n"); }
| factor { printf("unary-->factor\n"); }
;
factor : '(' bool ')' { printf("factor-->(bool)\n"); }
| loc { printf("factor-->loc\n"); }
| NUM { printf("factor-->num\n"); }
| REAL { printf("factor-->real\n"); }
| TRUE { printf("factor-->true\n"); }
| FALSE { printf("factor-->false\n"); }
;

%%
#include "lex.yy.c"
int  main()
{
extern FILE *yyin;
yyin=fopen("b.txt","r");
yyparse();
return 0;
}
yyerror(char *s)
{
printf("%s error!\n",s);
}


b.txt




View Code

{
i = 2;
while (i <=100)
{
sum = sum + i;
i = i + 2;
}
}


在unix可以生成a.out就能直接用。

《Lex与Yacc》中文第二版(带源码)_yacc_flex_两份文档:http://pan.baidu.com/share/link?shareid=167248&uk=1678594189

实验4 secomd time 晋级版():http://pan.baidu.com/share/link?shareid=167252&uk=1678594189
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: