[educoder] 用YACC(BISON)生成语法分析和翻译器
第一关
/* 逆波兰符号计算器 */
/* 功能:能够计算出合法的后缀表达式的值,包括加法、减法、乘法、除法、乘方、取反等运算 */
/* 说明:在下面的begin和end之间添加代码,加油吧! */
/* 提示: */
%{
#include <ctype.h>
#include <stdio.h>
#include <math.h>
int yylex (void);
void yyerror (char const *);
%}
%define api.value.type {double}
%token NUM
%%
/* Grammar rules and actions follow. */
input:
%empty
| input line
;
line:
'\n'
| exp '\n' { printf ("%.10g\n", $1); }
;
exp:
NUM { $$ = $1; }
/* begin: add your code */
| exp exp '+' {$$ = $1 + $2;}
| exp exp '-' {$$ = $1 - $2;}
| exp exp '*' {$$ = $1 * $2;}
| exp exp '/' {$$ = $1 / $2;}
| exp exp '^' {$$ = pow($1, $2);}
| exp 'n' {$$ = -$1;}
/* end: add your code */
;
%%
/* The lexical analyzer returns a double floating point
number on the stack and the token NUM, or the numeric code
of the character read if not a number. It skips all blanks
and tabs, and returns 0 for end-of-input. */
int yylex (void)
{
int c;
/* Skip white space. */
while ((c = getchar ()) == ' ' || c == '\t')
continue;
/* Process numbers. */
if (c == '.' || isdigit (c))
{
ungetc (c, stdin);
scanf ("%lf", &yylval);
return NUM;
}
/* Return end-of-input. */
if (c == EOF)
return 0;
if (c == '!')
return 0;
/* Return a single char. */
return c;
}
int main (int argc, char** argv)
{
return yyparse();
}
/* Called by yyparse on error. */
void yyerror (char const *s)
{
fprintf (stderr, "%s\n", s);
}
;
第二关
/* 后缀转中缀 */
/* 功能:后缀表达式转换成中缀表达式,包括加法、减法、乘法、除法等运算 */
/* 说明:在下面的begin和end之间添加代码,加油吧! */
%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#ifndef YYSTYPE
#define YYSTYPE char*
#endif
char idStr[50];
char numStr[50];
int yylex() ;
extern int yyparse() ;
FILE* yyin;
void yyerror(const char* s);
%}
%token ADD
%token MUL
%token SUB
%token DIV
%token LB
%token RB
%token NUMBER
%token ID
%left ADD MUS
%left MUL DIV
%right UMINUS
%%
lines : lines expr {printf("%s\n",$2);}
| lines
|
;
/* begin: add your code*/
expr : expr expr ADD { $$ = (char *)malloc(200*sizeof(char)); strcpy($$,"("); strcat($$,$1); strcat($$,"+"); strcat($$,$2); strcat($$,")"); }
| expr expr SUB { $$ = (char *)malloc(200*sizeof(char)); strcpy($$,"("); strcat($$,$1); strcat($$,"-"); strcat($$,$2); strcat($$,")"); }
| expr expr MUL { $$ = (char *)malloc(200*sizeof(char)); strcpy($$,"("); strcat($$,$1); strcat($$,"*"); strcat($$,$2); strcat($$,")"); }
| expr expr DIV { $$ = (char *)malloc(200*sizeof(char)); strcpy($$,"("); strcat($$,$1); strcat($$,"/"); strcat($$,$2); strcat($$,")"); }
| SUB expr %prec UMINUS { strcpy($$,"-"); strcat($$,$2); }
| NUMBER { $$ = (char *)malloc(200*sizeof(char)); strcpy($$,$1); }
| ID { $$ = (char *)malloc(200*sizeof(char)); strcpy($$,$1); }
;
/* end: add your code */
;
%%
// programs section
int yylex()
{
char t;
while(1){
t = getchar();
if(t==' ' || t =='\t'|| t == '\n')
{}
else if(t == '+'){
return ADD;
}
else if(t == '*'){
return MUL;
}
else if(t == '-'){
return SUB;
}
else if(t == '/'){
return DIV;
}
else if(t>='0'&&t<='9'){
int ti = 0;
while (t>='0'&&t<='9'){
numStr[ti]=t;
t = getchar();
ti++;
}
numStr[ti] = '\0';
yylval = numStr;
ungetc(t,stdin);
return NUMBER;
}
else if(('a'<=t&&t<='z')||('A'<=t&&'Z'>=t)||(t=='_')){
int ti=0;
while(('a'<=t&&t<='z')||('A'<=t&&'Z'>=t)||(t=='_')||(t>='0'&&t<='9')){
idStr[ti] = t;
ti++;
t=getchar();
}
idStr[ti] = '\0';
yylval = idStr;
ungetc(t,stdin);
return ID;
}
else{
return t;
}
}
}
int main(void)
{
yyin = stdin;
do {
yyparse () ;
} while (!feof(yyin)) ;
return 0;
}
void yyerror(const char* s) {
fprintf(stderr,"Parse error : %s\n",s) ;
exit(1);
}