⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfcalc.y

📁 Linux/windows 环境下跨平台开发程序
💻 Y
📖 第 1 页 / 共 4 页
字号:
%{/* mfcalc.y, mfcalc.cpp, Copyright (c) 2004, 2005 R.Lackner parse string and simple math: based on the bison 'mfcalc' example    This file is part of RLPlot.    RLPlot is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    RLPlot is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with RLPlot; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include <math.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include <stdio.h>#include "rlplot.h"class symrec {public:	int type, row, col;	unsigned int h_name;	char *name, *text;	double (*fnctptr)(...);	symrec *next;	double var;	symrec(unsigned int h_n, int typ, symrec *nxt);	~symrec();	double GetValue();	void GetValue(void *res);	double SetValue(double v);        void SetValue(void* dest, void* src);	void SetName(char *nam);	void InitSS();private:	bool isSSval;};// syntactical informationstruct syntax_info {	int last_tok;			//resolve ambiguous ':'	double clval;			//current value for where - clause	int cl1, cl2;			//limits of clause formula in buffer	struct syntax_info *next;	};static syntax_info *syntax_level = 0L;typedef struct{	double  val;	int type;	symrec  *tptr;	double *a_data;	char *text;	int a_count;}YYSTYPE;static symrec *putsym (unsigned int h_name, int sym_type);static symrec *getsym (unsigned int h_name, char *sym_name = 0L);static int push(YYSTYPE *res, YYSTYPE *val);static void store_res(YYSTYPE *res);static char *PushString(char *text);static char *add_strings(char *st1, char *st2);static char *string_value(YYSTYPE *exp);static double eval(YYSTYPE *sr, YYSTYPE *dst);static int range_array(YYSTYPE * res, char *range);static void exec_clause(YYSTYPE *res);static YYSTYPE *proc_clause(YYSTYPE *res);static void yyerror(char *s);static int yylex(void);static double nop() {return 0.0;};static char res_txt[1000];static anyResult line_res = {ET_UNKNOWN, 0.0, res_txt};static DataObj *curr_data;static char *last_error = 0L;		//error textstatic char *last_err_desc = 0L;	//short error descriptionstatic char *buffer = 0L;		//the current command bufferstatic int buff_pos = 0;static bool bRecent = false;		//rearrange functionsstatic int parse_level = 0;		//count reentrances into parser#define MAX_PARSE 20			//maximum number of reentances %}%token <val>  NUM STR ARR BLOCK PI E CLVAL PSEP IF ELSE%token <tptr> VAR FNCT AFNCT SFNCT FUNC2 TXT%type  <val>  exp str_exp arr%right  '='%left	','			/* list separator */%left	CLAUSE			/* clause (where) operator */%left	SER%right	COLR COLC		/* range sep., conditional sep. */%right	'?'			/* conditional assignment */%left	AND OR%left   EQ NE GT GE LT LE%left   '-' '+'%left   '*' '/'%left   NEG 		/* negation-unary minus */%left	INC DEC		/* increment, decrement */%left	PINC PDEC	/* pre- increment, decrement */%right  '^'	 	/* exponentiation       *//* Grammar follows */%%input:    /* empty string */	| input line;line:	 '\n' | ';' | ','	| exp '\n'		{store_res(&yyvsp[-1]); return 0;}	| exp ';'		{store_res(&yyvsp[-1]); return 0;}	| exp ','		{store_res(&yyvsp[-1]); return 0;}	| str_exp '\n'		{store_res(&yyvsp[-1]); return 0;}	| str_exp ';'		{store_res(&yyvsp[-1]); return 0;}	| error '\n'		{yyerrok;};str_exp:	STR			{;}	|str_exp '+' exp	{yyval.text=add_strings(yyvsp[-2].text, string_value(&yyvsp[0]));}	|exp '+' str_exp	{yyval.text=add_strings(string_value(&yyvsp[-2]), yyvsp[0].text);}	|str_exp '+' str_exp	{yyval.text=add_strings(yyvsp[-2].text, yyvsp[0].text);};range:	str_exp			{;}		|VAR COLR VAR		{if(yyval.text =(char*)malloc(strlen($1->name) +strlen($3->name) + 2)) sprintf(yyval.text, "%s:%s", $1->name, $3->name);};arr:	ARR	|exp			{if(!yyval.a_data) {yyval.a_data = (double*)malloc(sizeof(double)); yyval.a_count = 1; yyval.a_data[0] = yyval.val;}}	|arr ',' arr		{push(&yyval, &yyvsp[0]);}	|arr CLAUSE exp		{exec_clause(&yyval);} 	|range			{range_array(&yyval, yyvsp[0].text);}	|NUM SER NUM		{if($1 < $3 && (yyval.a_data = (double*)malloc((int)($3-$1+2)*sizeof(double))))					for(yyval.a_count=0; $1<=$3; yyval.a_data[yyval.a_count++] = $1, $1 += 1.0 );};exp:	NUM				{$$ = $1; yyval.type = NUM;}        |TXT				{$$ = 0.0;}	|CLVAL				{$$ = syntax_level ? syntax_level->clval : 0.0; }	|PI				{$$ = _PI; yyval.type = NUM;}	|E				{$$ = 2.71828182845905; yyval.type = NUM;}	|VAR				{$1->GetValue(&yyval);}	|BLOCK			{eval(&yyvsp[0], &yyval);}	|VAR '=' exp		{$1->SetValue(&yyval, &yyvsp[0]);}	|VAR '=' str_exp	{$1->SetValue(&yyval, &yyvsp[0]);}	|FNCT '(' exp ')'	{$$ = (($1->fnctptr)($3));}	|AFNCT '(' arr ')'	{$$ = (($1->fnctptr)(proc_clause(&yyvsp[-1])));}	|AFNCT '(' exp PSEP exp ')' {push(&yyvsp[-2], &yyvsp[0]); $$ = (($1->fnctptr)(&yyvsp[-2]));}	|AFNCT '(' exp PSEP exp PSEP exp ')' {push(&yyvsp[-4], &yyvsp[-2]); push(&yyvsp[-4], &yyvsp[0]); $$ = (($1->fnctptr)(&yyvsp[-4]));}	|SFNCT '(' str_exp ')'	{$$ = (($1->fnctptr)(&yyvsp[-1], &yyval));}	|SFNCT '(' exp ')'	{yyvsp[-1].text = string_value(&yyvsp[-1]); $$ = (($1->fnctptr)(&yyvsp[-1], &yyval));}	|FUNC2 '(' arr PSEP arr ')'	{$$ = ((*$1->fnctptr)(proc_clause(&yyvsp[-3]), proc_clause(&yyvsp[-1]), 0L));}	|FUNC2 '(' arr PSEP arr PSEP range')'				{$$ = ((*$1->fnctptr)(proc_clause(&yyvsp[-5]), proc_clause(&yyvsp[-3]), yyvsp[-1].text));}	|IF '(' exp ')' BLOCK	{$$ = $3 != 0 ? eval(&yyvsp[0], &yyval) : 0.0;}	|IF '(' exp ')' BLOCK ELSE BLOCK	{$$ = $3 != 0 ? eval(&yyvsp[-2], &yyval) : eval(&yyvsp[0], &yyval);}	|exp AND exp		{$$ = (($1 != 0) && ($3 != 0))? 1 : 0;}	|exp OR exp		{$$ = (($1 != 0) || ($3 != 0))? 1 : 0;}	|exp EQ exp		{$$ = ($1 == $3) ? 1 : 0;}	|exp NE exp		{$$ = ($1 != $3) ? 1 : 0;}	|exp GT exp		{$$ = ($1 > $3) ? 1 : 0;}	|exp GE exp		{$$ = ($1 >= $3) ? 1 : 0;}	|exp LT exp		{$$ = ($1 < $3) ? 1 : 0;}	|exp LE exp		{$$ = ($1 <= $3) ? 1 : 0;}	|exp '+' exp		{$$ = $1 + $3;}	|exp '-' exp		{$$ = $1 - $3;}	|exp '*' exp		{$$ = $1 * $3;}	|exp '/' exp		{if($3 != 0.0) $$ = $1 / $3;					else $$ = (getsym(HashValue((unsigned char*)"zdiv")))->GetValue(); }	|'-' exp  %prec NEG	{$$ = -$2;}	|VAR INC		{$$=$1->GetValue(); $1->SetValue($$+1.0); $$ -= 1.0; yyval.type = NUM;}	|VAR DEC		{$$=$1->GetValue(); $1->SetValue($$-1.0); $$ += 1.0; yyval.type = NUM;}	|INC VAR %prec PINC	{$$=$2->GetValue(); $2->SetValue($$+1.0); yyval.type = NUM;}	|DEC VAR %prec PDEC	{$$=$2->GetValue(); $2->SetValue($$-1.0); yyval.type = NUM;}	|exp '^' exp		{$$ = pow($1, $3);}	|'(' arr ')'		{memcpy(&yyval, &yyvsp[-1], sizeof(YYSTYPE)); yyvsp[-1].a_data = 0L; yyvsp[-1].a_count = 0;}	|exp '?' exp COLC exp	{memcpy(&yyval, $1 != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE))}	|exp '?' STR COLC STR	{memcpy(&yyval, $1 != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE))}	|exp '?' STR COLC exp	{memcpy(&yyval, $1 != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE))}	|exp '?' exp COLC STR	{memcpy(&yyval, $1 != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE))};%%// The symrec classsymrec::symrec(unsigned int h_n, int typ, symrec *nxt) {	h_name = h_n;	type = typ;	next = nxt;	row = col = -1;	name = text = 0L;	var = 0.0;	isSSval = false;	fnctptr = (double (*)(...))nop;}symrec::~symrec(){	if(name) free(name);	name = 0L;	if(text) free(text);	text = 0L;}doublesymrec::GetValue(){	anyResult ares;	if(isSSval) {		if(row < 0 && col < 0) InitSS();		//GetResult( , , ,true) inhibits reentrance into parser !		if(curr_data->GetResult(&ares, row, col, parse_level > MAX_PARSE)){			return var = ares.value;			}		isSSval = false;		row = col = -1;		}	return var;}voidsymrec::GetValue(void *re){	anyResult ares;	YYSTYPE *res = (YYSTYPE*)re;	if(isSSval) {		if(row < 0 && col < 0) InitSS();		res->a_data = 0L;	res->a_count = 0;		//GetResult( , , ,true) inhibits reentrance into parser !		if(curr_data->GetResult(&ares, row, col, parse_level > MAX_PARSE)){			if(text) free(text);		text = 0L;			if(ares.type == ET_VALUE) {				res->type = VAR;	res->val = ares.value;				res->text = 0L;				}			else if(ares.type == ET_TEXT && ares.text) {				res->type = STR;	res->val = 0.0;				text = strdup(ares.text);				res->text = text;				}			else {				res->type = NUM;	res->val = var;				res->text = 0L;				}			var = res->val;			return;			}		isSSval = false;		row = col = -1;		}	if(text && text[0]) {		res->text = strdup(text);		res->val = var;		res->type = STR;		}	else {		res->type = NUM;	res->val = var;		res->text = 0L;		}	res->a_data = 0L;	res->a_count = 0L;}double symrec::SetValue(double v){	if(isSSval) {		if(row < 0 && col < 0) InitSS();		if(curr_data->SetValue(row, col, v)){			if(curr_data) curr_data->Command(CMD_UPDATE, 0L, 0L);			return var = v;			}		isSSval = false;		row = col = -1;		}	return var = v;}void symrec::SetValue(void* d, void* s){	YYSTYPE *dest = (YYSTYPE*)d;	YYSTYPE *src = (YYSTYPE*)s;	if(isSSval && curr_data) {		if(row < 0 && col < 0) InitSS();		if(last_err_desc) curr_data->SetText(row, col, last_err_desc);		else if(src->type == STR) curr_data->SetText(row, col, src->text);		else if(src->type == ARR || (src->a_data)) curr_data->SetText(row, col, "#ARRAY");		else if(src->type == VAR && src->tptr->type == TXT) curr_data->SetText(row, col, src->tptr->text);		else curr_data->SetValue(row, col, src->val);		curr_data->Command(CMD_UPDATE, 0L, 0L);		}	var = src->val;	if(text) free(text);		text = 0L;	if(src->text && src->text[0]) 	text = strdup(src->text);	GetValue(d);	return;}voidsymrec::SetName(char *nam){	if(name || !nam || !nam[0]) return;	name = strdup(nam);	if((name && curr_data) && (isalpha(name[0]) || name[0] == '$') && isdigit(name[strlen(name)-1])) isSSval=true;}voidsymrec::InitSS(){	AccRange *ar;	if(row<0 && col<0 &&(ar = new AccRange(name))) {		ar->GetFirst(&col, &row);		delete(ar);		}}static void yyerror(char *s){  	//called by yyparse on error	if(curr_data) curr_data->Command(CMD_ERROR, last_error = s, 0L);	else printf("%s\n", s);}static void yyargserr(char *s){	//call from function on argument type/number mismatch	yyerror(s);	last_err_desc = "#ARGS";}static void store_res(YYSTYPE *res){	if(last_err_desc) {		line_res.type = ET_TEXT;		line_res.value = 0.0;		strcpy(res_txt, last_err_desc);		}	else if(res->type == STR) {		line_res.type = ET_TEXT;		line_res.value = 0.0;		if(res->text) strcpy(res_txt, res->text);		}	else if((res->type == ARR || (res->a_data)) && res->a_count == 1) {		line_res.type = ET_VALUE;		line_res.value = res->a_data[0];		}	else if(res->type == ARR && !(res->a_data) && !(res->a_count)) {		line_res.type = ET_VALUE;		line_res.value = res->val;		}	else if(res->type == ARR || (res->a_data)) {		line_res.type = ET_TEXT;		line_res.value = 0.0;		strcpy(res_txt, "#ARRAY");		}	else if(res->tptr && res->tptr->type == TXT) {		line_res.type = ET_TEXT;		line_res.value = 0.0;		if(res->tptr->text) strcpy(res_txt, res->tptr->text);		}	else {		line_res.type = ET_VALUE;		line_res.value = res->val;		}}static char *add_strings(char *st1, char *st2){	char *newstr, *ret;	if(st1 && st2) {		if(newstr = (char*)malloc(strlen(st1) +strlen(st2) +4)) {			sprintf(newstr, "%s%s", st1, st2);			ret = PushString(newstr);			free(newstr);			return ret;			}		else return 0L;		}	if(st1) return st1;	if(st2) return st2;	return 0L;}static char *string_value(YYSTYPE *exp){	char *st1, tmp[50];	if(exp->type == STR){		st1 = exp->text;		}	else if(exp->tptr && exp->tptr->type == TXT) {		st1 = exp->tptr->text;		}	else {		sprintf(tmp,"%g", exp->val);		st1 = tmp;		}	return PushString(st1);}// store syntactical informationstatic void push_syntax(){	syntax_info *next;	if(!(next = (syntax_info*)calloc(1, sizeof(syntax_info)))) return;	if(syntax_level)memcpy(next, syntax_level, sizeof(syntax_info));	next->next=syntax_level;	syntax_level = next;}static void pop_syntax(){	syntax_info *si;	if(si = syntax_level) {		syntax_level = si->next;		free(si);		}}static double eval(YYSTYPE *sr, YYSTYPE *dst) {	anyResult *ar;	if(!sr || !sr->text) return 0.0;	parse_level++;	ar = do_formula(0L, sr->text);	yylval.a_data = 0L;	yylval.a_count = 0;	switch(ar->type) {	case ET_VALUE:		dst->type = NUM;		dst->val = ar->value;		dst->text = 0L;		break;	case ET_TEXT:		dst->type = STR;		dst->val = 0.0;		dst->text = PushString(ar->text);		break;	default:		dst->type = NUM;		dst->val = 0.0;		dst->text = 0L;		break;		}	parse_level--;	return dst->val;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -