日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C指针原理(27)-编译基本原理-语法树及其实现7

發(fā)布時(shí)間:2025/3/12 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C指针原理(27)-编译基本原理-语法树及其实现7 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

下面完成一個(gè)簡單的計(jì)算器通過語法樹進(jìn)行計(jì)算,首先定義一個(gè)語法樹的結(jié)構(gòu),然后編寫flex文件,解析數(shù)字或符號(hào),對于 符號(hào)返回本身,對于數(shù)字,返回NUMBER,并對yylval的d進(jìn)行賦值,yylval指向一個(gè)聯(lián)合類型,接著,在語法分析器中完成語法樹的節(jié)點(diǎn)的增加,分別對應(yīng)數(shù)字和符號(hào)有不同的增加方式,最后有一個(gè)單獨(dú)的C代碼處理計(jì)算,以及語法樹相關(guān)計(jì)算的函數(shù)。對結(jié)果的計(jì)算的方式是對語法樹進(jìn)行遞歸。

詞法分析器為:

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代碼文件的內(nèi)容為: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();} Make

file文件為:

dp@dp:~/flexbison % cat makefile

myjs:myast.l myast.y myast.h

bison -d myast.y

flex -omyast.lex.c myast.l

cc -o $@ myast.tab.c myast.lex.c myastfunc.c

dp@dp:~/flexbison %
運(yùn)行效果如下

dp@dp:~/flexbison % ./myjs

$ 12+99

= 111

$11*(9-3)+6/3

= 68

$Q

dp@dp:~/flexbison %

總結(jié)

以上是生活随笔為你收集整理的C指针原理(27)-编译基本原理-语法树及其实现7的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。