我是靠谱客的博主 紧张月亮,最近开发中收集的这篇文章主要介绍yacc语法分析minipascal_用Yacc实现语法分析器-4-编译原理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

用Yacc实现语法分析器

一、实验目的

掌握语法分析器的构造原理,掌握Yacc的编程方法。

二、实验内容

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

program      → block

block→   { stmts}

stmts     → stmt stmts | e

stmt       →   id= expr ;

|      if ( bool ) stmt

|      if (bool) stmtelsestmt

|      while (bool) stmt

|      do stmtwhile (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]* {returnID;}

[0-9]+.[0-9]+ {returnREAL;}

[0-9]+ {returnNUM;}"||" {returnOR;}"&&" {returnAND;}"|" {return '|';}"&" {return '&';}"<=" {returnLE;}"=" {returnGE;}">" {return '>';}"!=" {returnNE;}"=" { return '=';}"==" {returnEQ;}"+" {return '+';}"-" {return '-';}"*" {return '*';}"/" {return '/';}"(" {return '(';}")" {return ')';}";" {return ';';}"{" {return '{';}"}" {return '}';}"[" {return '['; }"]" {return ']';}

Test.y:rel : expr'exprexpr<=exprn"); }| expr GE expr { printf("rel-->expr>=exprn"); }| expr '>' expr { printf("rel-->expr>exprn"); }| expr { printf("rel-->exprn"); }

;

expr : expr'+' term { printf("expr-->expr+termn"); }| expr '-' term { printf("expr-->expr-termn"); }| term { printf("expr-->termn"); }

;

term : term'*' unary { printf("term-->term*unaryn"); }| term '/' unary { printf("term-->term/unaryn"); }| unary { printf("term-->unaryn"); }

;

unary :'!' unary { printf("unary-->!unaryn"); }| '-' unary %prec UMINUS{ printf("unary-->-unaryn"); }| factor { printf("unary-->factorn"); }

;

factor :'(' bool ')' { printf("factor-->(bool)n"); }| loc { printf("factor-->locn"); }| NUM { printf("factor-->numn"); }| REAL { printf("factor-->realn"); }| TRUE { printf("factor-->truen"); }| FALSE { printf("factor-->falsen"); }

Flex生成代码:

View Code

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

[0-9]+.[0-9]+ {returnREAL;}

[0-9]+ {returnNUM;}"||" {returnOR;}"&&" {returnAND;}"|" {return '|';}"&" {return '&';}"<=" {returnLE;}"=" {returnGE;}">" {return '>';}"!=" {returnNE;}"=" { return '=';}"==" {returnEQ;}"+" {return '+';}"-" {return '-';}"*" {return '*';}"/" {return '/';}"(" {return '(';}")" {return ')';}";" {return ';';}"{" {return '{';}"}" {return '}';}"[" {return '['; }"]" {return ']';}

Test.y:rel : expr'exprexpr<=exprn"); }| expr GE expr { printf("rel-->expr>=exprn"); }| expr '>' expr { printf("rel-->expr>exprn"); }| expr { printf("rel-->exprn"); }

;

expr : expr'+' term { printf("expr-->expr+termn"); }| expr '-' term { printf("expr-->expr-termn"); }| term { printf("expr-->termn"); }

;

term : term'*' unary { printf("term-->term*unaryn"); }| term '/' unary { printf("term-->term/unaryn"); }| unary { printf("term-->unaryn"); }

;

unary :'!' unary { printf("unary-->!unaryn"); }| '-' unary %prec UMINUS{ printf("unary-->-unaryn"); }| factor { printf("unary-->factorn"); }

;

factor :'(' bool ')' { printf("factor-->(bool)n"); }| loc { printf("factor-->locn"); }| NUM { printf("factor-->numn"); }| REAL { printf("factor-->realn"); }| TRUE { printf("factor-->truen"); }| FALSE { printf("factor-->falsen"); }

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];elseyystate= yydefgoto[yyn -YYNTOKENS];gotoyynewstate;/*------------------------------------.

| yyerrlab -- here on detecting error |

`------------------------------------*/yyerrlab:/*If not already recovering from an error, report this error.*/

if (!yyerrstatus)

