创建一门新的编程语言-Flex&Bison教程-(3)-更实用的小计算器

本来想在这一节进入语法树的学习,然后顺势说完如何转换成汇编,真正做一个真正的编译器
但是呢。。。这个星期事务繁多,要到周末才真正有空,所以这一节还是简单介绍一些不用语法树的简单应用,下次更新可能要等到周末了
此外,我也想找点时间说说关于错误处理和提示等方面的东西,所以说这个教程还有很长的路


支持变量和简单判断的计算器
上一节我们已经实现了一个十分简易的计算器,但是要能说的上实用,还差一些功能
我们计划加入:
简单的变量,用set 变量名 = ...的语法
简单的判断,仿照c语言的a 那好,我们开始设计test3yy.y

%{
#include 
int yylex();
int yyerror(char *);
using namespace std;
float vars[128]={0};
float last=0;
%}
%token  CHAR
%token SET ANS
%token  Number
%type  exp
%type  cond
%union
{
  char iv;
  float fv;
  char cv;
}
%left '<' '>' '='
%left '+' '-'
%left '*' '/'
%left '?' ':'
%right '(' ')'
%%
program:
        program exp '\n' { cout << "Result: " << $2 << endl; last = $2; }
        | program stat '\n'
        | 
        ;
        
stat   :
        SET CHAR '=' exp { vars[$2] = $4; }


cond   :
        exp '<' exp     { $1<$3?$$=1:$$=0; }
        | exp '>' exp     { $1>$3?$$=1:$$=0; }
        | exp '<' '=' exp { $1<=$4?$$=1:$$=0; }
        | exp '>' '=' exp { $1>=$4?$$=1:$$=0; }
        | exp '=' exp     { $1==$3?$$=1:$$=0; }
        
exp    :
        Number        { $$ = $1; }
        | ANS          { $$ = last; }
        | CHAR         { $$ = vars[$1]; }
        | exp '+' exp  { $$ = $1 + $3; }
        | exp '-' exp  { $$ = $1 - $3; }
        | '(' exp ')'  { $$ = $2; }
        | exp '*' exp  { $$ = $1 * $3; }
        | exp '/' exp  { $$ = $1 / $3; }
        | cond '?' exp ':' exp { $1?$$=$3:$$=$5; }
        ;
%%
int yyerror(char *s)
{
  cout<



这里我们在主表达式设置了两种非空情况,其实就是要么是计算要么是变量赋值
在变量方面,为了图方便,所以我设定变量只能是一个字符,如果读者有兴趣可以做成更高级的
为了支持ans功能,我们用了一个last变量来保存最后计算出来的值
其他也没什么可说的了,我们来看test3ll.l


%{
  #include 
  #include "test3yy.h"
  int yyerror(char *);
%}


%%
[0-9]+        {
                yylval.fv = strtod(yytext,0);
                return Number;
              }
              
[0-9]+\.[0-9]+ {
                 yylval.fv = strtod(yytext,0);
                 return Number;
               }
               
[-+()?:<>=/*\n]      { return *yytext; }


[ \t]          ;


[a-zA-Z]          { yylval.cv = *yytext;
                 return CHAR;
               }


"set"          { return SET; }
"ans"          { return ANS; }               
%%


int yywrap()
{
	return 1;
}



这里返回了所需的两个符号 set和ans


照常按照上节方法编译,可以看到运行完美


(3)-更实用的小计算器 结束

你可能感兴趣的:(Flex&Bison教程)