From 5df79c53745fde5d6c3340a2979b1429cd5892c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 8 Oct 2011 20:30:28 +0200 Subject: Initial import of htcd system 1.0 Signed-off-by: Henrik Rydberg --- src/ops/express.cc | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 src/ops/express.cc (limited to 'src/ops/express.cc') diff --git a/src/ops/express.cc b/src/ops/express.cc new file mode 100644 index 0000000..2cd3114 --- /dev/null +++ b/src/ops/express.cc @@ -0,0 +1,173 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +const mstring sp_tag="SP"; + +//////////////////////////////////////////////////////////////// + +uniheap expr_t::tree; +void* expr_t::operator new(size_t n) { return tree.push(); } +void expr_t::operator delete(void* p) { tree.pop(p); } + +//////////////////////////////////////////////////////////////// + +inline int precedence(const expr_t* root,const op_t* op) +{ + if(!root->op) return 1; + else if(!op) return 0; + else if(root->left) { + if(root->right) return op->pre2&&root->op->pre2>=op->pre2; + else return root->op->pre2>=op->pre1; + } + else { + if(root->right) return op->pre2&&root->op->pre1>=op->pre2; + else return root->op->pre1>=op->pre1; + } +} + +static int ins_node_sp(expr_t*& root,op_env& env, + const sref& in,const op_t* op) throw(merror_t) +{ + if(root==0) { root=new expr_t(in,op); root->expand(env); return 1; } + else if(precedence(root,op)) { + if(op) { root=new expr_t(in,op,root); return 1; } else return 0; + } + else return ins_node_sp(root->right,env,in,op); +} + +static void ins_node(expr_t*& root,op_env& env,const sref& in) throw(merror_t) +{ + const op_t* op=env.ops->get(in); + if(!ins_node_sp(root,env,in,op)) { + if(!ins_node_sp(root,env,sp_tag,env.ops->get(sp_tag))) + THROW("ops: ("<expr<<" ["<trav(out,n-1); + for(int i=0;i<3*n;i++) out.put(' '); + out<<"["< "<trav(out,n-1); +} + +void expr_t::expand(op_env& env) throw(merror_t) +{ + if(!op) { + sref first,rest=expr; + env.split(first,rest); + if(first!=expr) { + do ins_node(right,env,first); + while(env.split(first,rest)); + } + } +} + +/////////////////////////////////////////////////////////////// + +void expr_t::eval(mstream& out,op_env& env,int opt) throw(merror_t) +{ + if(op) { + if(left) { + if(op->left>1) { + if(left->status&opt) { + swrite sw(left->result); + left->eval(sw,env,opt); + } + } + else if(!op->left) + THROW("ops: ("<expr<<" ["<op) + THROW("ops: (["<expr<<"] "<status=OP_LOCAL; + left->result=left->expr; + } + } + if(right) { + if(op->right>1) { + if(right->status&opt) { + swrite sw(right->result); + right->eval(sw,env,opt); + } + } + else if(!op->right) + THROW("ops: ("<expr<<" ["<op) + THROW("ops: (["<expr<<"] "<status=OP_LOCAL; + right->result=right->expr; + } + } + if(left) { + if(right) { + status=left->status|right->status; + if((status&OP_NINIT)==0) op->f2(out,env,left->result,right->result); + } + else if(!op->f1) + THROW("ops: ("<expr<<" "<status; + if((status&OP_NINIT)==0) op->f1(out,env,left->result); + } + } + else if(right) { + if(!op->f1) + THROW("ops: ([L] "<expr<<"): missing L argument") + else { + status=right->status; + if((status&OP_NINIT)==0) op->f1(out,env,right->result); + } + } + else THROW("ops: ["<eval(out,env,opt); + status=right->status; + } + else env.term(out,this); + } + if(status&OP_NINIT) THROW("ops: unfinished expression ["<