BioInfWeb - TreeGraph / Version 1 / Show File - tgf-parser.cc

TreeGraph subversion repository

sventon subversion web client - http://www.sventon.org
[show recent changes]
 
  Help
Rev: HEAD (2) - https://secure.bioinfweb.info/Code/svn/TreeGraph / trunk / main / tgf-parser.cc
Show File - tgf-parser.cc  [show properties]
spinner
/*
 tgf-parser.cc, part of
 treegraph
 Tree formatting program
 Generates vector graphics (SVG,EPS) from .tgf-tree description files.
10   Copyright (c) 2003-04 by Joern Mueller
11 
12 
13   This program is free software; you can redistribute it and/or
14   modify it under the terms of the GNU General Public License
15   as published by the Free Software Foundation; either version 2
16   of the License, or (at your option) any later version.
17 
18   This program is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21   GNU General Public License for more details.
22 
23   You should have received a copy of the GNU General Public License
24   along with this program (GPL.html); if not, write to the Free Software
25   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26   (also: http://www.gnu.org)
27  */
28 
29 
30 
31 
32 
33 
34 
35  #include "tgf-parser.h"
36  #include <cstdio>
37 
38 
39 
40 
41  parser::parser(std::istream& s1) : strom(s1), line(1)
42  {
43   bfresv=20;
44   bfsize=0;
45   buf=new char [bfresv];
46  }
47 
48  parser::~parser()
49  {
50   delete [] buf;
51  }
52 
53  void parser::unget(char ch){
54   if(bfsize+1>=bfresv){
55    bfresv+=10;
56    char *nb=new char[bfresv];
57    for(int i=0; i<bfsize; i++)
58     nb[i]=buf[i];
59    delete [] buf;
60    buf=nb;
61   }
62   buf[bfsize++]=ch;
63  };
64 
65  void parser::unget(const std::string& s){
66   if(bfsize+s.size()>=bfresv){
67    bfresv+=s.size()+10;
68    char *nb=new char[bfresv];
69    for(int i=0; i<bfsize; i++)
70     nb[i]=buf[i];
71    delete [] buf;
72    buf=nb;
73   }
74   for(int i=s.size()-1; i>=0; --i){
75    buf[bfsize+i]=s[s.size()-1-i];
76   }
77   bfsize+=s.size();
78  };
79 
80  float parser::readbracefloat(void)
81  // liest {<float>}
82  {
83   std::string s;
84   readbracestring(s);
85   float f;
86   if(std::sscanf(s.c_str(),"%f",&f)!=1){
87    std::cout << "Fehler: readbracefloat\n";
88    throw syntax(line);
89   }
90 
91   return f;
92 
93  }
94 
95  bool parser::skipbracestring(void)
96  //{<string>} ignorieren, wenn vorhanden
97  // true, wenn Klammer vorhanden war
98  {
99   skipspaces();
100   int ch=parser::get();
101   if(ch!='{'){
102    parser::unget(ch);
103    return false;
104   }
105   int bb=1;
106   while((ch=parser::get())!=EOF){
107    if(ch=='}') --bb;
108    else if(ch=='{') ++bb;
109    else if(ch=='\n'){
110     ++line;
111    }
112    if(bb==0) break;
113   }
114   if(bb>0){
115    std::cout << "Fehlende }\n";
116    throw syntax(line);
117   }
118   return true;
119  }
120 
121 
122  void parser::readbracestring(std::string& str)
123  //{<string>}
124  {
125   skipspaces();
126   int ch=parser::get();
127   if(ch!='{'){
128    std::cout << "Fehlende {\n";
129    throw syntax(line);
130   }
131   str="";
132   int bb=1;
133   while((ch=parser::get())!=EOF){
134    if(ch=='}') --bb;
135    else if(ch=='{') ++bb;
136    if(bb==0) break;
137    if(ch=='\n'){
138     ++line;
139     ch='\n';
140    } else if(ch=='\t') ch=' ';
141    str+=ch;
142   }
143   if(bb>0){
144    std::cout << "Fehlende }\n";
145    throw syntax(line);
146   }
147  }
148 
149 
150  void parser::readdefinition(void)
151  {
152   macro m;
153   readbracestring(m.mname);
154   if(m.mname[0]!='\\'){
155    std::cout << "Error: Macro name must start with '\\'\n";
156    throw syntax(line);
157   }
158   m.mname=m.mname.substr(1);
159   readbracestring(m.makro);
160 
161   m.nargs=0;
162   for(int i=0; i<m.makro.size(); i++){
163    char ch=m.makro[i];
164    if(ch=='#'){
165      int nn=m.makro[i+1]-'0';
166     ++i;
167     if(nn<0 || nn>9){
168      std::cout << "Error: # must be followed by decimal digit.\n";
169      throw syntax(line);
170     }
171     if(nn>m.nargs) m.nargs=nn;
172    }
173   }
174   insert_macro(m);
175  }
176 
177  void parser::readcommand(std::string& cmd)
178  //beginnt hinter '\' zu lesen
179  {
180   const int mwlen=20;
181   char wort[mwlen+1];
182   int i;
183   for(i=0; i<mwlen; i++){
184    int ch=parser::get();
185    if(isalnum(ch) || ch=='_' || ch=='*')
186     wort[i]=ch;
187    else {
188     parser::unget((char)ch);
189     break;
190    }
191   }
192   wort[i]=0;
193   cmd=wort;
194  }
195 
196  void parser::skipcomment(void)
197  //beginnt hinter '%' zu lesen
198  {
199   int ch;
200   do{
201    ch=parser::get();
202   } while(ch!='\n');
203   ++line;
204 
205  }
206 
207  void parser::skipspaces(void)
208  {
209   int ch;
210   do {
211    ch=parser::get();
212    if(ch=='\n'){
213     ++line;
214    } else if(ch!=EOF && !isspace(ch)){
215     parser::unget(ch);
216     ch=EOF;
217    }
218   } while(ch!=EOF);
219  }
220 
221 
222 
223  parser::ttoken parser::readnextword(std::string& s, float& f)
224  {
225   s="";
226   ttoken was=kErr;
227   int ch;
228   do {
229    skipspaces();
230    ch=parser::get();
231    switch(ch){
232    case '(': was=kOpenTree; break;
233    case ')': was=kCloseTree; break;
234    case ',': was=kNextTree; break;
235    case EOF: was=kEOF; break;
236    case '\\':
237     readcommand(s);
238     if((s[0]=='u' || s[0]=='d') && isdigit(s[1])){
239      if(s[0]=='u'){
240       ttoken w[4]={kTextU1,kTextU2,kTextU3,kTextU4};
241       was=w[s[1]-'0'-1];
242      } else {
243       ttoken w[4]={kTextD1,kTextD2,kTextD3,kTextD4};
244       was=w[s[1]-'0'-1];
245      }
246      readbracestring(s);
247     } else if(s=="r"){
248      readbracestring(s);
249      was=kTextR;
250     } else if(s=="len"){
251      f=readbracefloat();
252      was=kLength;
253     } else if(s=="label"){
254      readbracestring(s);
255      was=kLabel;
256     } else if(s=="prune"){
257      was=kPruned;
258     } else if(s=="min_length"){
259      was=kMinLength;
260      f=readbracefloat()*millimeter;
261     } else if(s=="space_above"){
262      was=kSpaceAbove;
263      f=readbracefloat()*millimeter;
264     } else if(s=="space_below"){
265      was=kSpaceBelow;
266      f=readbracefloat()*millimeter;
267     }
268     break;
269    case '"':
270     while((ch=parser::get())!='"')
271      s+=(char)ch;
272     was=kText;
273     break;
274    case '%': skipcomment(); break;
275    default:
276     std::cout << "readnextword: Illegal character " << (char)ch;
277      std::cout << " (ASCII " << ch<< ")\n";
278     break;
279    }
280   } while (ch=='%');
281   return was;
282 
283  }
284 
285 
286  int parser::find_macro(const std::string& s)
287  {
288   for(int i=0; i<defs.size(); i++){
289    if(defs[i].mname==s){
290     return i;
291    }
292   }
293   return -1;
294  }
295 
296  void parser::insert_macro(const macro& m)
297  {
298   int q=find_macro(m.mname);
299 
300   if(q<0) defs.push_back(m);
301   else defs[q]=m;
302  }
303 
304 
305  bool parser::expand(const std::string& s)
306   //ggf. Makro expandieren
307  {
308   int p=find_macro(s);
309   if(p<0) return false;
310   std::string args[9];
311   for(int i=0; i<defs[p].nargs; i++){
312    readbracestring(args[i]);
313   }
314 
315   std::string makr;
316   for(int i=0; i<defs[p].makro.size(); i++){
317    char ch=defs[p].makro[i];
318    if(ch=='#'){
319      int nn=defs[p].makro[i+1]-1-'0';
320     ++i;
321     makr+=args[nn];
322    }
323    else makr+=ch;
324   }
325 
326   parser::unget(makr);
327   return true;
328  }


feed icon

sventon 2.5.1

Valid XHTML 1.0 Strict   CSS ist valide!
bioinfweb RSS feed bioinfweb on twitter bioinfweb on GitHub
bioinfweb - Biology & Informatics Website