时间:2021-05-20
下面完成一个简单的计算器通过语法树进行计算,首先定义一个语法树的结构,然后编写flex文件,解析数字或符号,对于 符号返回本身,对于数字,返回NUMBER,并对yylval的d进行赋值,yylval指向一个联合类型,接着,在语法分析器中完成语法树的节点的增加,分别对应数字和符号有不同的增加方式,最后有一个单独的C代码处理计算,以及语法树相关计算的函数。对结果的计算的方式是对语法树进行递归。
词法分析器为:
dp@dp:~/flexbison % cat myast.l%option noyywrap nodefault yylineno%{#include "myast.h"#include "myast.tab.h"char buffer[20];%}EXP ([Ee][-+]?[0-9]+)%%"+"|"-"|"*"|"/"|"("|")"|"|" {return yytext[0];}[0-9]+"."[0-9]*{EXP}?|"."?[0-9]+{EXP}? {yylval.d=atof(yytext);return NUMBER;}\n {return EOL;}"//".*[ \t] {}"Q" {exit(0);}. {sprintf(buffer,"invalid character %c\n",*yytext); yyerror(buffer);} %%语法分析器为:
dp@dp:~/flexbison % cat myast.y%{#include <stdio.h>#include <stdlib.h>#include "myast.h"%}%union{struct myast *mya;double d;}%token <d> NUMBER%token EOL%type <mya> exp factor term%%calclist:|calclist exp EOL{printf("= %g\n",eval($2));treefree($2);printf("$");}|calclist EOL{printf("$");};exp:factor|exp '+' factor {$$=newast('+',$1,$3);} |exp '-' factor{$$=newast('-',$1,$3);};factor:term |factor '*' term {$$=newast('*',$1,$3);} |factor '/' term {$$=newast('/',$1,$3);};term:NUMBER{$$=newnum($1);}|'|' term{$$=newast('|',$2,NULL);}|'(' exp ')' {$$=$2;} |'-' term {$$=newast('M',$2,NULL);};%%然后头文件 为:
dp@dp:~/flexbison % cat myast.hextern int yylineno;void yyerror(char *s);struct ast{int nodetype;struct ast *l;struct ast *r;};struct numval{int nodetype;double number;};struct ast *newast(int nodetype,struct ast *l,struct ast *r);struct ast *newnum(double d);double eval(struct ast *);void treefree(struct ast *);C代码文件的内容为:
dp@dp:~/flexbison % cat myastfunc.c#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include "myast.h"struct ast * newast(int nodetype,struct ast *l,struct ast *r){struct ast *a=malloc(sizeof(struct ast));if (!a){yyerror("out of space");exit(0);}a->nodetype=nodetype;a->l=l;a->r=r;return a;}struct ast * newnum(double d){struct numval *a=malloc(sizeof(struct numval));if (!a){yyerror("out of space");exit(0);}a->nodetype='D';a->number=d;return (struct ast *)a;}double eval(struct ast *a){double v; switch(a->nodetype){case 'D':v=((struct numval *)a)->number;break;case '+':v=eval(a->l)+eval(a->r);break;case '-':v=eval(a->l)-eval(a->r);break;case '*':v=eval(a->l)*eval(a->r);break;case '/':v=eval(a->l)/eval(a->r);break;case '|':v=eval(a->l);v=v<0?v:-v;break;case 'M':v=-eval(a->l);break; defaut:printf("bad node:%c\n",a->nodetype); } return v;}void treefree(struct ast*a){switch(a->nodetype){case '+':case '-':case '*':case '/':treefree(a->r);case '|':case 'M':treefree(a->l);case 'D':free(a);break;default:printf("free bad node %c\n",a->nodetype);}}void yyerror(char *s){fprintf(stderr,"line %d error!:%s",yylineno,s);}int main(){printf("$ ");return yyparse();}Makefile文件为:
dp@dp:~/flexbison % cat makefilemyjs:myast.l myast.y myast.h bison -d myast.yflex -omyast.lex.c myast.lcc -o $@ myast.tab.c myast.lex.c myastfunc.cdp@dp:~/flexbison %运行效果如下
dp@dp:~/flexbison % ./myjs$ 12+99= 111$11*(9-3)+6/3= 68$Qdp@dp:~/flexbison %声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
C++基础教程之指针拷贝详解指针是编程人员的梦魇,对C语言的开发者是如此,对C++的开发者也是如此。特别是在C++中,如果不注意处理类中的指针,非常容易出问题。
以c语言为例,其指针是C语言中的一个重要概念及其特点,也是掌握C语言比较困难的部分。指针也就是内存地址,指针变量是用来存放内存地址的变量,不同类型的指针变量所占
在实现自己的call,apply,bind前,需要复习一下this.所谓的this其实可以理解成一根指针:其实this的指向,始终坚持一个原理:this永远指向
前言C++中使用class语法实现回调(当然,,旧式的C函数指针回调也是支持的)比如,有人提供一个类库AfCopyFile,能够提供文件拷贝的功能,而且能通知用
0.前言前文【二叉树的概念和原理】主要介绍了树的相关概念和原理,本文主要内容为二叉树的创建及遍历的代码实现,其中包括递归遍历和栈遍历。1.二叉树的实现思路1.0