source: tol/tol/bparser/scn.cpp

devel
Last change on this file was 33fc49e, checked in by Jorge Pérez <josp.jorge@…>, 11 years ago

refs #1866, cambios desde compilación en Linux, el error de windows se mantiene SEGFAULT

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@6822 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 19.2 KB
Line 
1/* scn.cpp: implementation of lexical scanner for GNU/TOL Language.
2
3   Copyright (C) 2005 - Bayes Decision, SL (Spain [EU])
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2, or (at your option)
8   any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18   USA.
19 */
20
21#if defined(_MSC_VER)
22#include <win_tolinc.h>
23#endif
24
25#include <tol/tol_bscanner.h>
26#include <assert.h>
27
28BTraceInit("scn.cpp");
29
30/*! Structure where recognizables tokens of TOL language are stored.
31 *  This object is created in PutSymbolTable method, called from
32 *  constructor.
33 *  \sa PutSymbolTable
34 */
35BScanner::BTokenByNameHash BScanner::symbolTable_;
36BScanner::BTokenByNameHash BScanner::aliasTable_;
37BScanner::BTokenByNameHash BScanner::usrDefSymbol_; //!< User defined symbols Class, Struct, ...
38BScanner* BScanner::current_ = NULL;
39
40
41//--------------------------------------------------------------------
42BScanner::BScanner()
43
44/*! Create BScanner object.<br>
45 *  Create and initialize \a symbolTable_ with
46 * Initialize \a position_, \a nextSymbol_, \a nextArgument_.
47 */
48//--------------------------------------------------------------------
49{
50//Std(BText("\nCreating BScanner ")+(BInt)this);
51  PutSymbolTable();
52  position_   = NIL;
53  nextSymbol_ = NIL;
54  lastSymbol_ = NIL;
55  nextArgument_ = "";
56  structDefininig_ = false;
57}
58
59//--------------------------------------------------------------------
60BScanner::~BScanner()
61//--------------------------------------------------------------------
62{
63//Std(BText("\nDestroying BScanner ")+(BInt)this);
64}
65
66//--------------------------------------------------------------------
67BInt BTokenOrderCriterium(const BAny vBToken1, const BAny vBToken2)
68
69/*! Comparision function to sort by name in arrays of BToken*
70 */
71//--------------------------------------------------------------------
72{
73/*
74  BToken& sym1 = **((BToken**)vBToken1);
75  BToken& sym2 = **((BToken**)vBToken2);
76  BInt cmp = StrCmp(sym1.String(), sym2.String());
77  return(cmp);
78*/
79  BToken* sym1 = *(BToken**)vBToken1;
80  BToken* sym2 = *(BToken**)vBToken2;
81  if     (!sym1 && !sym2) { return( 0); }
82  else if(!sym1 &&  sym2) { return( 1); }
83  else if( sym1 && !sym2) { return(-1); }
84  else { return(StrCmp(sym1->String(), sym2->String())); }
85}
86
87
88//--------------------------------------------------------------------
89BInt Str2SymCmp(const BAny vBChar, const BAny vBToken)
90
91/*! Comparision function to find by name in sorted arrays of BToken*
92 *  <br><i>Obsolete method. Not used by TOL code</i>
93 */
94//--------------------------------------------------------------------
95{
96  BChar*  str =    (BChar*)   vBChar;
97  BToken& sym = **(BToken**) vBToken;
98  return(strcmp(str, sym.String()));
99}
100
101//#define _USE_TRACE_CURRENT_NEXTARGUMENT_
102
103#if defined( _USE_TRACE_CURRENT_NEXTARGUMENT_ )
104//--------------------------------------------------------------------
105static void _trace_current_nextArgument_(
106  const char* function,
107  int itemNum)
108//--------------------------------------------------------------------
109{
110  if(BScanner::GetCurrent())
111  {
112    Std(BText("\n _TRACE_CURRENT_NEXTARGUMENT_(")+function+","+itemNum+") "
113        " -> '"+BScanner::GetCurrent()->NextArgument()+"'\n");
114  }
115}
116#endif
117
118#ifdef _USE_TRACE_CURRENT_NEXTARGUMENT_
119#define _TRACE_CURRENT_NEXTARGUMENT_(function,itemNum) \
120        _trace_current_nextArgument_(function,itemNum)
121#else
122#define _TRACE_CURRENT_NEXTARGUMENT_(function,itemNum)
123#endif
124
125//--------------------------------------------------------------------
126BToken* BScanner::FindSymbol(const BText& name)
127
128/*! Find a symbol in \a symbolTable_ which name is \a str and
129 *  returns it if exists, else return NIL.
130 * \param str Name of BToken symbol that will be searched
131 * \return BToken found in \a symbolTable_
132 * \sa BArray::FindSorted
133 */
134//--------------------------------------------------------------------
135{
136  _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",1);
137  if(!name.HasName())
138  { return(NULL); }
139  BToken* tok = NULL;
140  _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",2);
141  BTokenByNameHash::const_iterator found;
142  _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",3);
143  found = symbolTable_.find(name);
144  _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",4);
145  if(found==symbolTable_.end())
146  {
147    _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",5);
148    found = aliasTable_.find(name);
149    _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",6);
150    if(found!=aliasTable_.end())
151    {
152      _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",7);
153      tok = found->second;
154      _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",8);
155    }
156    _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",9);
157  }
158  else
159  {
160    _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",10);
161    tok = found->second;
162    _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",11);
163  }           
164  _TRACE_CURRENT_NEXTARGUMENT_("FindSymbol",12);
165  return(tok);
166}
167
168//--------------------------------------------------------------------
169BToken* BScanner::FindSymbol(const BChar* str)
170
171/*! Find a symbol in \a symbolTable_ which name is \a str and
172 *  returns it if exists, else return NIL.
173 * \param str Name of BToken symbol that will be searched
174 * \return BToken found in \a symbolTable_
175 * \sa BArray::FindSorted
176 */
177//--------------------------------------------------------------------
178{
179  BText name = str;
180  return(FindSymbol(name));
181}
182
183//--------------------------------------------------------------------
184BInt BScanner::CountSymbols()
185
186/*! Return size of \a symbolTable_ attribute.
187 */
188//--------------------------------------------------------------------
189{
190  return(symbolTable_.size());
191}
192
193//--------------------------------------------------------------------
194BInt BScanner::AddSymbol(BToken* sym)
195
196/*! Store in \a symbolTable_ BToken \a sym parameter.
197 * \param sym BToken that will be stores in \a symbolTable_
198 * \return Size of symbolTable_
199 * \sa BArray::AddSorted
200 */
201//--------------------------------------------------------------------
202{
203  const BText& name = sym->Name();
204  assert(name.HasName());
205  BToken* s = FindSymbol(name);
206  if(!s)
207  {
208//Std(BText("\nAdding Symbol <") + sym->Name()+">");
209    s = symbolTable_[name] = sym;
210    if(sym->TokenType()==TYPE)
211    {
212      usrDefSymbol_[name]=sym;
213    }
214  }
215  s->IncNRefs();
216  return(symbolTable_.size());
217}
218
219//--------------------------------------------------------------------
220BInt BScanner::DelSymbol(const BText& name)
221
222/*! Remove BToken with \a name_ attribute equal to \a str parameter
223 *  from symbolTable_.
224 * \param str Char* value of \a name_ of BToken that will be removed
225 * \return symbolTable_ size.
226 * \sa BArray::FindSorted, BArray::ReallocBuffer
227 */
228//--------------------------------------------------------------------
229{
230  BToken* s = FindSymbol(name);
231  if(s)
232  {
233    s->DecNRefs();
234    if(!s->NRefs())
235    {
236      symbolTable_.erase(name);
237    }
238  }
239  return(symbolTable_.size());
240}
241
242//--------------------------------------------------------------------
243BInt BScanner::DelSymbol(const BChar* str)
244
245/*! Remove BToken with \a name_ attribute equal to \a str parameter
246 *  from symbolTable_.
247 * \param str Char* value of \a name_ of BToken that will be removed
248 * \return symbolTable_ size.
249 * \sa BArray::FindSorted, BArray::ReallocBuffer
250 */
251//--------------------------------------------------------------------
252{
253  BText name = str;
254  return(DelSymbol(name));
255}
256
257//--------------------------------------------------------------------
258// Tables of tokens by type
259//--------------------------------------------------------------------
260static BOpenToken defOpe_[] =
261{
262  BOpenToken("("),
263  BOpenToken("["),
264  BOpenToken("{"),
265  BOpenToken("#{#"),
266  BOpenToken("#(#")
267};
268
269static BCloseToken defClo_[] =
270{
271  BCloseToken(")",   &(defOpe_[0])),
272  BCloseToken("]",   &(defOpe_[1])),
273  BCloseToken("}",   &(defOpe_[2])),
274  BCloseToken("#}#", &(defOpe_[3])),
275  BCloseToken("#)#", &(defOpe_[4]))
276};
277
278//--------------------------------------------------------------------
279  char GetIdFromTokenClose(BCloseToken* c)
280//--------------------------------------------------------------------
281{
282  BCloseToken* t = &(defClo_[0]);
283  if(!c) { return('\0'); }
284  assert((c>=t)&&(c<t+5));
285  return(1+(c-t));
286}
287
288
289//--------------------------------------------------------------------
290  BCloseToken* GetTokenCloseFromId(char k)
291//--------------------------------------------------------------------
292{
293  assert((k>=0)&&(k<=5));
294  if(!k) { return(NULL); }
295  return(&defClo_[k-1]);
296}
297
298static BSeparatorToken defSep_[] =
299{
300  BSeparatorToken(";", 1),
301  BSeparatorToken(",", 2)
302};
303
304static BToken defBin_[] =
305{
306  BBinaryToken("=",        3),   // 0
307  BBinaryToken(":=",       3),   // 1
308  BBinaryToken("#F#",      4),   // 2
309  BBinaryToken("|",        5),   // 3
310  BBinaryToken("&",        6),   // 4
311  BBinaryToken("Of",       7),   // 5
312  BBinaryToken(">",        8),   // 6
313  BBinaryToken("<",        8),   // 7
314  BBinaryToken(">",        8),   // 8
315  BBinaryToken("==",       8),   // 9
316  BBinaryToken(">=",       8),   // 10
317  BBinaryToken("<=",       8),   // 11
318  BBinaryToken(":>",       8),   // 12
319  BBinaryToken("<:",       8),   // 13
320  BBinaryToken("!=",       8),   // 14
321  BBinaryToken("#+#",      9),   // 15
322  BBinaryToken("#-#",      9),   // 16
323  BBinaryToken("*",       10),   // 17
324  BBinaryToken("$*",      10),   // 18
325  BBinaryToken("/",       11),   // 19
326  BBinaryToken("$/",      11),   // 20
327  BBinaryToken("%",       11),   // 21
328  BBinaryToken("^",       12),   // 22
329  BBinaryToken("**",      12),   // 23
330  BBinaryToken("&&",      13),   // 24
331  BBinaryToken("||",      13),   // 25
332  BBinaryToken(":",       14),   // 26
333  BBinaryToken("<<",      15),   // 27
334  BBinaryToken(">>",      15),   // 28
335  BBinaryToken("->",      16),   // 29
336  BBinaryToken("#E#",     17),   // 30
337  BBinaryToken("#::#",    18)    // 31
338};
339
340static BMonaryToken defMon_[] =
341{
342  BMonaryToken("+", &(defBin_[15])),
343  BMonaryToken("-", &(defBin_[16])),
344  BMonaryToken("~"),
345  BMonaryToken("!"),
346  BMonaryToken("$"),
347  BMonaryToken("Do"),
348  BMonaryToken("Struct"),
349  BMonaryToken("Class"),
350  BMonaryToken("Static"),
351  BMonaryToken("::", &(defBin_[31]))
352};
353
354static BTypeToken defTyp_[] =
355{
356  BTypeToken("Anything",  BTypeToken::BSYSTEM),
357  BTypeToken("Set",       BTypeToken::BSYSTEM),
358  BTypeToken("Date",      BTypeToken::BSYSTEM),
359  BTypeToken("CTime",     BTypeToken::BSYSTEM),
360  BTypeToken("Real",      BTypeToken::BSYSTEM),
361  BTypeToken("Complex",   BTypeToken::BSYSTEM),
362  BTypeToken("Matrix",    BTypeToken::BSYSTEM),
363  BTypeToken("VMatrix",   BTypeToken::BSYSTEM),
364  BTypeToken("Polyn",     BTypeToken::BSYSTEM),
365  BTypeToken("Ratio",     BTypeToken::BSYSTEM),
366  BTypeToken("Text",      BTypeToken::BSYSTEM),
367  BTypeToken("TimeSet",   BTypeToken::BSYSTEM),
368  BTypeToken("CTimeSet",  BTypeToken::BSYSTEM),
369  BTypeToken("Serie",     BTypeToken::BSYSTEM),
370  BTypeToken("CSeries",   BTypeToken::BSYSTEM),
371  BTypeToken("Code",      BTypeToken::BSYSTEM),
372  BTypeToken("NameBlock", BTypeToken::BSYSTEM),
373  BTypeToken("PolMatrix", BTypeToken::BSYSTEM),
374  BTypeToken("#Require",  BTypeToken::BSYSTEM)
375};
376
377static BMacroToken defMac_[] =
378{
379  BMacroToken("#Embed")
380};
381
382static const char* alias_[][2] =
383{
384  { "Ration", "Ratio" }
385};
386
387static const char* usrDef_[] =
388{
389  "Struct", "Class"
390};
391
392static BInt defOpeNum_ = sizeof(defOpe_)/sizeof(BOpenToken);
393static BInt defCloNum_ = sizeof(defClo_)/sizeof(BCloseToken);
394static BInt defSepNum_ = sizeof(defSep_)/sizeof(BSeparatorToken);
395static BInt defBinNum_ = sizeof(defBin_)/sizeof(BBinaryToken);
396static BInt defMonNum_ = sizeof(defMon_)/sizeof(BMonaryToken);
397static BInt defTypNum_ = sizeof(defTyp_)/sizeof(BTypeToken);
398static BInt defMacNum_ = sizeof(defMac_)/sizeof(BMacroToken);
399static BInt aliasNum_  = sizeof(alias_ )/sizeof(alias_ [1]);
400static BInt usrDefNum_ = sizeof(usrDef_)/sizeof(usrDef_[1]);
401
402static BInt defTokNum_ =
403            defOpeNum_ +
404            defCloNum_ +
405            defSepNum_ +
406            defBinNum_ +
407            defMonNum_ +
408            defTypNum_ +
409            defMacNum_ ;
410
411
412//--------------------------------------------------------------------
413void BScanner::PutSymbolTable()
414
415/*! Puts all recognizables tokens of TOL in \a symbolTable_ static
416 *  attribute and sorts it.<br>
417 *  Different types of tokens, stored in different static tables:<br>
418 *  <ul>
419 *     <li>\a defOpe_ array for tokens that represents open symbols
420 *     <li>\a defClo_ array for tokens that represents close symbols
421 *     <li>\a defSep_ array for tokens that represents separator symbols
422 *     <li>\a defBin_ array for tokens that represents binary symbols
423 *     <li>\a defMon_ array for tokens that represents monary symbols
424 *     <li>\a defTyp_ array for tokens that represents types
425 * </ul>
426 */
427//--------------------------------------------------------------------
428{
429  static bool symbolTableFilled_ = BFALSE;
430  if (!symbolTableFilled_)
431  {
432    SetEmptyKey(symbolTable_, NULL);
433    SetDeletedKey(symbolTable_, name_del_key());
434
435    symbolTableFilled_ = BTRUE;
436    BInt n=0, m=0;
437    for(n=0; n<defOpeNum_; n++)
438    { symbolTable_[defOpe_[n].Name()]=&(defOpe_[n]); }
439    m+=n;
440    for(n=0;n<defCloNum_; n++)
441    { symbolTable_[defClo_[n].Name()]=&(defClo_[n]); }
442    m+=n;
443    for(n=0; n<defSepNum_; n++)
444    { symbolTable_[defSep_[n].Name()]=&(defSep_[n]); }
445    m+=n;
446    for(n=0; n<defBinNum_; n++)
447    { symbolTable_[defBin_[n].Name()]=&(defBin_[n]); }
448    m+=n;
449    for(n=0; n<defMonNum_; n++)
450    { symbolTable_[defMon_[n].Name()]=&(defMon_[n]); }
451    m+=n;
452    for(n=0; n<defTypNum_; n++)
453    { symbolTable_[defTyp_[n].Name()]=&(defTyp_[n]); }
454    m+=n;
455    for(n=0; n<defMacNum_; n++)
456    { symbolTable_[defMac_[n].Name()]=&(defMac_[n]); }
457
458    SetEmptyKey(aliasTable_, NULL);
459    for(n=0; n<aliasNum_; n++)
460    {
461      BToken* tok = FindSymbol(alias_[n][1]);
462      assert(tok);
463      aliasTable_[alias_[n][0]] = tok;
464    }
465    SetEmptyKey(usrDefSymbol_, NULL);
466    for(n=0; n<usrDefNum_; n++)
467    {
468      BToken* tok = FindSymbol(usrDef_[n]);
469      assert(tok);
470      usrDefSymbol_[usrDef_[n]] = tok;
471    }
472  }
473}
474
475//--------------------------------------------------------------------
476void BScanner::Initialize(const BText& expression)
477
478/*! Prepares it self to scan an expression. Initialize all non-static
479 *  attributes with values extracted from \a expression parameter.
480 */
481//--------------------------------------------------------------------
482{
483  length_     = expression.Length();
484  expression_ = expression.String();
485  position_   = expression_;
486  nextSymbol_ = NIL;
487  lastSymbol_ = NIL;
488  nextArgument_ = "";
489  structDefininig_ = false;
490  current_ = this;
491}
492
493
494//--------------------------------------------------------------------
495BBool BScanner::NextChar()
496
497/*! Moves position_ to the next no blank character.
498 *  If there are no more characters moves position_ to NIL.
499 */
500//--------------------------------------------------------------------
501{
502  while((position_[0]==' ' ) ||
503  (position_[0]=='\n') ||
504  (position_[0]=='\t')) { position_++; }
505  return(position_[0]);
506}
507
508//--------------------------------------------------------------------
509/*! Reads the next word from \a position_.
510 * <p>
511 * <b>Algorythm</b>:
512 *  <ol type=a>
513 *    <li> If there are no more text -> returns the type NONE.<br><br>
514 *    <li> Else-If the next no blank character is a comma then:<br><br>
515 *      <ol>
516 *        <li> Puts the text until the next comma in \a nextArgument_ field,
517 *        <li> moves \a position_ after the last comma, and
518 *        <li> returns the type ARGUMENT.
519 *      </ol><br><br>
520 *    <li> Else reads the word until next blank character. Then<br><br>
521 *      <ol>
522 *        <li> Moves \a position_ after the blank character, and
523 *          <ol type=a>
524 *            <li> If this word is the name of a token then:
525 *              <ol type=1>
526 *                <li> Puts the word in \a nextSymbol_ field,
527 *                <li> returns the type of the found token.
528 *              </ol>
529 *            <li> else
530 *              <ol type=1>
531 *                <li> Puts NIL in \a nextSymbol_ field,
532 *                <li> puts the word in \a nextArgument_ field,
533 *                <li> returns the type ARGUMENT.
534 *              </ol>
535 *          </ol>
536 *      </ol>
537 *  </ol>
538 */
539BTokenType BScanner::NextWordType()
540{
541  BChar nextWord[256];
542  BTokenByNameHash::const_iterator found;
543  static BToken* structToken_ = NULL;
544  static BToken* fieldToken_ = NULL;
545  if(!structToken_)
546  {
547    structToken_ = FindSymbol("Struct");
548    fieldToken_  = FindSymbol("->");
549  }
550  BTokenType type = ARGUMENT;
551  if(nextSymbol_) { lastSymbol_ = nextSymbol_; }
552  nextSymbol_  = NIL;
553  if(NextChar())
554  {
555    if(position_[0]=='\"')
556    {
557      BInt n=0;
558      do { n++; }
559      while(position_[n] && (position_[n]!='\"'));
560      nextArgument_.Copy(position_, n);
561      nextArgument_.Replace("\\'","\"");
562      position_+=n+1;
563    }
564    else
565    {
566      BInt nChar;
567      if(sscanf(position_, "%s%n", nextWord, &nChar)) 
568      {
569        BInt rest = expression_+length_-position_;
570        if(rest>nChar) { position_+=nChar; }
571        else { position_=expression_+length_; }
572        if(nChar>255) nextWord[255]='\0';
573
574        nextSymbol_ = FindSymbol(nextWord);
575        if(nextSymbol_ && lastSymbol_)
576        {
577          if((lastSymbol_==structToken_) && (nextSymbol_->TokenType()==OPEN))
578          {
579            structDefininig_ = true;
580          }
581          else if(structDefininig_ && (nextSymbol_->TokenType()==CLOSE))
582          {
583            structDefininig_ = false;
584          }
585          else if(structDefininig_ && (lastSymbol_->TokenType()==TYPE))
586          {
587            found = usrDefSymbol_.find(nextSymbol_->Name());
588            if(found != usrDefSymbol_.end())
589            {
590              nextSymbol_ = NULL;
591            }
592          }
593          else
594          {
595          //if((nextSymbol_->Name()=="Class")&&(lastSymbol_->Name()=="->"))
596            if(lastSymbol_== fieldToken_)
597            {
598              found = usrDefSymbol_.find(nextSymbol_->Name());
599              if(found != usrDefSymbol_.end())
600              {
601                nextSymbol_ = NULL;
602              }
603            }
604          }
605        }
606        if(nextSymbol_)
607        { type = nextSymbol_->TokenType(); }
608        else
609        { nextArgument_.Copy(nextWord,nChar); }
610      }
611    }
612  }
613  else
614  {
615    type = NONE;
616  }
617  return(type);
618}
619
620
621//--------------------------------------------------------------------
622/*! Reads the next word.
623 *  If its type is ARGUMENT read the next word and returns its type,
624 *  else returns ARGUMENT type.
625 * \return Type of next word to be scanned
626 * \sa BScanner::NextWordType
627 */
628BTokenType BScanner::ReadNextSymbol()
629{
630  if(nextSymbol_) { lastSymbol_ = nextSymbol_; }
631  nextSymbol_  = NIL;
632  nextArgument_ = "";
633  BTokenType type = NextWordType();
634  if(type==ARGUMENT) { type = NextWordType(); }
635  return (type);
636}
637
638
639//--------------------------------------------------------------------
640BText BScanner::Scanned()
641
642/*! Returns the text scanned at this moment.
643 *  Its usefull for parser error messages.
644 */
645//--------------------------------------------------------------------
646{
647  return(BText(expression_,0,(position_-expression_)-1));
648}
Note: See TracBrowser for help on using the repository browser.