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

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


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

%{#include <iostream>int yylex();int yyerror(char *);using namespace std;float vars[128]={0};float last=0;%}%token <cv> CHAR%token SET ANS%token <fv> Number%type <fv> exp%type <iv> 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<<s<<endl;}int main(int argc,char **argv){  yyparse();}



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


%{  #include <stdlib.h>  #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)-更实用的小计算器 结束
原创粉丝点击