Redy语法分析--一个简单的四则运算计算器

来源:互联网 发布:天宫一号 知乎 编辑:程序博客网 时间:2024/05/30 05:09

返回文档首页

(一)简介

代码下载: git clone git://git.code.sf.net/p/redy/code redy-code


这一章的内容:

使用yacc实现一个简单的四则运算计算器


(二)四则运算计算器

这一章里面我会讲解怎么使用yacc来完成一个简单的四则运算器,该计算器功能有:
  1. 有26个寄存器,分别用'a'-'z'来表示,用来保存数据,以便后面使用
  2. 支持加法,减法,乘法, 除法这四种运算
  3. 支持括号
  4. 不持浮点数的运算,当除法运算结果不为整数时,舍弃小数部份。
  5. 当输入是错误表达式时,输出为“Syntax Error",否则输出运算的结果
使用方法为:
  1. 字母=表达式     表示把表达式的值保存寄存器中。例如:a=1+3 ,运行后,寄存器a的值为4
  2. 运算单元可以是整数,也可以是寄存器,例如1*3+2, a+b+3*c。


(1)文法分析

四则运算合运算符的优先级为:
  1. 括号,运算单元(整数,寄存器)
  2. 一元运算符'-',表示负数
  3. 乘号和除号这两个运算符
  4. 加号和减号
  5. 等号,用于把结果保存到寄存器中

在写文法这前,先介绍一下yacc的书写格式
  1. 符号’:'左边为产生式左部,右边为产生式右部,右部的多个文法符号用空格分开。
  2. 如果左部的文法符号可以推导出多个字符串情况,用'|'把它们分开。
  3. 在每个产式的右部,可以嵌入语义动作,放在大括号中,$$表示产生式左部文法符号的属性,$i表示产生式右部第i个文法的属性。
  4. 如果在程序中没有嵌入语义动作,yacc则采用缺省语义动作。

编写文法的算述表达式文法的技巧为,先运算符的优先级是高的,接着依次到最底

第一步,这里面括号,运算单元(整数,寄存器)的化先级最高,文法为:
primary_expr: '(' expr ')' {$$=$2;}| number| letter {$$=reg[$1];};

其中:

  1. 第一行语义动作表示,把第二个文法符号的属性(即expr)的值,赋值给产生式左部的文法符号primary_expr
  2. 第三行语义动作表示,把letter所表示寄存器中的值取出,赋值给primary_expr。
  3. 第二行采用是缺省的语义动作,为$$=$1,表示把number的值赋给primary_expr

第二步,为优先级第二运算符编写文法:

unary_expr: primary_expr   | '-' primary_expr {$$=-$2;}  ;

第三步,接着为乘号和除号:

mul_expr:unary_expr {$$=$1;}| mul_expr '*' unary_expr {$$=$1*$3;}| mul_expr '/' unary_expr {$$=$1/$3;};

第四步,为加号和减号:

add_expr:mul_expr {$$=$1;}| add_expr '+' mul_expr {$$=$1+$3;}| add_expr '-' mul_expr {$$=$1-$3;};


最后为:

assign: letter '=' add_expr {reg[$1]=$3;};


到现在为些已经完成了算术表达式的编写,下面我给出整个源程序

%{#include<stdio.h>#include<ctype.h>int reg[26];%}%start list%token digit  letter%%list: list start '\n' | list error '\n' | start '\n';start: expr {printf("result: %d\n\n",$1);}| assign;number:number digit {$$=$1*10+$2;}  |digit ;primary_expr: '(' expr ')' {$$=$2;}| number| letter {$$=reg[$1];};unary_expr: primary_expr   | '-' primary_expr {$$=-$2;}  ;mul_expr:unary_expr {$$=$1;}| mul_expr '*' unary_expr {$$=$1*$3;}| mul_expr '/' unary_expr {$$=$1/$3;};add_expr:mul_expr {$$=$1;}| add_expr '+' mul_expr {$$=$1+$3;}| add_expr '-' mul_expr {$$=$1-$3;};assign: letter '=' add_expr {reg[$1]=$3;};expr: add_expr ;%%int yylex(){int ch=' ';while(isspace(ch)&&ch!='\n') ch=fgetc(stdin);if(isdigit(ch)){yylval=ch-'0';return digit;}if(isalpha(ch)){yylval=ch-'a';return letter;}return ch;}int main(){return yyparse();}int yyerror(char* s){fprintf(stderr,"%s\n",s);}



运行结果


这一章的代码可以在tutorial/syntax/simple_cal中找到


返回文档首页












原创粉丝点击