{++yynerrs;#if YYERROR_VERBOSEyyn=yypact[yystate];if (YYPACT_NINF < yyn && yyn

{

YYSIZE_T yysize= 0;int yytype =YYTRANSLATE (yychar);const char*yyprefix;char *yymsg;intyyx;/*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);

}elseyyerror ("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#include#include

%}%%

"if" {returnIF;}"while" {returnWHILE;}"do" {returnDO;}"break" {returnBREAK;}"int"|"float"|"bool"|"char" {returnBASIC;}"true" {returnTRUE;}"false" {returnFALSE;}"else" {returnELSE;}

[a-zA-Z_][a-zA-Z_0-9]* {returnID;}

[0-9]+.[0-9]+ {returnREAL;}

[0-9]+ {returnNUM;}"||" {returnOR;}"&&" {returnAND;}"|" {return '|';}"&" {return '&';}"<=" {returnLE;}"=" {returnGE;}">" {return '>';}"!=" {returnNE;}"=" { return '=';}"==" {returnEQ;}"+" {return '+';}"-" {return '-';}"*" {return '*';}"/" {return '/';}"(" {return '(';}")" {return ')';}";" {return ';';}"{" {return '{';}"}" {return '}';}"[" {return '['; }"]" {return ']';}"//".*{}

[ nt] {}%%

test.y

View Code

%{

#include#include

%}%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-->blockn"); }

;

block :'{' decls stmts '}' { printf("block-->{decls stmts}n"); }

;

decls : decls decl { printf("decls-->decls decln"); }| /*empty*/;

decl : type ID';' { printf("decl-->type id;n"); }

;

type : type'[' NUM ']' { printf("type-->type[num]n"); }| BASIC { printf("type-->basicn"); }

;

stmts : stmts stmt { printf("stmts-->stmts stmtn"); }| /*empty*/;

stmt : DO stmt WHILE'(' bool ')' ';' { printf("stmt-->do stmt while(bool);n"); }| IF '(' bool ')' stmt { printf("stmt--if(bool)stmtn"); }| IF '(' bool ')' stmt ELSE stmt { printf("stmt-->if(bool)stmt else stmtn"); }| WHILE '(' bool ')' stmt { printf("stmt-->while(bool)stmtn"); }| BREAK ';' { printf("stmt-->break;n"); }| block { printf("stmt-->blockn"); }| loc '=' bool ';' { printf("stmt-->loc=bool;n"); }

;

loc : loc'[' bool ']' { printf("loc-->loc[bool]n"); }| ID { printf("loc-->idn"); }

;bool : bool OR join { printf("bool-->bool||joinn"); }| join { printf("bool-->joinn"); }

;

join : join AND equality { printf("join-->join&&equalityn"); }| equality { printf("join-->equalityn"); }

;

equality : equality EQ rel { printf("equality-->equality==reln"); }| equality NE rel { printf("equality-->equality!=reln"); }| rel { printf("equality-->reln"); }

;

rel : expr'exprexpr<=exprn"); }| expr GE expr { printf("rel-->expr>=exprn"); }| expr '>' expr { printf("rel-->expr>exprn"); }| expr { printf("rel-->exprn"); }

;

expr : expr'+' term { printf("expr-->expr+termn"); }| expr '-' term { printf("expr-->expr-termn"); }| term { printf("expr-->termn"); }

;

term : term'*' unary { printf("term-->term*unaryn"); }| term '/' unary { printf("term-->term/unaryn"); }| unary { printf("term-->unaryn"); }

;

unary :'!' unary { printf("unary-->!unaryn"); }| '-' unary %prec UMINUS{ printf("unary-->-unaryn"); }| factor { printf("unary-->factorn"); }

;

factor :'(' bool ')' { printf("factor-->(bool)n"); }| loc { printf("factor-->locn"); }| NUM { printf("factor-->numn"); }| REAL { printf("factor-->realn"); }| TRUE { printf("factor-->truen"); }| FALSE { printf("factor-->falsen"); }

;%%#include"lex.yy.c"

intmain()

{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就能直接用。

最后

以上就是紧张月亮为你收集整理的yacc语法分析minipascal_用Yacc实现语法分析器-4-编译原理的全部内容,希望文章能够帮你解决yacc语法分析minipascal_用Yacc实现语法分析器-4-编译原理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部