lex与yacc程序学习(3)——yacc源程序的结构&yacc编译器的实践

 

yacc源程序的结构

声明部分
%%
翻译规则
%%
辅助函数

声明部分辅助函数与lex相同。

翻译规则:语法规则+相应的语义动作

下面是一个完整的yacc程序代码:

%{
	#include<stdio.h>
	#include<ctype.h>
	#include<stdlib.h>
	int yylex();
	void yyerror(char const*); 
%} 
%token	DIGIT
%%
line	:	expr'\n'		{printf("%d\n",$1);}
		;
expr	:	expr'+'term		{$$=$1+$3;}
		|	term
		;
term	:	term'*'factor	{$$=$1*$3;}
		|	factor
		;
factor	:	'('expr')'		{$$=$2;}
		|	DIGIT
		;
%%
int main(){
	return yyparse();
}
int yylex(){
	int c;
	c=getchar();
	if(isdigit(c)){
		yylval=c-'0';
		return DIGIT;
	}
	return c;
}
void yyerror(char const*s){
	fprintf(stderr,"%s\n",s);
}

代码分析:

声明部分

       符号常量、变量等的声明;

      指出DIGIT是token类型(单词符号类型)的词汇,供后面两部分引用;

在编译yacc源程序后,会生成相应的头文件(y.tab.h),在该文件中,将DIGIT定义为一个整数,代表单词符号的种别编码。

特别说明:语法分析需要读入单词符号,因此在yacc源程序中必须包含实现词法分析功能的yylex()函数。可手动编写ylex()函数,也可以使用词法分析器的自动产生工具lex产生yylex()函数。如果使用lex创建的传送单词符号的词法分析器,则lex的源程序需要使用这里声明的token。并且在lex源程序中包含#include"y.tab.h"头文件。

翻译规则

由文法的产生式和相关的语义动作组成。

     :文法的产生式

yacc产生式冒号表示定义为竖线表示分割后选式分号表示该产生式结束

文法G(line)的产生式终结符号非终结符号组成。

终结符号:①用单引号括起来的单个字符;②token类型。

非终结符号:没括起来并且也没被说明成token类型的字符数字串。

文法的开始符号:第一个产生式的左部非终结符。

   : 语义动作部分

yacc的语义动作:在语义动作中可以引用文法符号的属性值。

$$左部非终结符号的属性值。

$n右部第n个文法符号(终结符或非终结符)的属性值。

辅助函数

  语法分析器,调用该函数开始语法分析。

在使用yyparse()函数执行语法分析的过程中,会调用yylex()函数得到单词符号。

  :必须提供的函数。

词法分析器:必须包含

每次调用yylex()时,yylex()返回1个单词符号,该单词符号包括两部分:①单词种别编码:通过yacc源程序中声明部分%token说明;②单词属性值:通过yacc定义的全局变量yylval传递给语法分析器。

  当yyparse()函数执行语法分析遇到语法错误时,会调用yyerror()函数,输出一条错误信息。

错误报告例程:必须包含

 

yacc编译器的实践

将上述完整代码写入后缀为.y的文件中

编译yacc

bison -y -d 文件名.y

  目标文件下生成c语言的源程序和头文件。

对c语言的源程序进行编译

gcc y.tab.c

生成文件

运行该文件

a.exe

可以执行加法运算和乘法运算。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值