source: tol/tol/bparser/scn.cpp @ 6db72d5e

1941-docker-image-to-testdevel
Last change on this file since 6db72d5e was 6db72d5e, checked in by Víctor de Buen <vdebuen@…>, 17 years ago

Fixes #825

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

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