/* Companion source code for "flex & bison", published by O'Reilly
* Media, ISBN 978-0-596-15597-1
* Copyright (c) 2009, Taughannock Networks. All rights reserved.
* See the README file for license conditions and contact info.
* $Header: /home/johnl/flnb/code/RCS/purecalcfuncs.c,v 2.2 2009/11/08 02:53:18 johnl Exp $
*/
/* helper functions for purecalc */
# include <stdio.h>
# include <stdlib.h>
# include <stdarg.h>
# include <string.h>
# include <math.h>
# include "purecalc.tab.h"
# include "purecalc.lex.h"
# include "purecalc.h"
/* symbol table */
/* hash a symbol */
static unsigned
symhash(char *sym)
{
unsigned int hash = 0;
unsigned c;
while(c = *sym++) hash = hash*9 ^ c;
return hash;
}
struct symbol *
lookup(struct pcdata *pp, char* sym)
{
struct symbol *sp = &(pp->symtab)[symhash(sym)%NHASH];
int scount = NHASH; /* how many have we looked at */
while(--scount >= 0) {
if(sp->name && !strcmp(sp->name, sym)) { return sp; }
if(!sp->name) { /* new entry */
sp->name = strdup(sym);
sp->value = 0;
sp->func = NULL;
sp->syms = NULL;
return sp;
}
if(++sp >= symtab+NHASH) sp = symtab; /* try the next entry */
}
yyerror(pp, "symbol table overflow\n");
abort(); /* tried them all, table is full */
}
struct ast *
newast(struct pcdata *pp, int nodetype, struct ast *l, struct ast *r)
{
struct ast *a = malloc(sizeof(struct ast));
if(!a) {
yyerror(pp, "out of space");
exit(0);
}
a->nodetype = nodetype;
a->l = l;
a->r = r;
return a;
}
struct ast *
newnum(struct pcdata *pp, double d)
{
struct numval *a = malloc(sizeof(struct numval));
if(!a) {
yyerror(pp, "out of space");
exit(0);
}
a->nodetype = 'K';
a->number = d;
return (struct ast *)a;
}
struct ast *
newcmp(struct pcdata *pp, int cmptype, struct ast *l, struct ast *r)
{
struct ast *a = malloc(sizeof(struct ast));
if(!a) {
yyerror(pp, "out of space");
exit(0);
}
a->nodetype = '0' + cmptype;
a->l = l;
a->r = r;
return a;
}
struct ast *
newfunc(struct pcdata *pp, int functype, struct ast *l)
{
struct fncall *a = malloc(sizeof(struct fncall));
if(!a) {
yyerror(pp, "out of space");
exit(0);
}
a->nodetype = 'F';
a->l = l;
a->functype = functype;
return (struct ast *)a;
}
struct ast *
newcall(struct pcdata *pp, struct symbol *s, struct ast *l)
{
struct ufncall *a = malloc(sizeof(struct ufncall));
if(!a) {
yyerror(pp, "out of space");
exit(0);
}
a->nodetype = 'C';
a->l = l;
a->s = s;
return (struct ast *)a;
}
struct ast *
newref(struct pcdata *pp, struct symbol *s)
{
struct symref *a = malloc(sizeof(struct symref));
if(!a) {
yyerror(pp, "out of space");
exit(0);
}
a->nodetype = 'N';
a->s = s;
return (struct ast *)a;
}
struct ast *
newasgn(struct pcdata *pp, struct symbol *s, struct ast *v)
{
struct symasgn *a = malloc(sizeof(struct symasgn));
if(!a) {
yyerror(pp, "out of space");
exit(0);
}
a->nodetype = '=';
a->s = s;
a->v = v;
return (struct ast *)a;
}
struct ast *
newflow(struct pcdata *pp, int nodetype, struct ast *cond, struct ast *tl, struct ast *el)
{
struct flow *a = malloc(sizeof(struct flow));
if(!a) {
yyerror(pp, "out of space");
exit(0);
}
a->nodetype = nodetype;
a->cond = cond;
a->tl = tl;
a->el = el;
return (struct ast *)a;
}
struct symlist *
newsymlist(struct pcdata *pp, struct symbol *sym, struct symlist *next)
{
struct symlist *sl = malloc(sizeof(struct symlist));
if(!sl) {
yyerror(pp, "out of space");
exit(0);
}
sl->sym = sym;
sl->next = next;
return sl;
}
void
symlistfree(struct pcdata *pp, struct symlist *sl)
{
struct symlist *nsl;
while(sl) {
nsl = sl->next;
free(sl);
sl = nsl;
}
}
/* define a function */
void
dodef(struct pcdata *pp, struct symbol *name, struct symlist *syms, struct ast *func)
{
if(name->syms) symlistfree(pp, name->syms);
if(name->func) treefree(pp, name->func);
name->syms = syms;
name->func = func;
}
static double callbuiltin(struct pcdata *pp, struct fncall *);
static double calluser(struct pcdata *pp, struct ufncall *);
double
eval(struct pcdata *pp, struct ast *a)
{
double v;
if(!a) {
yyerror(pp, "internal error, null eval");
return 0.0;
}
switch(a->nodetype) {
/* constant */
case 'K': v = ((struct numval *)a)->number; break;
/* name reference */
case 'N': v = ((struct symref *)a)->s->value; break;
/* assignment */
case '=': v = ((struct symasgn *)a)->s->value =
eval(pp, ((struct symasgn *)a)->v); break;
/* expressions */
case '+': v = eval(pp, a->l) + eval(pp, a->r); break;
case '-': v = eval(pp, a->l) - eval(pp, a->r); break;
case '*': v = eval(pp, a->l) * eval(pp, a->r); break;
case '/': v = eval(pp, a->l) / eval(pp, a->r); break;
case '|': v = fabs(eval(pp, a->l)); break;
case 'M': v = -eval(pp, a->l); break;
/* comparisons */
case '1': v = (eval(pp, a->l) > eval(pp, a->r))? 1 : 0; break;
case '2': v = (eval(pp, a->l) < eval(pp, a->r))? 1 : 0; break;
case '3': v = (eval(pp, a->l) != eval(pp, a->r))? 1 : 0; break;
case '4': v = (eval(pp, a->l) == eval(pp, a->r))? 1 : 0; break;
case '5': v = (eval(pp, a->l) >= eval(pp, a->r))? 1 : 0; break;
case '6': v = (eval(pp, a->l) <= eval(pp, a->r))? 1 : 0; break;
/* control flow */
/* null if/else/do expressions allowed in the grammar, so check for them */
case 'I':
if( eval(pp, ((struct flow *)a)->cond) != 0) {
if( ((struct flow *)a)->tl) {
v = eval(pp, ((struct flow *)a)->tl);
} else
v = 0.0; /* a default value */
} else {
if( ((struct flow *)a)->el) {
v = eval(pp, ((struct flow *)a)->el);
} else
v = 0.0; /* a default value */
}
break;
case 'W':
v = 0.0; /* a default value */
if( ((struct flow *)a)->tl) {
while( eval(pp, ((struct flow *)a)->cond) != 0)
v = eval(pp, ((struct flow *)a)->tl);
}
break; /* last value is value */
case 'L': eval(pp, a->l); v = eval(pp, a->r); break;
case 'F': v = callbuiltin(pp, (struct fncall *)a); break;
case 'C': v = calluser(pp, (struct ufncall *)a); break;
default: printf("internal error: bad node %c\n", a->nodetype);
}
return v;
}
static double
callbuiltin(struct pcdata *pp, struct fncall *f)
{
enum bifs functype = f->functype;
double v = eval(pp, f->l);
switch(functype) {
case B_sqrt:
return sqrt(v);
case B_exp:
return exp(v);
case B_log:
return log(v);
case B_print:
printf("= %4.4g\n", v);
return v;
default:
yyerror(pp, "Unknown built-in function %d", functype);
return 0.0;
}
}
static double
calluser(struct pcdata *pp, struct ufncall *f)
{
struct symbol *fn = f->s; /* function name */
struct symlist *sl; /* dummy arguments */
struct ast *args = f->l; /* actual arguments */
double *oldval, *newval; /* saved arg values */
double v;
int nargs;
int i;
if(!fn->func) {
yyerror(pp, "call to undefined function", fn->name);
return 0;
}
/* count the arguments */
sl = fn->syms;
for(nargs = 0; sl; sl = sl->next)
nargs++;
/* prepare to save them */
oldval = (double *)malloc(nargs * sizeof(double));
newval = (double *)malloc(nargs * sizeof(double));
if(!oldval || !newval) {
yyerror(pp, "Out of space in %s", fn->name); return 0.0;
}
/* evaluate the arguments */
for(i = 0; i < nargs; i++) {
if(!args) {
yyerror(pp, "too few args in call to %s", fn->name);
free(oldval); free(newval);
return 0;
}
if(args->nodetype == 'L') { /* if this is a list node */
newval[i] = eval(pp, args->l);
args = args->r;
} else { /* if it's the end of the list */
newval[i] = eval(pp, args);
args = NULL;
}
}
/* save old values of dummies, assign new ones */
sl = fn->syms;
for(i = 0; i < nargs; i++) {
struct symbol *s
flex与bison源代码
需积分: 5 109 浏览量
2023-05-28
10:49:35
上传
评论
收藏 65KB ZIP 举报
cuimaoqian
- 粉丝: 3
- 资源: 14
最新资源
- 南京邮电大学数学实验:熟练掌握 Matlab 软件的基本命令和操作
- 2017校招真题校园招聘真题算法题(37道)Python源码.zip
- 基于单片机protues仿真的多功能自动饮水机系统设计(仿真图、源代码、演示视频)
- 二叉树7-1-1.cpp
- android 9.0 原生模拟器 签名文件
- 技术面试最后反问面试官的话 校招面试非技术问题有哪些 非技术问题如何回答.png
- NB-IOT-BC26全网通模块Altium+ CADENCE +PADS三种格式(原理图SCH+PCB封装库)文件.zip
- 基于微信小程序开发的校园失物招领系统源码毕业设计(优质项目源码).zip
- 词向量是一种将自然语言中的单词转换为数值向量的技术,它能够捕捉词义和上下文信息
- nmap与masscan的简单使用
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