用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 + term
| expr - term
| term
term → term * factor
| term / factor
| factor
factor → ( expr ) | id| num
三、实验步骤及结果
实验环境:unix
实验结果:按归约的先后顺序显示每次归约时所使用的产生式。
部分代码:
用于产生flex输入的代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif) 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 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 { 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生成代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif) 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 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 { 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生成部分代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif) 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 |