/************************************************************************* * * 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 ["<