home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / CALCPLUS.ZIP / CALCLEX.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-02  |  21.0 KB  |  933 lines

  1. /*******************************************************
  2.  
  3.     The CalcPlus Class Library Version 1.0,
  4.     Author: Vladimir Schipunov, Copyright (C) 1996
  5.  
  6.     This library is free software. Permission to use,
  7.     copy, modify and redistribute the CalcPlus library
  8.     for any purpose is hereby granted without fee,
  9.     provided that the above copyright notice appear
  10.     in all copies.
  11.  
  12. *******************************************************/
  13.  
  14. #include <iostream.h>
  15. #include <fstream.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <ctype.h>
  19. #if !defined(_MSC_VER) && !defined(__WIN32__)
  20.     #include <strstream.h>
  21. #else
  22.     #include <strstrea.h>
  23. #endif
  24. #include "calclex.h"
  25. #include "yytab.h"
  26.  
  27. static KeyDef KeyData[] =
  28. {
  29.     { "FUNCTION",   lxFunc    },
  30.     { "PROCEDURE",  lxProc    },
  31.     { "FUNC",       lxFunc    },
  32.     { "PROC",       lxProc    },
  33.     { "AND",        lxAnd     },
  34.     { "OR",         lxOr      },
  35.     { "VAR",        lxVar     },
  36.     { "ECHO",       lxEcho    },
  37.     { "IF",         lxIf      },
  38.     { "THEN",       lxThen    },
  39.     { "ELSE",       lxElse    },
  40.     { "ENDL",       lxEndl    },
  41.     { "TRUE",       lxTrue    },
  42.     { "FALSE",      lxFalse   },
  43.     { "BEGIN",      lxBegin   },
  44.     { "END",        lxEnd     },
  45.     { "WHILE",      lxWhile   },
  46.     { "DO",         lxDo      },
  47.     { "FOR",        lxFor     },
  48.     { "TO",         lxTo      },
  49.     { "LOOP",       lxLoop    },
  50.     { "STEP",       lxStep    },
  51.     { "RETURN",     lxRet     },
  52.     { "EXIT",       lxExit    },
  53.     { "CONST",      lxConst   },
  54.     { "STRUCT",     lxStruct  },
  55.     { "NIL",        lxNil     },
  56.     { "NOT",        lxNot     },
  57.     { "INCLUDE",    lxInclude },
  58.     { "DEFINE",     lxDefine  },
  59.     { "UNDEF",      lxUndef   },
  60.     { "IFDEF",      lxIfdef   },
  61.     { "IFNDEF",     lxIfndef  },
  62.     { "ENDIF",      lxEndif   }
  63. };
  64.  
  65. Keywords Keywords::Dictionary;
  66. Keyword::~Keyword(){}
  67. Keywords::Keywords()
  68. {
  69.     for( int i = 0; i < sizeof( KeyData )/sizeof( KeyData[0] ); i++ )
  70.     {
  71.         KeyDef& d = KeyData[i];
  72.         Add( new Keyword( d.token, d.lex ));
  73.     }
  74. }
  75.  
  76. YLex::yylex()
  77. {
  78.     if( !in && NextStream())
  79.         return lxEof;
  80.     __whitespace();
  81.     c = GetChar();
  82.     if( !in || in->eof())                       return lxEof;
  83.     if( isalpha(c) || c == '_' || c == '@' )    return __name();
  84.     switch( c )
  85.     {
  86.         case '{': case '}': case '.':
  87.         case '[': case ']': case ')':
  88.         case '&': case '*': case '(': case '!':
  89.         case ';': case ',': case '^': case '=':
  90.  
  91.                                 return *pyylval()=c;
  92.         case '#':               return __preprocessor();
  93.         case '/':               return __comment();
  94.         case ':':               return __assignment();
  95.         case '-':               return __implication();
  96.         case '+':               return __increment();
  97.         case '<': case '>':     return __comparison();
  98.         case '"': case '\'':    return __string();
  99.  
  100.         case '0':
  101.         case '1': case '2': case '3':
  102.         case '4': case '5': case '6':
  103.         case '7': case '8': case '9':   return __number();
  104.     }
  105.     return lxBadToken;
  106. }
  107.  
  108. void YLex::yyerror
  109. (
  110.     const char* s1,
  111.     const char* s2,
  112.     const char* s3
  113. )
  114. {
  115.     if( Skipping || errors->NumObj > 10 )
  116.         return;
  117.     if( errors->NumObj == 10 )
  118.     {
  119.         s1 = "too many errors";
  120.         s2 = s3 = "";
  121.     }
  122.     ListIdx i( *errors );
  123.     for( ; i; i++ )
  124.         if(((SyntaxError*)i.obj)->line == (lexstr ? lexstr->line : 0 ))
  125.             return;
  126.     SyntaxError* p = new SyntaxError( s1, s2, s3 );
  127.     p->line = lexstr ? lexstr->line : 0;
  128.     errors->Add( p );
  129. }
  130.  
  131. LStream* YLex::lexstr;
  132.  
  133. YLex::YLex( const char *i ) :
  134.     in( 0 ), input( 0 ), Macros( 1 ),
  135.     IfDefSP( 0 ), Skipping( 0 )
  136. {
  137.     errors  = new LexList;
  138.     defines = new LexList;
  139.     if( i )
  140.         File( i );
  141. }
  142.  
  143. void YLex::File( const char* i, int Undef )
  144. {
  145.     if( !input )
  146.         input = new LexStack( 0 );
  147.     input->Push( new LSFile( i, Undef ));
  148. }
  149.  
  150. YLex::~YLex()
  151. {
  152.     delete errors;
  153.     delete input;
  154.     delete defines;
  155. }
  156.  
  157. YLex::NextStream()
  158. {
  159.     if( !input )
  160.         return 1;
  161.     LStream* s = (LStream*)input->Last();
  162.     if( !s )
  163.         return 1;
  164.     if( s->dirty && !s->in->eof() ||
  165.        !s->dirty && !s->Open())
  166.     {
  167.         s->dirty = 1;
  168.         in = s->in;
  169.         lexstr = s;
  170.         return 0;
  171.     }
  172.     if( s->UndefAll())
  173.     {
  174.         delete defines;
  175.         defines = new LexList;
  176.     }
  177.     if( s->isFile() && IfDefSP )
  178.     {
  179.         Skipping = 0;
  180.         yyerror("unclosed ifdef directive");
  181.     }
  182.     input->Pop();
  183.     lexstr = 0;
  184.     in     = 0;
  185.     return NextStream();
  186. }
  187.  
  188. char YLex::GetChar()
  189. {
  190.     if( !in && NextStream())
  191.         return lxEof;
  192.     char c;
  193.     *in >> c;
  194.     if( in->eof())
  195.           return NextStream() ? (char)lxEof : GetChar();
  196.     lexstr->pos++;
  197.     lexstr->begline = lexstr->begline &&
  198.         (c =='\n' || c=='\t' || c=='\v' || c==' ' || c=='#');
  199.     return c;
  200. }
  201.  
  202. void YLex::PutBack( char  c )
  203. {
  204.     in->putback(c);
  205.     if( lexstr )
  206.         lexstr->pos--;
  207. }
  208.  
  209. void YLex::NextLine()
  210. {
  211.     lexstr->pos = 0;
  212.     lexstr->line++;
  213.     lexstr->begline = 1;
  214. }
  215.  
  216. YLex::TokenProc( int isProc )
  217. {
  218.     return isProc ? yyProc : yyFunc;
  219. }
  220.  
  221. Token YLex::__number()
  222. {
  223.     int dot = 0, exp = 0, done = 0;
  224.     for( int i = 0; i < sizeof(Lex); i++, c = GetChar() )
  225.     {
  226.         Lex[i] = c;
  227.         switch(c)
  228.         {
  229.             case '0':
  230.             case '1': case '2': case '3':
  231.             case '4': case '5': case '6':
  232.             case '7': case '8': case '9': break;
  233.  
  234.             case 'e':
  235.             case 'E':
  236.             {
  237.                 exp++;
  238.                 if( dot == 1 ) dot = 0;
  239.                 c = GetChar();
  240.                 if( c == '-' || c == '+' )
  241.                     Lex[++i] = c;
  242.                 else
  243.                     PutBack(c);
  244.                 break;
  245.             }
  246.             case '.':   { dot++; break; }
  247.  
  248.             default:
  249.             {
  250.                 PutBack(c);
  251.                 done = 1;
  252.                 Lex[i] = 0;
  253.                 if( i > MaxIdLength )
  254.                     return lxBadToken;
  255.                 break;
  256.             }
  257.         }
  258.         if( done ) break;
  259.     }
  260.  
  261.     if( dot > 1 || exp > 1 || dot && exp )
  262.         return lxBadToken;
  263.  
  264.     double tmp = atof(Lex);
  265.     if( exp || dot )
  266.     {
  267.         YYLVAL(tmp);
  268.         return lxReal;
  269.     }
  270.     else
  271.     {
  272.         #define MAXLONG     0x7FFFFFFFL
  273.         static long MaxInt = MAXLONG, MinInt = -MAXLONG;
  274.         if( tmp > MaxInt || tmp < MinInt )
  275.             return lxBadToken;
  276.         long v = (long)tmp;
  277.         YYLVAL(v);
  278.         return lxInt;
  279.     }
  280. }
  281.  
  282. Token YLex::__name()
  283. {
  284.     Lex[MaxIdLength] = 0;
  285.     for( int i = 0; i <= MaxIdLength; i++, c = GetChar() )
  286.     {
  287.         if( i == MaxIdLength )
  288.             return lxBadToken;
  289.  
  290.         if( isalpha(c) || isdigit(c) || c == '_' ||
  291.             c == '@' && !i || i && *Lex=='@' && c=='.' )
  292.         {
  293.             Lex[i] = c;
  294.             continue;
  295.         }
  296.         else
  297.         {
  298.             PutBack(c);
  299.             Lex[i] = 0;
  300.             break;
  301.         }
  302.     }
  303.     LOOKUP( Keywords::Dictionary, Keyword );
  304.     if( Macros && __macro( Lex ))
  305.         return yylex();
  306.     char *p = Lex;
  307.     YYLVAL(p);
  308.     return lxName;
  309. }
  310.  
  311. Token YLex::__comparison()
  312. {
  313.     char c1 = c, c2;
  314.     c2 = GetChar();
  315.     return c2 == '=' ? ( c1 == '<' ? lxLe : lxGe ) :
  316.            c1 == '<' &&  c2 == '>' ? lxNe : ( PutBack(c2), c1 );
  317. }
  318.  
  319. Token YLex::__assignment()
  320. {
  321.     c = GetChar();
  322.     if( c == '=' )
  323.         return lxAssign;
  324.     PutBack(c);
  325.     return (Token)':';
  326. }
  327.  
  328. Token YLex::__implication()
  329. {
  330.     c = GetChar();
  331.     if( c == '>' )
  332.         return lxImp;
  333.     if( c == '=' )
  334.         return lxDec;
  335.     PutBack(c);
  336.     return (Token)'-';
  337. }
  338.  
  339. Token YLex::__increment()
  340. {
  341.     c = GetChar();
  342.     if( c == '+' )
  343.         return lxInc;
  344.     PutBack(c);
  345.     return (Token)'+';
  346. }
  347.  
  348. Token YLex::__comment()
  349. {
  350.     c = GetChar();
  351.     if( c == '*' )
  352.     {
  353.         while( !in->eof() )
  354.         {
  355.             if( c = GetChar(), c == '*' )
  356.                 if( c = GetChar(), c == '/')
  357.                     break;
  358.             if( c == '\n' )
  359.                 NextLine();
  360.         }
  361.         return (Token)yylex();
  362.     }
  363.     if( c == '/' )
  364.     {
  365.         while( !in->eof() )
  366.         {
  367.             c = GetChar();
  368.             if( c != '\n' )
  369.                 continue;
  370.             NextLine();
  371.             return (Token)yylex();
  372.         }
  373.     }
  374.     PutBack(c);
  375.     return (Token)'/';
  376. }
  377.  
  378. void YLex::__whitespace()
  379. {
  380.     while( in && !in->eof() )
  381.     {
  382.         c = GetChar();
  383.         if( c == '\n' ) NextLine();
  384.         if( c != '\n' && c != '\t' && c != '\v' && c != ' ' )
  385.         {
  386.             if( c!=lxEof && (unsigned char)c!=0xFF )
  387.                 PutBack( c );
  388.             break;
  389.         }
  390.     }
  391. }
  392.  
  393. Token YLex::__string()
  394. {
  395.     in->getline(Lex,sizeof(Lex)-1,c);
  396. #ifdef __ZTC__
  397.     int n = strlen( Lex );
  398.     if( n>0 )
  399.         Lex[ n-1 ] = 0;
  400. #endif
  401.     char *p = Lex;
  402.     YYLVAL(p);
  403.     return lxString;
  404. }
  405.  
  406. #define DEFEXIT { yyerror("error in definition"); return; }
  407. void YLex::__definition()
  408. {
  409.     Macros = 0; Token t = yylex(); Macros = 1;
  410.     if( t==lxName && (*defines)( Lex ))
  411.     {
  412.         yyerror("redefinition of symbol ", Lex );
  413.         return;
  414.     }
  415.     if( t!=lxName  && t!=yyVar &&
  416.         t!=yyConst && t!=yyStruct )
  417.             DEFEXIT;
  418.     for( *in >> c; c==' ' || c=='\t'; *in >> c ){}
  419.     if( in->eof() || c=='\n' )
  420.     {
  421.         defines->Add( new LexDefine( Lex ));
  422.         return;
  423.     }
  424.     if( c=='(' )
  425.     {
  426.         int i;
  427.         for( i = strlen( Lex ); c!=')' &&
  428.             i < sizeof( Lex ); *in >> c )
  429.         {
  430.             if( in->eof() || c=='\n' )
  431.                 DEFEXIT;
  432.             Lex[i++] = c;
  433.         }
  434.         Lex[i++] = c;
  435.         Lex[i] = 0;
  436.     }
  437.     else
  438.         in->putback( c );
  439.     LexDefine* def = new LexDefine( Lex );
  440.     defines->Add( def );
  441.     for( *in >> c; c==' ' || c=='\t'; *in >> c ){}
  442.     in->putback( c );
  443.     char prev = 0;
  444.     int i;
  445.     for( i = 0; i < sizeof( Lex ); i++ )
  446.     {
  447.         *in >> c;
  448.         if( c==lxEof )
  449.             break;
  450.         if( c=='\n' )
  451.         {
  452.             NextLine();
  453.             if( prev=='\\' )
  454.                 c = Lex[i-1] = ' ';
  455.             else
  456.                 break;
  457.         }
  458.         Lex[i] = c;
  459.         prev = c==' '||c=='\t'? prev : c;
  460.     }
  461.     Lex[i] = 0;
  462.     def->Translate( Lex );
  463. }
  464.  
  465. Token YLex::__preprocessor()
  466. {
  467.     if( !lexstr->begline )
  468.         return c;
  469.     __whitespace();
  470.     c = GetChar();
  471.     Token t = __name();
  472.     int not = 0;
  473.     switch( t )
  474.     {
  475.         case lxInclude:
  476.         {
  477.             if( yylex()!=lxString )
  478.             {
  479.                 yyerror();
  480.                 break;
  481.             }
  482.             File( Lex, 0 );
  483.             in = 0;
  484.             return yylex();
  485.         }
  486.         case lxDefine:
  487.         {
  488.             if( !Skipping )
  489.                 __definition();
  490.             return yylex();
  491.         }
  492.         case lxUndef:
  493.         {
  494.             if( Skipping )
  495.                 return yylex();
  496.             Macros = 0; t = yylex(); Macros = 1;
  497.             if( t!=lxName )
  498.                 yyerror();
  499.             LexDefine* def = (LexDefine*)(*defines)( Lex );
  500.             if( def )
  501.                 defines->Remove( def );
  502.             return yylex();
  503.         }
  504.         case lxIfndef:  not = 1;
  505.         case lxIfdef:
  506.         {
  507.             Macros = 0; t = yylex(); Macros = 1;
  508.             if( t!=lxName )
  509.                 yyerror();
  510.             LexDefine* def = (LexDefine*)(*defines)( Lex );
  511.             IfDefStack[ IfDefSP++ ] = Skipping ? 2 :
  512.                 (!def && !not || def && not) ? 1 : 0;
  513.             break;
  514.         }
  515.         case lxElse:
  516.         {
  517.             if( !IfDefSP )
  518.             {
  519.                 yyerror("misplaced #else");
  520.                 return yylex();
  521.             }
  522.                 int& c = IfDefStack[ IfDefSP-1 ];
  523.                 c = c==2 ? c : c==1 ? 0 : 1;
  524.             break;
  525.         }
  526.         case lxEndif:
  527.         {
  528.             if( !IfDefSP )
  529.             {
  530.                 yyerror("misplaced #endif");
  531.                 return yylex();
  532.             }
  533.             IfDefSP--;
  534.             break;
  535.         }
  536.         default:    return t;
  537.     }
  538.     Skipping = IfDefSP>0 && IfDefStack[ IfDefSP-1 ]>0;
  539.     Token last = 0;
  540.     while( Skipping )
  541.         last = yylex();
  542.     return last ? last : yylex();
  543. }
  544.  
  545. YLex::__macro( const char* s )
  546. {
  547.     LexDefine* def = (LexDefine*)(*defines)( s );
  548.     if( !def || def->busy )
  549.         return 0;
  550.     __whitespace();
  551.     c = GetChar();
  552.     if( !in || in->eof() ||
  553.         c=='(' && !def->argc ||
  554.         c!='(' &&  def->argc )
  555.     {
  556.         yyerror("wrong number of arguments in macro ",
  557.             def->StringValue());
  558.         return 0;
  559.     }
  560.     if( !def->argc )
  561.         PutBack( c );
  562.     char *p = def->Generate( *in );
  563.     if( !p )
  564.     {
  565.         yyerror("bad arguments for macro ", def->StringValue());
  566.         return 0;
  567.     }
  568.     input->Push( new LSMacro( def, p ));
  569.     in = 0;
  570.     return 1;
  571. }
  572.  
  573. void YLex::Errors( ostream& o ) const
  574. {
  575.     if( !errors )
  576.         return;
  577.     for( LexObj* p = errors->FirstInList; p; p = p->NextInList )
  578.     {
  579.         SyntaxError& err = (SyntaxError&) *p;
  580.         o << err.file << "\t" << err.line << ": " << err << endl;
  581.     }
  582. }
  583.  
  584. SyntaxError::SyntaxError
  585. (
  586.     const char*s1,
  587.     const char*s2,
  588.     const char*s3
  589. ) :
  590.     line( 0 ),
  591.     str( new char
  592.     [
  593.         strlen( s1 )+
  594.         strlen( s2 )+
  595.         strlen( s3 )+1
  596.     ]
  597. )
  598. {
  599.     char *f = YLex::lexstr ? YLex::lexstr->file : "";
  600.     strcpy( str, s1 );
  601.     strcat( str, s2 );
  602.     strcat( str, s3 );
  603.     file = new char[ strlen( f )+1 ];
  604.     strcpy( file, f );
  605. }
  606.  
  607. LexDefine::LexDefine( const char* s ) :
  608.     value( 0 ), busy( 0 ), argc( 0 )
  609. {
  610.     name = new char[ strlen( s )+1 ];
  611.     strcpy( name, s );
  612. }
  613.  
  614. inline isA( char c ){ return c=='_' || isdigit( c ) || isalpha( c ); }
  615. static char *strtran
  616. (
  617.     const char* str,
  618.     const char* a,
  619.     const char* b,
  620.     int whole_word = 1
  621. )
  622. {
  623.     int n1 = strlen( a );
  624.     int n2 = strlen( b );
  625.     char* s = new char[ strlen( str )+1 ];
  626.     strcpy( s, str );
  627.     for( const char* p = strstr( s, a );
  628.         p && *p; p = strstr( p, a ))
  629.     {
  630.         if(( s!=p && isA( p[-1] ) ||
  631.             isA( p[ n1 ])) && whole_word )
  632.         {
  633.             p += n1;
  634.             continue;
  635.         }
  636.         int i = (int)(p - s);
  637.         char *q = new char[ strlen( s )-n1+n2+1 ];
  638.         memcpy( q, s, i );
  639.         strcpy( q+i, b );
  640.         strcat( q+i, p+n1 );
  641.         delete[] s;
  642.         s = q;
  643.         p = q+i+n2;
  644.     }
  645.     return s;
  646. }
  647.  
  648. void LexDefine::Translate( const char* str )
  649. {
  650.     value = new char[ strlen( str )+1 ];
  651.     strcpy( value, str );
  652.  
  653.     static char dummy[] = "~?";
  654.     char* s = new char[ strlen( value )+1 ];
  655.     strcpy( s, value );
  656.     static char lex[256];
  657.     dummy[1] = '0';
  658.     for( char* p = strchr( name, '(' );
  659.         p && *p; p = strchr( p, ',' ), dummy[1]++, argc++ )
  660.     {
  661.         int k = 0;
  662.         for( int j = 1; p[j] && p[j]!=',' && p[j]!=')'; j++ )
  663.             if( p[j]!=' ' && p[j]!='\t' )
  664.                 lex[k++] = p[j];
  665.         char* q = strtran( s, lex, dummy );
  666.         delete[] s;
  667.         s = q;
  668.         *p = 0;
  669.         p++;
  670.     }
  671.     delete[] value;
  672.     value = s;
  673. }
  674.  
  675. #define GEN_ERROR { delete[] s; return 0; }
  676. #define GEN_ACCEPT { lex[j++] = c; break; }
  677. #define GEN_ARG { lex[j] = 0; j = -1; \
  678.     char *q = strtran( s, dummy, lex ); \
  679.     delete[] s; s = q; break; }
  680.  
  681. char* LexDefine::Generate( istream& in )
  682. {
  683.     static char dummy[] = "~?";
  684.     char*s = new char[ strlen( value )+1 ];
  685.     strcpy( s, value );
  686.     dummy[1] = '0';
  687.     for( int i = 0; i<argc; i++, dummy[1]++ )
  688.     {
  689.         char c;
  690.         char lex[ 256 ];
  691.         char string = 0;
  692.         int level = 0;
  693.         int j = 0;
  694.         while( j >= 0 )
  695.         {
  696.             in >> c;
  697.             if( in.eof() )
  698.                 GEN_ERROR;
  699.             switch( c )
  700.             {
  701.                 case '\'':
  702.                 case '"':   string = string==c ? (char)0 :
  703.                                 string ? string : c;
  704.                             GEN_ACCEPT;
  705.  
  706.                 case '(':   if( !string )
  707.                                 level++;
  708.                             GEN_ACCEPT;
  709.  
  710.                 case ')':   if( string )
  711.                                 GEN_ACCEPT;
  712.                             if( level )
  713.                             {
  714.                                 level--;
  715.                                 GEN_ACCEPT;
  716.                             }
  717.                             if( i!=argc-1 )
  718.                                 GEN_ERROR;
  719.                             GEN_ARG;
  720.  
  721.                 case ',':   if( string || level )
  722.                                 GEN_ACCEPT;
  723.                             if( i==argc-1 )
  724.                                 GEN_ERROR;
  725.                             GEN_ARG;
  726.  
  727.                 default:    GEN_ACCEPT;
  728.             }
  729.         }
  730.     }
  731.     char *q = strtran( s, "##", "", 0 );
  732.     delete[] s;
  733.     return q;
  734. }
  735.  
  736. LStream::~LStream()
  737. {
  738.     delete[] file;
  739.     delete in;
  740. }
  741.  
  742. LSFile::LSFile( const char* s, int u ) :
  743.     Undef( u )
  744. {
  745.     begline = 1;
  746.     line = 1;
  747.     pos = 0;
  748.     file = new char[ strlen( s )+1 ];
  749.     strcpy( file, s );
  750. }
  751.  
  752. LSFile::operator int() const
  753. {
  754.     if( !in )
  755.         return 1;
  756.     return !in->good();
  757. }
  758.  
  759. LSFile::Open()
  760. {
  761.     YLex::lexstr = this;
  762.     delete in;
  763.     in = new ifstream( file, ios::in | ios::nocreate
  764. #ifdef __ZTC__
  765.         | ios::translated
  766. #endif
  767.     );
  768.     if( in && in->good())
  769.         in->flags( in->flags() & ~ios::skipws );
  770.     else
  771.         cerr << "Cannot open file " << file << endl;
  772.     return *this;
  773. }
  774.  
  775. LSMacro::LSMacro( LexDefine* p, char* s ) :
  776.     def( p ), str( s )
  777. {
  778.     LStream* y = YLex::lexstr;
  779.     def->busy = 1;
  780.     begline = y->begline;
  781.     line    = y->line;
  782.     pos     = y->pos;
  783.     file = new char[ strlen( y->file )+1 ];
  784.     strcpy( file, y->file );
  785.     YLex::lexstr = this;
  786.     in = new istrstream( str, strlen( str ));
  787. }
  788.  
  789. LSMacro::~LSMacro()
  790. {
  791.     def->busy = 0;
  792.     delete[] str;
  793. }
  794.  
  795. void LexObj::print( ostream& o ) const
  796. {
  797.     o << StringValue();
  798. }
  799.  
  800. LexObj::isEqual( const LexObj& o ) const
  801. {
  802.     const char *p = StringValue();
  803.     const char *q = o.StringValue();
  804.     if( !p || !q )
  805.         return 0;
  806.     return !strcmp( p, q );
  807. }
  808.  
  809. static theSame( const char* s1, const char *s2 )
  810. {
  811.     for( int i = 0; s1[i] || s2[i]; i++ )
  812.         if( !s1[i] || !s2[i] ||
  813.             toupper( s1[i] ) !=
  814.             toupper( s2[i] ))
  815.                 return 0;
  816.     return 1;
  817. }
  818.  
  819. LexObj* LexList::operator()( const char *s ) const
  820. {
  821.     for( LexObj* p = FirstInList; p; p = p->NextInList )
  822.         if( theSame( p->StringValue(), s ))
  823.             return p;
  824.     return 0;
  825. }
  826.  
  827. LexList::~LexList()
  828. {
  829.     for( LexObj *p = FirstInList; p; )
  830.     {
  831.         LexObj* q = p;
  832.         p = p->NextInList;
  833.         delete q;
  834.     }
  835. }
  836.  
  837. void LexList::Add( LexObj* o )
  838. {
  839.     NumObj++;
  840.     if( !FirstInList )
  841.     {
  842.         FirstInList = LastInList = o;
  843.         return;
  844.     }
  845.     LastInList->NextInList = o;
  846.     o->PrevInList = LastInList;
  847.     LastInList = o;
  848. }
  849.  
  850. void LexList::Remove( LexObj* o )
  851. {
  852.     NumObj--;
  853.     if( o == FirstInList )
  854.         FirstInList = o->NextInList;
  855.     if( o == LastInList )
  856.         LastInList = o->PrevInList;
  857.     if( o->NextInList )
  858.         o->NextInList->PrevInList = o->PrevInList;
  859.     if( o->PrevInList )
  860.         o->PrevInList->NextInList = o->NextInList;
  861.     delete o;
  862. }
  863.  
  864. void LexList::print( ostream& o ) const
  865. {
  866.     for( LexObj* p = FirstInList;
  867.         p; p = p->NextInList )
  868.             o << *p << endl;
  869. }
  870.  
  871. void LexStack::Push( LexObj*o )
  872. {
  873.     if( ref )
  874.         o = new LexRef( o );
  875.     Add( o );
  876. }
  877.  
  878. void LexStack::Pop()
  879. {
  880.     LexObj *p = LastInList;
  881.     if( !p )
  882.         return;
  883.     NumObj--;
  884.     if( p == FirstInList )
  885.     {
  886.         p->NextInList =
  887.         p->PrevInList =
  888.         FirstInList =
  889.         LastInList = 0;
  890.         delete p;
  891.         return;
  892.     }
  893.     LastInList = LastInList->PrevInList;
  894.     p->PrevInList = LastInList->NextInList = 0;
  895.     delete p;
  896. }
  897.  
  898. LexObj *LexStack::Last() const
  899. {
  900.     if( !LastInList )
  901.         return 0;
  902.     return ref ? ((LexRef*)LastInList)->Obj() : LastInList;
  903. }
  904.  
  905. Lexema::Lexema( const char *s, int t ) : token( t )
  906. {
  907.     lex = new char[ strlen(s)+1 ];
  908.     strcpy( lex, s );
  909. }
  910.  
  911. Lexema::Lexema( const Lexema& l ) : token( l.token )
  912. {
  913.     lex = new char[ strlen(l.lex)+1 ];
  914.     strcpy( lex, l.lex );
  915. }
  916.  
  917. void Lexema::print( ostream& o ) const
  918. {
  919.     o << lex;
  920. }
  921.  
  922. Lexema::setYyLval( void *yylvalPtr )
  923. {
  924.     if( !yylvalPtr )
  925.     {
  926.         cerr << "Yylex error!" << endl;
  927.         return lxBadToken;
  928.     }
  929.     memcpy( yylvalPtr, yyData(), yySize());
  930.     return token;
  931. }
  932.  
  933.