[educoder] 用YACC(BISON)生成语法分析和翻译器

[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);
}


  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: YaccBison)是一种工具,用于生成语法分析器和翻译器。它可以根据给定的语法规则生成语法分析器,然后将输入的源代码解析成语法树。接着,可以使用翻译器将语法树转换为目标代码或其他形式的输出。使用YaccBison)可以简化语法分析翻译器的开发过程,提高开发效率。 ### 回答2: yacc是Unix操作系统中常用的语法分析生成工具,它可以生成C语言代码并用于编译程序的语法分析部分。通过定义语法规则,yacc可以自动生成语法分析器,并能够将输入的语句分解成各个语法单元,进而处理语法分析中涉及到的语言结构。 为了生成语法分析器,我们需要先定义好输入语言的文法规则。文法规则定义了语言的语法结构,可以被翻译器所使用。文法规则通常使用Backus-Naur范式(BNF)进行描述,每个产生式规则由非终结符(非语言本身的标识符或变量)和终结符(语言单词或标点等)组成。 接下来,我们将定义输入语句所对应的语法结构。例如,假设我们定义了一种简单的程序语言,它包含变量定义、表达式计算、赋值操作等语言结构。我们可以使用BNF规则来描述该语言的语法结构: 1.程序由多行语句组成 程序 = 语句 | 程序 语句 2.变量定义语句 语句 = 变量类型 变量名 ';' 3.表达式计算语句 语句 = 表达式 ';' 4.赋值语句 语句 = 变量名 '=' 表达式 ';' 其中,变量名、变量类型、表达式等都被定义成了非终结符。 接下来,我们需要利用yacc将该BNF规则转换成C语言代码。yacc会将规则转换为执行序列,并通过该序列来解析输入语句。yacc生成的代码包含以下部分: 1.定义语法规则 我们可以通过定义规则来告诉yacc需要如何将输入语句分解成各个语法单元。 2.生成各个语法单元的代码 yacc可以自动为每个语法单元生成相应的代码。 3.定义语法分析yacc可以将所有语法单元的生成代码组合成一个语法分析器。该语法分析器可以通过输入文本文件和调用词法分析器的过程来识别输入的语句并生成相应的输出。 最后,我们需要添加一些错误处理和异常处理机制,以使得生成语法分析器可以正确地处理各种异常情况。 总之,使用yacc可以很方便地生成语法分析器。它可以自动生成代码,并且可以处理各种异常情况。对于需要处理大量输入文本的应用程序来说,使用yacc可以大幅提高开发效率。 ### 回答3: yacc(Yet Another Compiler Compiler)是一个生成语法分析器和解析器的工具,它可以将输入的文本转换成抽象语法树,然后通过程序来对其进行操作。通过yacc,可以方便地生成自定义的编程语言、编译器等工具。 开发一个yacc生成语法分析器和翻译器需要以下步骤: 1. 定义语法规则 首先需要定义所开发的语言的语法规则,包括终结符和非终结符的定义,以及它们之间的关系。例如,可以使用BNF(Backus-Naur形式)表示法来定义语法规则,这是一种常用的表示语言语法的形式。 2. 编写yacc源代码 编写yacc源代码,即定义yacc文件,包括语法规则和翻译规则。语法规则用来描述输入文本的语法结构,而翻译规则则用来将输入的文本转换为目标代码或解释执行。 3. 编写lex代码 在yacc文件中,还需要将输入的文本进行词法分析,即将输入的字符流转换为词法单元(token)。这一过程通常需要使用lex工具,在lex文件中定义词法规则,并将识别出的单词输出到yacc程序中。 4. 编译和运行 将yacc和lex源代码编译成可执行文件,然后运行生成的编译器和解释器。在运行时,输入需要分析的源代码,编译器和解释器会根据定义的语法规则进行解析,并输出结果。 总的来说,使用yacc生成语法分析翻译器的过程需要熟悉语言的语法规则和编译原理,以及yacc和lex工具的使用。针对具体的需求,需要根据语言的特点和应用场景来进行设计,最终生成符合要求的编译器或解释器。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ETO降临派

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值