📄 简单的yacc程序.txt
字号:
程序源代码:
/*Lex(toyacc.lex)用于产生YACC所需的单词*
final [\+\t\n] /* 正则式定义 */
ws [final]+
letter [A-Za-z]
digit [0-9]
num {digit}+
id {letter}({letter}|{digit})*
%%
{ws} {} /* 向YACC输出单词流*/
if {inif=1;return(IF);}
then {return(THEN);}
else {state=abs(state-1);return(ELSE);} /*if中条件为布尔0,state取反*/
{id} {yylval.str=strdup (yytext); return(ID);}
{num} {yylval.str=strdup (yytext); return(NUM);}
":=" {return(FUZHI);}
"<" {yylval.intvar = 1;return(COMP);} /*返回比较符*/
"<=" {yylval.intvar = 2;return(COMP);}
"=" {yylval.intvar = 3;return(COMP);}
"<>" {yylval.intvar = 4;return(COMP);}
">" {yylval.intvar = 5;return(COMP);}
">=" {yylval.intvar = 6;return(COMP);}
";" {return(ENDOFC);}
"+" {return('+');}
"*" {return('*');}
"-" {return('-');}
%%
void readfile()
{
yyin=yylex();
}
int yywrap()
{
return 1;
}
/*YACC做PASCAL语法分析*/
%{
#include<stdio.h>
#include<ctype.h>
#include <string.h>
typedef char* string;
char* idnames[20];
int idvalues[20];
int total=0,found=0,a,inif=0,state=0; /*total 总标识符个数,state if语句是否成立*/
%}
%union {
int intvar; /*定义yylex与yacc之间接口变量的值用于传回数char *str 字和字符串。*/
}
%token IF THEN ELSE ID NUM FUZHI COMP ENDOFC /*定义标识符*/
%left '+'
%left '*'
%right UMINUS
%%
lines : ifstat ENDOFC {inif=0;} /*当一个if语句结束的时候,将标志变量复原*/
| idexpr ENDOFC
| lines lines
;
ifstat : IF statexpr THEN idexpr ELSE idexpr /*if-else语句的生成式*/
| IF statexpr THEN idexpr
;
statexpr : expr PANDUAN expr {
state=0; /*根据传回的判断符号和实际情况置 state值*/
if ($2.intvar==1 && $1.intvar==$3.intvar) state=1;
else if ($2.intvar==2 && $1.intvar<$3.intvar) state=1;
else if ($2.intvar==3 && $1.intvar<=$3.intvar) state=1;
else if ($2.intvar==4 && $1.intvar!=$3.intvar) state=1;
else if ($2.intvar==5 && $1.intvar>$3.intvar) state=1;
else if ($2.intvar==6 && $1.intvar>=$3.intvar) state=1;
} ;
/*赋值语句的生成式*/
idexpr : ID FUZHI expr {
if (inif==0 || (inif==1 && state==1)){ //如果赋值语句不在if语句内,或者是一个为真的if语句内
found=0;
for(a=1;a<=total;a++) // 标识符存在,直接赋值
if (strcmp($1.str,idnames[a])==0){
found=1;
idvalues[a]=$3.intvar;
}
if (found==0) { //如不存在,添加进符号表
total++;
idnames[total]=strdup($1.str);
idvalues[total]=$3.intvar;
}
}
} ;
/*计算式,包含标识符以及数字的生成式*/
expr : expr'+'expr {$$.intvar=$1.intvar+$3.intvar;}
| expr'*'expr {$$.intvar=$1.intvar*$3.intvar;}
| '('expr')' {$$.intvar=$2.intvar;}
|'-'expr %prec UMINUS {$$.intvar=-$2.intvar;}
| NUM {$$.intvar=atoi(yylval.str);}
|ID {
found=0;
for(a=1;a<=total;a++)
if (strcmp($1.str,idnames[a])==0){
found=1;
$$.intvar=idvalues[a];
}
if (found==0) {
total++;
idnames[total]=strdup($1.str);
$$.intvar=0;
idvalues[total]=0;
}} ;
%%
#include"royacc.c" /*引入lex中的分析结果*/
main(){
yyparse();
printf("NO error!\n");
printf("%d identifiers totally:",total);
for(a=1;a<=total;a++) printf("Idname: %s , Value: %d\n",idnames[a],idvalues[a]);
}
程序输出测试:
输入:x:=1;
y:=x+1;
if y>x then z=y else z=x;
输出:
NO error!
3 identifiers totally: X:1
Y:2
Z:2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -