Back to index

salome-med  6.5.0
SPythonInterpreter.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #include "SPythonInterpreter.hxx"
00021 #include "SPythonParser.hxx"
00022 
00023 #include <vector>
00024 #include <sstream>
00025 #include <algorithm>
00026 
00027 using namespace ParaMEDMEM;
00028 
00029 const char *SPythonInterpreter::INDENT_TOKEN[]={"def","class","for","if","while","try","except"};
00030 
00031 const char SPythonInterpreter::NUMBERS[]="0123456789";
00032 
00033 SPythonInterpreter::SPythonInterpreter(PyObject *globals, PyObject *locals):_indent_must_change(false),_glob(globals),_loc(locals)
00034 {
00035   _indent_pos.insert(0);
00036 }
00037 
00038 void SPythonInterpreter::initialize()
00039 {
00040   _indent_pos.clear();
00041   _indent_pos.insert(0);
00042   _indent_must_change=false;
00043   _cmd.clear();
00044 }
00045 
00046 bool SPythonInterpreter::run(const char *str, bool& isSPython)
00047 {
00048   isSPython=false;
00049   std::string s(str);
00050   if(s.empty())
00051     {
00052       finishSession();
00053       _indent_must_change=false;
00054       return true;
00055     }
00056   std::size_t pos=s.find_first_not_of(' ');
00057   if(pos==std::string::npos)
00058     return false;
00059   if(s[pos]=='#')
00060     return false;
00061   if(!checkIndentCoherency(s,pos))
00062     return true;
00063   if(!isIndenter(s,pos))
00064     {
00065       _indent_must_change=false;
00066       if(pos==0)
00067         {
00068           if(isSPythonExpression(s))
00069             {
00070               isSPython=true;
00071               return true;
00072             }
00073           else
00074             {
00075               _cmd+=s;
00076               _cmd+="\n";
00077               return finishSession();
00078             }
00079         }
00080       _cmd+=s;
00081       _cmd+="\n";
00082       return false;
00083     }
00084   else
00085     {
00086       _indent_must_change=true;
00087       _cmd+=s;
00088       _cmd+="\n";
00089       return false;
00090     }
00091 }
00092 
00093 bool SPythonInterpreter::finishSession()
00094 {
00095   PyObject *res=0;
00096   if(_cmd.empty())
00097     return false;
00098   res=PyRun_String(_cmd.c_str(),Py_file_input,_glob,_loc);
00099   _cmd.clear();
00100   checkPythonInterp(res);
00101   //_indent_pos.clear();
00102   //_indent_pos.insert(0);
00103   return true;
00104 }
00105 
00106 void SPythonInterpreter::checkPythonInterp(PyObject *r)
00107 {
00108   if(!r)
00109     PyErr_Print();
00110 }
00111 
00112 bool SPythonInterpreter::checkIndentCoherency(const std::string& s, std::size_t p)
00113 {
00114   if(!_indent_must_change)
00115     {
00116       if(_indent_pos.find(p)!=_indent_pos.end())
00117         {
00118           std::set<int>::iterator it=_indent_pos.begin();
00119           bool found=false;
00120           for(;it!=_indent_pos.end() && !found;it++)
00121             if(*it==(int)p)
00122               found=true;
00123           if(found)
00124             _indent_pos.erase(it,_indent_pos.end());
00125           return true;
00126         }
00127       else
00128         {//let python doing the job of error msg !
00129           _cmd+=s;
00130           finishSession();
00131           _indent_pos.clear();
00132           return true;
00133         }
00134     }
00135   else
00136     {
00137       if((int)p>*_indent_pos.rbegin())
00138         {
00139           _indent_pos.insert(p);
00140           return true;
00141         }
00142       else
00143         {//let python doing the job of error msg !
00144           _cmd+=s;
00145           finishSession();
00146           _indent_pos.clear();
00147           return true;
00148         }
00149     }
00150 }
00151 
00155 bool SPythonInterpreter::isIndenter(const std::string& s, std::size_t p)
00156 {
00157   std::string s1=s.substr(p);
00158   for(int i=0;i<NB_OF_INDENT;i++)
00159     {
00160       std::string elt(INDENT_TOKEN[i]);
00161       std::size_t sz=elt.length();
00162       if(s1.length()>=sz)
00163         if(s1.substr(0,sz)==elt)
00164           return true;
00165     }
00166   return false;
00167 }
00168 
00169 std::string SPythonInterpreter::strip(const std::string& s)
00170 {
00171   std::size_t sz=s.length();
00172   std::size_t n1=std::count(s.c_str(),s.c_str()+sz,' ');
00173   std::size_t n2=std::count(s.c_str(),s.c_str()+sz,'\n');
00174   std::size_t n3=std::count(s.c_str(),s.c_str()+sz,'\t');
00175   std::string ret(sz-n1-n2-n3,'$');
00176   std::size_t i=0,j=0;
00177   for(;i!=std::string::npos;)
00178     {
00179       i=s.find_first_not_of(" \n\t",i);
00180       if(i!=std::string::npos)
00181         ret[j++]=s[i++];
00182     }
00183   return ret;
00184 }
00185 
00186 bool SPythonInterpreter::isSPythonExpression(const std::string& s)
00187 {
00188   std::string w(s);
00189   if(w.find("import ")!=std::string::npos)
00190     return false;
00191   if(w.find_first_of('@')!=std::string::npos)
00192     return false;
00193   if(w.find("del ")!=std::string::npos)
00194     return false;
00195   const char PRINT[]="print ";
00196   bool isPrint=w.find(PRINT)!=std::string::npos;
00197   if(isPrint)
00198     {
00199       std::size_t p=w.find(PRINT);
00200       w=w.substr(p+sizeof(PRINT)-1);
00201     }
00202   std::string result;
00203   if(!isSPythonExpressionLev1(w,result))
00204     return false;
00205   if(isPrint)
00206     result=std::string(PRINT)+result;
00207   _cmd+=result+"\n";
00208   finishSession();
00209   return true;
00210 }
00211 
00212 bool SPythonInterpreter::isSPythonExpressionLev1(const std::string& s, std::string& result)
00213 {
00214   std::string sst=strip(s);
00215   SPythonParserHL p(_glob,_loc);
00216   if(!p.parse(sst,result))
00217     return false;
00218   return true;
00219 }
00220 
00221 bool SPythonInterpreter::isCandidateParenthesis(const std::string& s, std::size_t p1, std::size_t& n)
00222 {
00223   std::size_t p2=s.find_first_of(')',p1);
00224   std::size_t p3=s.find_first_of('(',p1+1);
00225   if(p2!=std::string::npos && (p3==std::string::npos || (p3!=std::string::npos && p2<p3) ))
00226     {
00227       n=p2-p1;
00228       return true;
00229     }
00230   return false;
00231 }