Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/vm/input/tasm/tasm-scanner.ll

Go to the documentation of this file.
00001 %{
00002 /*
00003  * vm/input/tasm/tasm-scanner.ll
00004  * 
00005  * VM plaintext assembly scanner (lexical analysis). 
00006  * 
00007  * Copyright (c) 2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ 
00008  * 
00009  * This file may be distributed and/or modified under the terms of the 
00010  * GNU General Public License version 2 as published by the Free Software 
00011  * Foundation. (See COPYING.GPL for details.)
00012  * 
00013  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00014  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00015  * 
00016  */
00017 
00018 
00028 #include <lib/message/message.h>
00029 #include <lib/lex/basicparse.h>
00030 
00031 #include <vm/input/tasm/tasm-scanner.h>
00032 
00033 #include <ctype.h>
00034 
00035 
00036 #define YY_EXTRA_TYPE  class TextAsmScanner*
00037 
00038 // Special "trick": include scannerbase.cc for the first time: 
00039 #include <lib/lex/scannerbase.cc>
00040 
00041 // Get pointer where to store token info (string/integer/float val...)
00042 #define TOK()    ((TextAsmScanner::Token*)(yyextra->_tok_ptr()))
00043 
00044 // Check whether an instruction may be specified now. 
00045 #define CHECK_INST_ALLOWED  if(!yyextra->_CheckInstAllowed()) break;
00046 
00047 // Used at start of instruction to keep position info up-to-date. 
00048 #define PI_INST()  do { PI_LINE(); PI_START(); } while(0)
00049 
00050 // There some ugly macros for the code lexing. But IMO, code is more 
00051 // readable like that and there is no easy C++ replacement. 
00052 #define SWITCH_BSIL(idx,MNEMO) \
00053     switch(yytext[idx]) \
00054     { \
00055         case 'b':  inst=VM::INST::MNEMO ## B;  break; \
00056         case 's':  inst=VM::INST::MNEMO ## S;  break; \
00057         case 'i':  inst=VM::INST::MNEMO ## I;  break; \
00058         case 'l':  inst=VM::INST::MNEMO ## L;  break; \
00059         default: Assert(0); \
00060     }
00061 
00062 #define SWITCH_BSILFD(idx,MNEMO) \
00063     switch(yytext[idx]) \
00064     { \
00065         case 'b':  inst=VM::INST::MNEMO ## B;  break; \
00066         case 's':  inst=VM::INST::MNEMO ## S;  break; \
00067         case 'i':  inst=VM::INST::MNEMO ## I;  break; \
00068         case 'l':  inst=VM::INST::MNEMO ## L;  break; \
00069         case 'f':  inst=VM::INST::MNEMO ## F;  break; \
00070         case 'd':  inst=VM::INST::MNEMO ## D;  break; \
00071         default: Assert(0); \
00072     }
00073 
00074 #define SWITCH_BSILPAFD(idx,MNEMO) \
00075     switch(yytext[idx]) \
00076     { \
00077         case 'b':  inst=VM::INST::MNEMO ## B;  break; \
00078         case 's':  inst=VM::INST::MNEMO ## S;  break; \
00079         case 'i':  inst=VM::INST::MNEMO ## I;  break; \
00080         case 'l':  inst=VM::INST::MNEMO ## L;  break; \
00081         case 'p':  inst=VM::INST::MNEMO ## P;  break; \
00082         case 'a':  inst=VM::INST::MNEMO ## A;  break; \
00083         case 'f':  inst=VM::INST::MNEMO ## F;  break; \
00084         case 'd':  inst=VM::INST::MNEMO ## D;  break; \
00085         default: Assert(0); \
00086     }
00087 
00088 #define SWITCH_BSILF_D_(idx,MNEMO) \
00089     switch(yytext[idx]) \
00090     { \
00091         case 'b':  inst=VM::INST::MNEMO ## B;  break; \
00092         case 's':  inst=VM::INST::MNEMO ## S;  break; \
00093         case 'i':  inst=VM::INST::MNEMO ## I;  break; \
00094         case 'l':  inst=VM::INST::MNEMO ## L;  break; \
00095         case 'f': \
00096             switch(yytext[idx+1]) \
00097             { \
00098                 case '2':  inst=VM::INST::MNEMO ## F2;  break; \
00099                 case '3':  inst=VM::INST::MNEMO ## F3;  break; \
00100                 case '4':  inst=VM::INST::MNEMO ## F4;  break; \
00101                 default:   inst=VM::INST::MNEMO ## F;   break; \
00102             } \
00103             break; \
00104         case 'd': \
00105             switch(yytext[idx+1]) \
00106             { \
00107                 case '2':  inst=VM::INST::MNEMO ## D2;  break; \
00108                 case '3':  inst=VM::INST::MNEMO ## D3;  break; \
00109                 case '4':  inst=VM::INST::MNEMO ## D4;  break; \
00110                 default:   inst=VM::INST::MNEMO ## D;   break; \
00111             } \
00112             break; \
00113         default: Assert(0); \
00114     }
00115 
00116 #define SWITCH_BSILPAF_D_(idx,MNEMO) \
00117     switch(yytext[idx]) \
00118     { \
00119         case 'b':  inst=VM::INST::MNEMO ## B;  break; \
00120         case 's':  inst=VM::INST::MNEMO ## S;  break; \
00121         case 'i':  inst=VM::INST::MNEMO ## I;  break; \
00122         case 'l':  inst=VM::INST::MNEMO ## L;  break; \
00123         case 'p':  inst=VM::INST::MNEMO ## P;  break; \
00124         case 'a':  inst=VM::INST::MNEMO ## A;  break; \
00125         case 'f': \
00126             switch(yytext[idx+1]) \
00127             { \
00128                 case '2':  inst=VM::INST::MNEMO ## F2;  break; \
00129                 case '3':  inst=VM::INST::MNEMO ## F3;  break; \
00130                 case '4':  inst=VM::INST::MNEMO ## F4;  break; \
00131                 default:   inst=VM::INST::MNEMO ## F;   break; \
00132             } \
00133             break; \
00134         case 'd': \
00135             switch(yytext[idx+1]) \
00136             { \
00137                 case '2':  inst=VM::INST::MNEMO ## D2;  break; \
00138                 case '3':  inst=VM::INST::MNEMO ## D3;  break; \
00139                 case '4':  inst=VM::INST::MNEMO ## D4;  break; \
00140                 default:   inst=VM::INST::MNEMO ## D;   break; \
00141             } \
00142             break; \
00143         default: Assert(0); \
00144     }
00145 
00146 #define SWITCH_PARW(idx,MNEMO) \
00147     switch(yytext[idx]) \
00148     { \
00149         case 'p': \
00150             switch(yytext[idx+1]) \
00151             { \
00152                 case 'r':  inst=VM::INST::MNEMO ## PR;  break; \
00153                 case 'w':  inst=VM::INST::MNEMO ## PW;  break; \
00154                 default: Assert(0); \
00155             } \
00156             break; \
00157         case 'a': \
00158             switch(yytext[idx+1]) \
00159             { \
00160                 case 'r':  inst=VM::INST::MNEMO ## AR;  break; \
00161                 case 'w':  inst=VM::INST::MNEMO ## AW;  break; \
00162                 default: Assert(0); \
00163             } \
00164             break; \
00165         default: Assert(0); \
00166     }
00167 
00168 static void _CheckCmdEnd(const char *s)
00169 {
00170     while(isspace(*s))  ++s;
00171     Assert(*s=='#' || *s=='\0');
00172 }
00173 
00174 // These ugly defines make the flex-generated scanner use OUR memory 
00175 // (de)allocation routines. 
00176 #define malloc(p)        ALLOC<char>(p)
00177 #define realloc(p,size)  REALLOC<char>(p,size)
00178 #define free(p)          FREE<char>(p)
00179 
00180 %}
00181 
00182 /* Generate scanner file by using: 
00183  * flex -s tasm-scanner.ll    [works with flex >= 2.5.10] */
00184 
00185 %pointer
00186 %option 8bit
00187 %option reentrant
00188 /*%option bison-bridge*/
00189 /* option bison-locations does NOT calculate locations; just passes 
00190  * the structure to store the pos. Then, I don't need it. */
00191 /*%option bison-locations*/
00192 /*%option yylineno*/
00193 %option nodefault
00194 %option noyywrap
00195 %option stack
00196 %option prefix="TASM_"
00197 %option outfile="tasm-scanner.cc"
00198 /*%option header-file="tasm-scanner.hh"*/
00199 
00200 
00201 /* IN_CMT -> comment */
00202 %x IN_CMT
00203 /* IN_SKIPSPC -> skip until next (white) space [error recovery] */
00204 %x IN_SKIPSPC
00205 /* IN_SKIPSPC -> skip until next newline [error recovery] */
00206 %x IN_SKIPNL
00207 
00208 /* IN_SYM -> in object and symbol description */
00209 %s IN_SYM
00210 /* IN_GLOBAL -> in "vglobal"/"pglobal" within IN_SYM */
00211 %s IN_GLOBAL
00212 /* IN_VTABLE -> in "vtable" within IN_SYM */
00213 %s IN_VTBL
00214 /* IN_BASE -> in "base" block within IN_SYM */
00215 %s IN_BASE
00216 /* IN_SYMBS -> in "symbols" block within IN_SYM */
00217 %s IN_SYMBS
00218 /* IN_VARS -> in "size" (=variables) block within IN_SYM */
00219 %s IN_VARS
00220 
00221 /* IN_LOC -> in location description */
00222 %s IN_LOC
00223 
00224 /* IN_PRG -> in program code (instruction) section */
00225 %x IN_PRG
00226 
00227 /* IN_INFO -> in info section */
00228 %s IN_INFO
00229 
00230 
00231 name        [[:alpha:]_][[:alnum:]_]*
00232 uint        0?([[:digit:]]+|(x[[:xdigit:]]+))
00233 sint        [+-]?{uint}
00234 flt         [+-]?(((([[:digit:]]+\.?)|([[:digit:]]*\.[[:digit:]]+))([eE][+-]?[[:digit:]]+)?)|(0x(([[:xdigit:]]+\.?)|([[:xdigit:]]*\.[[:xdigit:]]+))p[[:digit:]]+))
00235 typeid      {sint}
00236 wspace      [[:space:]]+
00237 wspace_opt  {wspace}?
00238 stype       [bsilfd]|p({wspace_opt}">"{wspace_opt}{typeid})?|a[bsilfdp]
00239 fname       {name}?"~"[[:alnum:]_%]+
00240 ftype       s?("function"|"func"|"method"|"meth"|"vmethod"|"vmeth")
00241 codemark    "&"{wspace_opt}{uint}
00242 symref_ni   "$"{wspace_opt}{uint}
00243 symref_ie   "$"{wspace_opt}{sint}
00244 
00245 /* instruction spacing (between args) */
00246 is          [ \t]*
00247 /* instruction begin: */
00248 ib          \t
00249 /* instruction end: my include comment */
00250 ie          {is}("#"[^\n]*)?\n
00251 /* end of a label */
00252 label_end   {is}":"{ie}
00253 
00254 bsilpaf_d_  [bsilpa]|f[234]?|d[234]?
00255 bsilf_d_    [bsil]|f[234]?|d[234]?
00256 
00257 
00258 %%
00259 
00260     /*================================<COMMENT>===============================*/
00261 <IN_CMT>.*\n  {
00262         PI_LINE();
00263         PI_START();
00264         yy_pop_state(yyscanner);
00265     }
00266 <IN_CMT><<EOF>>  {
00267         PI_EOF();
00268         PI_TOK();
00269         PI_START();
00270         yy_pop_state(yyscanner);
00271         return(0);
00272     }
00273 <IN_CMT>.  {
00274         /* This rule will normally not match (only if terminated by EOF). */
00275         PI_CHAR(yytext[0]);
00276         PI_START();
00277     }
00278 
00279     /*==========================<SKIP until next SPACE>=======================*/
00280 <IN_SKIPSPC>[^[:space:]]*{wspace}  {
00281         PI_STR(yytext,yyleng);
00282         yy_pop_state(yyscanner);
00283         PI_START();
00284     }
00285 <IN_SKIPSPC>.  {
00286         /* This rule will normally not match (only if terminated by EOF). */
00287         PI_CHAR(yytext[0]);
00288         yy_pop_state(yyscanner);
00289         PI_START();
00290     }
00291 
00292     /*=========================<SKIP until next NEWLINE>======================*/
00293 <IN_SKIPNL>.*\n  {
00294         PI_LINE();
00295         yy_pop_state(yyscanner);
00296         PI_START();
00297     }
00298 <IN_SKIPNL>.  {
00299         /* This rule will normally not match (only if terminated by EOF). */
00300         PI_CHAR(yytext[0]);
00301         yy_pop_state(yyscanner);
00302         PI_START();
00303     }
00304 
00305     /*======================<OBJECT / SYMBOL DESCRIPTION>=====================*/
00306 <IN_INFO>"abiversion"{wspace}[[:alnum:]_\-/.]+  {
00307         PI_STR(yytext,yyleng);
00308         TOK()->str_val=yyextra->_ParseNameStr(yytext+10,yytext+yyleng);
00309         return(TextAsmScanner::TI_abivers);
00310     }
00311     
00312     /*==============================<INFO SECTION>============================*/
00313 <IN_SYM>"namespace"{wspace}{name}  {
00314         PI_STR(yytext,yyleng);
00315         TOK()->str_val=yyextra->_ParseNameStr(yytext+9,yytext+yyleng);
00316         return(TextAsmScanner::TS_namespace);
00317     }
00318 <IN_SYM>"class"{wspace_opt}{typeid}{wspace_opt}{name}  {
00319         PI_STR(yytext,yyleng);
00320         const char *s=yyextra->_ParseInt(&TOK()->tid,yytext+5);
00321         TOK()->str_val=yyextra->_ParseNameStr(s,yytext+yyleng);
00322         return(TextAsmScanner::TS_class);
00323     }
00324 <IN_SYM>"base"{wspace}{uint}  {
00325         PI_STR(yytext,yyleng);
00326         const char *s=yyextra->_ParseInt(&TOK()->num,yytext+4);
00327         Assert(!*s);   // lexer rules ensure that
00328         yy_push_state(IN_BASE,yyscanner);
00329         return(TextAsmScanner::TS_base);
00330     }
00331 <IN_SYM>"size"{wspace}{uint}{wspace}{uint}({wspace_opt}","{wspace_opt}{uint})?  {
00332         PI_STR(yytext,yyleng);
00333         const char *s=yyextra->_ParseInt(&TOK()->size,yytext+4);
00334                     s=yyextra->_ParseInt(&TOK()->num_p,s);
00335         if(*s)
00336         {
00337             while(isspace(*s))  ++s;
00338             Assert(*s==',');   // lexer rules ensure that
00339             s=yyextra->_ParseInt(&TOK()->num_v,s+1);
00340         }
00341         else
00342         {  TOK()->num_v=0;  }
00343         Assert(!*s);   // lexer rules ensure that
00344         yy_push_state(IN_VARS,yyscanner);
00345         return(TextAsmScanner::TS_size);
00346     }
00347 <IN_SYM>"virtual"{wspace}{uint}  {
00348         PI_STR(yytext,yyleng);
00349         const char *s=yyextra->_ParseInt(&TOK()->num,yytext+7);
00350         Assert(!*s);   // lexer rules ensure that
00351         return(TextAsmScanner::TS_virtual);
00352     }
00353 <IN_SYM>"vtable"{wspace}{uint}  {
00354         PI_STR(yytext,yyleng);
00355         const char *s=yyextra->_ParseInt(&TOK()->num,yytext+6);
00356         Assert(!*s);   // lexer rules ensure that
00357         yy_push_state(IN_VTBL,yyscanner);
00358         return(TextAsmScanner::TS_vtable);
00359     }
00360 <IN_SYM>"symbols"  {
00361         PI_STR(yytext,yyleng);
00362         yy_push_state(IN_SYMBS,yyscanner);
00363         return(TextAsmScanner::TS_symbols);
00364     }
00365 <IN_SYM>[vp]"global"{wspace}{uint}  {
00366         PI_TOK();
00367         const char *s=yyextra->_ParseInt(&TOK()->size,yytext+7);
00368         Assert(!*s);   // lexer rules ensure that
00369         yy_push_state(IN_GLOBAL,yyscanner);
00370         switch(yytext[0])
00371         {
00372             case 'v':  return(TextAsmScanner::TS_vglobal);
00373             case 'p':  return(TextAsmScanner::TS_pglobal);
00374             default:  Assert(0);
00375         } // not reached. 
00376     }
00377 <IN_SYM>"pglobal"  {
00378         PI_TOK();
00379         yy_push_state(IN_GLOBAL,yyscanner);
00380         return(TextAsmScanner::TS_pglobal);
00381     }
00382 <IN_SYM>";"  {
00383         PI_TOK();
00384         return(TextAsmScanner::T_pop);
00385     }
00386 
00387 <IN_GLOBAL>{stype}{wspace}{uint}{wspace_opt}{symref_ni}  {
00388         PI_STR(yytext,yyleng);
00389         const char *s=yyextra->_ParseTypeSpec(&TOK()->t,yytext);
00390                     s=yyextra->_ParseInt(&TOK()->off,s);
00391                     s=yyextra->_ParseInt(&TOK()->symref,s,'$');
00392         Assert(!*s);   // lexer rules ensure that
00393         return(TextAsmScanner::TS_globvar);
00394     }
00395 <IN_GLOBAL>";"  {
00396         PI_TOK();
00397         yy_pop_state(yyscanner);
00398         return(TextAsmScanner::T_pop);
00399     }
00400 
00401 <IN_VTBL>{symref_ie}  {
00402         PI_TOK();
00403         const char *s=yyextra->_ParseInt(&TOK()->symref,yytext,'$');
00404         Assert(!*s);   // lexer rules ensure that
00405         return(TextAsmScanner::TS_symref);
00406     }
00407 <IN_VTBL>";"  {
00408         PI_TOK();
00409         yy_pop_state(yyscanner);
00410         return(TextAsmScanner::T_pop);
00411     }
00412 
00413 <IN_BASE>","{wspace_opt}{typeid}{wspace}{uint}  {
00414         PI_STR(yytext,yyleng);
00415         const char *s=yyextra->_ParseInt(&TOK()->tid,yytext+1);
00416                     s=yyextra->_ParseInt(&TOK()->off,s);
00417         Assert(!*s);   // lexer rules ensure that
00418         return(TextAsmScanner::TS_baseent);
00419     }
00420 <IN_BASE>";"  {
00421         PI_TOK();
00422         yy_pop_state(yyscanner);
00423         return(TextAsmScanner::T_pop);
00424     }
00425 
00426 <IN_VARS>{stype}{wspace}{uint}({wspace_opt}","{wspace_opt}{name})?  {
00427         // type offset and optional name
00428         PI_STR(yytext,yyleng);
00429         const char *s=yyextra->_ParseTypeSpec(&TOK()->t,yytext);
00430                     s=yyextra->_ParseInt(&TOK()->off,s);
00431         while(isspace(*s))  ++s;
00432         if(*s==',')
00433         {  TOK()->str_val=yyextra->_ParseNameStr(s+1,yytext+yyleng);  }
00434         else Assert(!*s);   // lexer rules ensure that
00435         return(TextAsmScanner::TS_varent);
00436     }
00437 <IN_VARS>";"  {
00438         PI_TOK();
00439         yy_pop_state(yyscanner);
00440         return(TextAsmScanner::T_pop);
00441     }
00442 
00443 <IN_SYMBS>{ftype}{wspace_opt}{symref_ni}{wspace}{fname}  {
00444         PI_STR(yytext,yyleng);
00445         
00446         const char *s=yytext;
00447         if(*s=='s')
00448         {  TOK()->ftype=s[1]-'a'+'A';  }  // convert to uppercase: non-exported
00449         else
00450         {  TOK()->ftype=*s;  }
00451         while(*s!='$')  ++s;
00452         
00453         s=yyextra->_ParseInt(&TOK()->symref,s,'$');
00454         TOK()->str_val=yyextra->_ParseNameStr(s,yytext+yyleng);
00455         return(TextAsmScanner::TS_funcsym);
00456     }
00457 <IN_SYMBS>{stype}{wspace_opt}{symref_ni}{wspace}{name}  {
00458         PI_STR(yytext,yyleng);
00459         const char *s=yyextra->_ParseTypeSpec(&TOK()->t,yytext);
00460                     s=yyextra->_ParseInt(&TOK()->symref,s,'$');
00461         TOK()->str_val=yyextra->_ParseNameStr(s,yytext+yyleng);
00462         return(TextAsmScanner::TS_varsym);
00463     }
00464 <IN_SYMBS>";"  {
00465         PI_TOK();
00466         yy_pop_state(yyscanner);
00467         return(TextAsmScanner::T_pop);
00468     }
00469 
00470     /*==========================<LOCATION DESCRIPTION>========================*/
00471 <IN_LOC>.  {
00472         CritAssert(!"location desc not implemented");
00473     }
00474 
00475     /*==========================<PROGRAM INSTRUCTIONS>========================*/
00476     /* each of these rules matches one line. */
00477 <IN_PRG>".init"{label_end}  {
00478         PI_LINE();
00479         TOK()->str_val=yyextra->_ParseNameStr(yytext,yytext+5);
00480         return(TextAsmScanner::TP_slabel);
00481     }
00482 <IN_PRG>".start"{label_end}  {
00483         PI_LINE();
00484         TOK()->str_val=yyextra->_ParseNameStr(yytext,yytext+6);
00485         return(TextAsmScanner::TP_slabel);
00486     }
00487 <IN_PRG>"&"{uint}{label_end}  {
00488         PI_LINE();
00489         yyextra->_ParseInt(&TOK()->codemark,yytext+1);
00490         return(TextAsmScanner::TP_mlabel);
00491     }
00492 <IN_PRG>"$"{uint}{label_end}  {
00493         PI_LINE();
00494         yyextra->_ParseInt(&TOK()->symref,yytext+1);
00495         return(TextAsmScanner::TP_rlabel);
00496     }
00497     
00498 <IN_PRG>{ib}"nop"{ie}  {
00499         PI_INST(); CHECK_INST_ALLOWED
00500         yyextra->InsnStorage()->append(VM::INST::NOP);
00501     }
00502 <IN_PRG>{ib}"hlt"{ie}  {
00503         PI_INST(); CHECK_INST_ALLOWED
00504         yyextra->InsnStorage()->append(VM::INST::HLT);
00505     }
00506     
00507 <IN_PRG>{ib}"plb"{is}{sint}({is}{uint})?{ie}  {
00508         PI_INST(); CHECK_INST_ALLOWED
00509         const char *s=yytext+4;
00510         uint8 a,z;
00511         s=yyextra->_ParseInt(&a,s);
00512         s=yyextra->_ParseInt0(&z,s);
00513         yyextra->InsnStorage()->append(VM::INST::PLB,a,z);
00514         _CheckCmdEnd(s);
00515     }
00516 <IN_PRG>{ib}"pls"{is}{sint}({is}{uint})?{ie}  {
00517         PI_INST(); CHECK_INST_ALLOWED
00518         const char *s=yytext+4;
00519         uint8 z;
00520         uint16 a;
00521         s=yyextra->_ParseInt(&a,s);
00522         s=yyextra->_ParseInt0(&z,s);
00523         yyextra->InsnStorage()->append(VM::INST::PLS,a,z);
00524         _CheckCmdEnd(s);
00525     }
00526 <IN_PRG>{ib}"pli"{is}{sint}({is}{uint})?{ie}  {
00527         PI_INST(); CHECK_INST_ALLOWED
00528         const char *s=yytext+4;
00529         uint8 z;
00530         uint32 a;
00531         s=yyextra->_ParseInt(&a,s);
00532         s=yyextra->_ParseInt0(&z,s);
00533         yyextra->InsnStorage()->append(VM::INST::PLI,a,z);
00534         _CheckCmdEnd(s);
00535     }
00536 <IN_PRG>{ib}"pll"{is}{sint}({is}{uint})?{ie}  {
00537         PI_INST(); CHECK_INST_ALLOWED
00538         const char *s=yytext+4;
00539         uint8 z;
00540         uint64 a;
00541         s=yyextra->_ParseInt(&a,s);
00542         s=yyextra->_ParseInt0(&z,s);
00543         yyextra->InsnStorage()->append(VM::INST::PLL,a,z);
00544         _CheckCmdEnd(s);
00545     }
00546 <IN_PRG>{ib}"plf"{is}{flt}({is}{uint})?{ie}  {
00547         PI_INST(); CHECK_INST_ALLOWED
00548         const char *s=yytext+4;
00549         uint8 z;
00550         flt a;
00551         s=yyextra->_ParseFloat(&a,s);
00552         s=yyextra->_ParseInt0(&z,s);
00553         yyextra->InsnStorage()->append(VM::INST::PLF,a,z);
00554         _CheckCmdEnd(s);
00555     }
00556 <IN_PRG>{ib}"pld"{is}{flt}({is}{uint})?{ie}  {
00557         PI_INST(); CHECK_INST_ALLOWED
00558         const char *s=yytext+4;
00559         uint8 z;
00560         dbl a;
00561         s=yyextra->_ParseFloat(&a,s);
00562         s=yyextra->_ParseInt0(&z,s);
00563         yyextra->InsnStorage()->append(VM::INST::PLD,a,z);
00564         _CheckCmdEnd(s);
00565     }
00566 <IN_PRG>{ib}"plf2"({is}{flt}){2}({is}{uint})?{ie}  {
00567         PI_INST(); CHECK_INST_ALLOWED
00568         const char *s=yytext+5;
00569         uint8 z;
00570         flt a,b;
00571         s=yyextra->_ParseFloat(&a,s);
00572         s=yyextra->_ParseFloat(&b,s);
00573         s=yyextra->_ParseInt0(&z,s);
00574         yyextra->InsnStorage()->append(VM::INST::PLF2,a,b,z);
00575         _CheckCmdEnd(s);
00576     }
00577 <IN_PRG>{ib}"pld2"({is}{flt}){2}({is}{uint})?{ie}  {
00578         PI_INST(); CHECK_INST_ALLOWED
00579         const char *s=yytext+5;
00580         uint8 z;
00581         dbl a,b;
00582         s=yyextra->_ParseFloat(&a,s);
00583         s=yyextra->_ParseFloat(&b,s);
00584         s=yyextra->_ParseInt0(&z,s);
00585         yyextra->InsnStorage()->append(VM::INST::PLD2,a,b,z);
00586         _CheckCmdEnd(s);
00587     }
00588 <IN_PRG>{ib}"plf3"({is}{flt}){3}({is}{uint})?{ie}  {
00589         PI_INST(); CHECK_INST_ALLOWED
00590         const char *s=yytext+5;
00591         uint8 z;
00592         flt a,b,c;
00593         s=yyextra->_ParseFloat(&a,s);
00594         s=yyextra->_ParseFloat(&b,s);
00595         s=yyextra->_ParseFloat(&c,s);
00596         s=yyextra->_ParseInt0(&z,s);
00597         yyextra->InsnStorage()->append(VM::INST::PLF3,a,b,c,z);
00598         _CheckCmdEnd(s);
00599     }
00600 <IN_PRG>{ib}"pld3"({is}{flt}){3}({is}{uint})?{ie}  {
00601         PI_INST(); CHECK_INST_ALLOWED
00602         const char *s=yytext+5;
00603         uint8 z;
00604         dbl a,b,c;
00605         s=yyextra->_ParseFloat(&a,s);
00606         s=yyextra->_ParseFloat(&b,s);
00607         s=yyextra->_ParseFloat(&c,s);
00608         s=yyextra->_ParseInt0(&z,s);
00609         yyextra->InsnStorage()->append(VM::INST::PLD3,a,b,c,z);
00610         _CheckCmdEnd(s);
00611     }
00612 <IN_PRG>{ib}"plf4"({is}{flt}){4}({is}{uint})?{ie}  {
00613         PI_INST(); CHECK_INST_ALLOWED
00614         const char *s=yytext+5;
00615         uint8 z;
00616         flt a,b,c,d;
00617         s=yyextra->_ParseFloat(&a,s);
00618         s=yyextra->_ParseFloat(&b,s);
00619         s=yyextra->_ParseFloat(&c,s);
00620         s=yyextra->_ParseFloat(&d,s);
00621         s=yyextra->_ParseInt0(&z,s);
00622         yyextra->InsnStorage()->append(VM::INST::PLF4,a,b,c,d,z);
00623         _CheckCmdEnd(s);
00624     }
00625 <IN_PRG>{ib}"pld4"({is}{flt}){4}({is}{uint})?{ie}  {
00626         PI_INST(); CHECK_INST_ALLOWED
00627         const char *s=yytext+5;
00628         uint8 z;
00629         dbl a,b,c,d;
00630         s=yyextra->_ParseFloat(&a,s);
00631         s=yyextra->_ParseFloat(&b,s);
00632         s=yyextra->_ParseFloat(&c,s);
00633         s=yyextra->_ParseFloat(&d,s);
00634         s=yyextra->_ParseInt0(&z,s);
00635         yyextra->InsnStorage()->append(VM::INST::PLD4,a,b,c,d,z);
00636         _CheckCmdEnd(s);
00637     }
00638 
00639 <IN_PRG>{ib}"pln"{ie}  {
00640         PI_INST(); CHECK_INST_ALLOWED
00641         yyextra->InsnStorage()->append(VM::INST::PLN);
00642     }
00643 
00644 <IN_PRG>{ib}"ps"{bsilpaf_d_}{is}{uint}({is}{uint})?{ie}  {
00645         PI_INST(); CHECK_INST_ALLOWED
00646         const char *s=yytext+4;  if(!isspace(*s)) ++s;
00647         uint8 z;
00648         VM::Offset a;
00649         s=yyextra->_ParseInt(&a,s);
00650         s=yyextra->_ParseInt0(&z,s);
00651         _CheckCmdEnd(s);
00652         VM::INST::IID inst;
00653         SWITCH_BSILPAF_D_(3,PS)
00654         yyextra->InsnStorage()->append(inst,a,z);
00655     }
00656 <IN_PRG>{ib}"ps"{bsilpaf_d_}{is}"-"{uint}({is}{uint})?{ie}  {
00657         PI_INST(); CHECK_INST_ALLOWED
00658         // It seems we actually do not need this instruction. 
00659         CritAssert(!"ps* -adr [inc] not implemented");
00660     }
00661 
00662 <IN_PRG>{ib}"pg"{bsilpaf_d_}{is}"$"{sint}({is}{uint})?{ie}  {
00663         PI_INST(); CHECK_INST_ALLOWED
00664         const char *s=yytext+4;  if(!isspace(*s)) ++s;
00665         uint8 z;
00666         VM::SymRef a;
00667         s=yyextra->_ParseInt(&a,s,'$');
00668         s=yyextra->_ParseInt0(&z,s);
00669         _CheckCmdEnd(s);
00670         VM::INST::IID inst;
00671         SWITCH_BSILPAF_D_(3,PG)
00672         yyextra->InsnStorage()->append(inst,a,z);
00673     }
00674 <IN_PRG>{ib}"pg"{bsilpaf_d_}{is}{uint}({is}{uint})?{ie}  {
00675         PI_INST(); CHECK_INST_ALLOWED
00676         // We do not need this instruction if we use non-exported symbols. 
00677         // We could use it, however, to make linking a bit faster. 
00678         CritAssert(!"pg* offset [inc] not implemented");
00679     }
00680 
00681 <IN_PRG>{ib}"pf"{bsilf_d_}{is}{uint}({is}{uint})?{ie}  {
00682         PI_INST(); CHECK_INST_ALLOWED
00683         const char *s=yytext+4;  if(!isspace(*s)) ++s;
00684         uint8 z;
00685         VM::Offset a;
00686         s=yyextra->_ParseInt(&a,s);
00687         s=yyextra->_ParseInt0(&z,s);
00688         _CheckCmdEnd(s);
00689         VM::INST::IID inst;
00690         SWITCH_BSILF_D_(3,PF)
00691         yyextra->InsnStorage()->append(inst,a,z);
00692     }
00693 <IN_PRG>{ib}"pf"[pa][rw]{is}{uint}({is}{uint})?{ie}  {
00694         PI_INST(); CHECK_INST_ALLOWED
00695         const char *s=yytext+5;
00696         uint8 z;
00697         VM::Offset a;
00698         s=yyextra->_ParseInt(&a,s);
00699         s=yyextra->_ParseInt0(&z,s);
00700         _CheckCmdEnd(s);
00701         VM::INST::IID inst;
00702         SWITCH_PARW(3,PF)
00703         yyextra->InsnStorage()->append(inst,a,z);
00704     }
00705 
00706 <IN_PRG>{ib}"pa"[bsilfd]{ie}  {
00707         PI_INST(); CHECK_INST_ALLOWED
00708         VM::INST::IID inst;
00709         SWITCH_BSILFD(3,PA)
00710         yyextra->InsnStorage()->append(inst);
00711     }
00712 <IN_PRG>{ib}"pa"[pa][rw]{ie}  {
00713         PI_INST(); CHECK_INST_ALLOWED
00714         VM::INST::IID inst;
00715         SWITCH_PARW(3,PA)
00716         yyextra->InsnStorage()->append(inst);
00717     }
00718 
00719 <IN_PRG>{ib}"pi"{is}{uint}{ie}  {
00720         PI_INST(); CHECK_INST_ALLOWED
00721         const char *s=yytext+3;
00722         uint32 a;
00723         s=yyextra->_ParseInt(&a,s);
00724         _CheckCmdEnd(s);
00725         yyextra->InsnStorage()->append(VM::INST::PI,a);
00726     }
00727 
00728 <IN_PRG>{ib}"popv"{is}{uint}{ie}  {
00729         PI_INST(); CHECK_INST_ALLOWED
00730         const char *s=yytext+5;
00731         uint32 a;
00732         s=yyextra->_ParseInt(&a,s);
00733         _CheckCmdEnd(s);
00734         yyextra->InsnStorage()->append(VM::INST::POPV,a);
00735     }
00736 <IN_PRG>{ib}"popp"{is}{uint}{ie}  {
00737         PI_INST(); CHECK_INST_ALLOWED
00738         const char *s=yytext+5;
00739         uint32 a;
00740         s=yyextra->_ParseInt(&a,s);
00741         _CheckCmdEnd(s);
00742         yyextra->InsnStorage()->append(VM::INST::POPP,a);
00743     }
00744 
00745 <IN_PRG>{ib}"ss"{bsilpaf_d_}{is}{uint}({is}{uint})?{ie}  {
00746         PI_INST(); CHECK_INST_ALLOWED
00747         const char *s=yytext+4;  if(!isspace(*s)) ++s;
00748         uint8 z;
00749         VM::Offset a;
00750         s=yyextra->_ParseInt(&a,s);
00751         s=yyextra->_ParseInt0(&z,s);
00752         _CheckCmdEnd(s);
00753         VM::INST::IID inst;
00754         SWITCH_BSILPAF_D_(3,SS)
00755         yyextra->InsnStorage()->append(inst,a,z);
00756     }
00757 <IN_PRG>{ib}"ss"{bsilpaf_d_}{is}"-"{uint}({is}{uint})?{ie}  {
00758         PI_INST(); CHECK_INST_ALLOWED
00759         // It seems we actually do not need this instruction. 
00760         CritAssert(!"ss* -adr [inc] not implemented");
00761     }
00762 
00763 <IN_PRG>{ib}"sg"{bsilpaf_d_}{is}"$"{sint}({is}{uint})?{ie}  {
00764         PI_INST(); CHECK_INST_ALLOWED
00765         const char *s=yytext+4;  if(!isspace(*s)) ++s;
00766         uint8 z;
00767         VM::SymRef a;
00768         s=yyextra->_ParseInt(&a,s,'$');
00769         s=yyextra->_ParseInt0(&z,s);
00770         _CheckCmdEnd(s);
00771         VM::INST::IID inst;
00772         SWITCH_BSILPAF_D_(3,SG)
00773         yyextra->InsnStorage()->append(inst,a,z);
00774     }
00775 <IN_PRG>{ib}"sg"{bsilpaf_d_}{is}{uint}({is}{uint})?{ie}  {
00776         PI_INST(); CHECK_INST_ALLOWED
00777         // We do not need this instruction if we use non-exported symbols. 
00778         // We could use it, however, to make linking a bit faster. 
00779         CritAssert(!"sg* offset [inc] not implemented");
00780     }
00781 
00782 <IN_PRG>{ib}"sf"{bsilpaf_d_}{is}{uint}({is}{uint})?{ie}  {
00783         PI_INST(); CHECK_INST_ALLOWED
00784         const char *s=yytext+4;  if(!isspace(*s)) ++s;
00785         VM::Offset a;
00786         uint8 z;
00787         s=yyextra->_ParseInt(&a,s);
00788         s=yyextra->_ParseInt0(&z,s);
00789         _CheckCmdEnd(s);
00790         VM::INST::IID inst;
00791         SWITCH_BSILPAF_D_(3,SF)
00792         yyextra->InsnStorage()->append(inst,a,z);
00793     }
00794 
00795 <IN_PRG>{ib}"sa"[bsilpafd]{ie}  {
00796         PI_INST(); CHECK_INST_ALLOWED
00797         VM::INST::IID inst;
00798         SWITCH_BSILPAFD(3,SA)
00799         yyextra->InsnStorage()->append(inst);
00800     }
00801 
00802 <IN_PRG>{ib}"add"{bsilf_d_}{ie}  {
00803         PI_INST(); CHECK_INST_ALLOWED
00804         VM::INST::IID inst;
00805         SWITCH_BSILF_D_(4,ADD)
00806         yyextra->InsnStorage()->append(inst);
00807     }
00808 <IN_PRG>{ib}"sub"{bsilf_d_}{ie}  {
00809         PI_INST(); CHECK_INST_ALLOWED
00810         VM::INST::IID inst;
00811         SWITCH_BSILF_D_(4,SUB)
00812         yyextra->InsnStorage()->append(inst);
00813     }
00814 
00815 <IN_PRG>{ib}"mul"([bsilfd]){ie}  {
00816         PI_INST(); CHECK_INST_ALLOWED
00817         VM::INST::IID inst;
00818         SWITCH_BSILFD(4,MUL)
00819         yyextra->InsnStorage()->append(inst);
00820     }
00821 <IN_PRG>{ib}"div"([bsilfd]){ie}  {
00822         PI_INST(); CHECK_INST_ALLOWED
00823         VM::INST::IID inst;
00824         SWITCH_BSILFD(4,DIV)
00825         yyextra->InsnStorage()->append(inst);
00826     }
00827 <IN_PRG>{ib}"mod"([bsilfd]){ie}  {
00828         PI_INST(); CHECK_INST_ALLOWED
00829         VM::INST::IID inst;
00830         SWITCH_BSILFD(4,MOD)
00831         yyextra->InsnStorage()->append(inst);
00832     }
00833 
00834 <IN_PRG>{ib}"neg"{bsilf_d_}{ie}  {
00835         PI_INST(); CHECK_INST_ALLOWED
00836         VM::INST::IID inst;
00837         SWITCH_BSILF_D_(4,NEG)
00838         yyextra->InsnStorage()->append(inst);
00839     }
00840 
00841 <IN_PRG>{ib}"eq"{bsilpaf_d_}{ie}  {
00842         PI_INST(); CHECK_INST_ALLOWED
00843         VM::INST::IID inst;
00844         SWITCH_BSILPAF_D_(3,EQ)
00845         yyextra->InsnStorage()->append(inst);
00846     }
00847 
00848 <IN_PRG>{ib}"and"[bsil]{ie}  {
00849         PI_INST(); CHECK_INST_ALLOWED
00850         VM::INST::IID inst;
00851         SWITCH_BSIL(4,AND)
00852         yyextra->InsnStorage()->append(inst);
00853     }
00854 <IN_PRG>{ib}"or"[bsil]{ie}  {
00855         PI_INST(); CHECK_INST_ALLOWED
00856         VM::INST::IID inst;
00857         SWITCH_BSIL(3,OR)
00858         yyextra->InsnStorage()->append(inst);
00859     }
00860 <IN_PRG>{ib}"xor"[bsil]{ie}  {
00861         PI_INST(); CHECK_INST_ALLOWED
00862         VM::INST::IID inst;
00863         SWITCH_BSIL(4,XOR)
00864         yyextra->InsnStorage()->append(inst);
00865     }
00866 
00867 <IN_PRG>{ib}"shl"[bsil]{ie}  {
00868         PI_INST(); CHECK_INST_ALLOWED
00869         VM::INST::IID inst;
00870         SWITCH_BSIL(4,SHL)
00871         yyextra->InsnStorage()->append(inst);
00872     }
00873 <IN_PRG>{ib}"shr"[bsil]{ie}  {
00874         PI_INST(); CHECK_INST_ALLOWED
00875         VM::INST::IID inst;
00876         SWITCH_BSIL(4,SHR)
00877         yyextra->InsnStorage()->append(inst);
00878     }
00879 
00880 <IN_PRG>{ib}"incs"[bsilfd]{is}{uint}{ie}  {
00881         PI_INST(); CHECK_INST_ALLOWED
00882         const char *s=yytext+6;
00883         VM::Offset a;
00884         s=yyextra->_ParseInt(&a,s);
00885         _CheckCmdEnd(s);
00886         VM::INST::IID inst;
00887         SWITCH_BSILFD(5,INCS)
00888         yyextra->InsnStorage()->append(inst,a);
00889     }
00890 <IN_PRG>{ib}"decs"[bsilfd]{is}{uint}{ie}  {
00891         PI_INST(); CHECK_INST_ALLOWED
00892         const char *s=yytext+6;
00893         VM::Offset a;
00894         s=yyextra->_ParseInt(&a,s);
00895         _CheckCmdEnd(s);
00896         VM::INST::IID inst;
00897         SWITCH_BSILFD(5,DECS)
00898         yyextra->InsnStorage()->append(inst,a);
00899     }
00900 
00901 <IN_PRG>{ib}"jmp"{is}"&"{uint}{ie}  {
00902         PI_INST(); CHECK_INST_ALLOWED
00903         const char *s=yytext+4;
00904         VM::CodeMark a;
00905         s=yyextra->_ParseInt(&a,s,'&');
00906         _CheckCmdEnd(s);
00907         yyextra->InsnStorage()->append(VM::INST::JMP,a);
00908     }
00909 <IN_PRG>{ib}"jn"[bsilpafd]{is}"&"{uint}{ie}  {
00910         PI_INST(); CHECK_INST_ALLOWED
00911         const char *s=yytext+4;
00912         VM::CodeMark a;
00913         s=yyextra->_ParseInt(&a,s,'&');
00914         _CheckCmdEnd(s);
00915         VM::INST::IID inst;
00916         SWITCH_BSILPAFD(3,JN)
00917         yyextra->InsnStorage()->append(inst,a);
00918     }
00919 <IN_PRG>{ib}"jz"[bsilpafd]{is}"&"{uint}{ie}  {
00920         PI_INST(); CHECK_INST_ALLOWED
00921         const char *s=yytext+4;
00922         VM::CodeMark a;
00923         s=yyextra->_ParseInt(&a,s,'&');
00924         _CheckCmdEnd(s);
00925         VM::INST::IID inst;
00926         SWITCH_BSILPAFD(3,JZ)
00927         yyextra->InsnStorage()->append(inst,a);
00928     }
00929 
00930 <IN_PRG>{ib}"anew"[bsilpafd]{ie}  {
00931         PI_INST(); CHECK_INST_ALLOWED
00932         uint8 a=0,b=0;
00933         switch(yytext[5])
00934         {
00935             case 'b':  a=1;  break;
00936             case 's':  a=2;  break;
00937             case 'i':  a=3;  break;
00938             case 'l':  a=4;  break;
00939             case 'p':  a=5;  break;
00940             case 'a':  a=6;  break;
00941             case 'f':  a=7;  break;
00942             case 'd':  a=8;  break;
00943             default: Assert(0);
00944         }
00945         yyextra->InsnStorage()->append(VM::INST::ANEW,a,b);
00946     }
00947 
00948 <IN_PRG>{ib}"asize"{ie}  {
00949         PI_INST(); CHECK_INST_ALLOWED
00950         yyextra->InsnStorage()->append(VM::INST::ASIZE);
00951     }
00952 
00953 <IN_PRG>{ib}"onew"{is}{typeid}{ie}  {
00954         PI_INST(); CHECK_INST_ALLOWED
00955         const char *s=yytext+5;
00956         VM::TypeID a;
00957         s=yyextra->_ParseInt(&a,s);
00958         _CheckCmdEnd(s);
00959         yyextra->InsnStorage()->append(VM::INST::ONEW,a);
00960     }
00961 
00962 <IN_PRG>{ib}"acpy"{ie}  {
00963         PI_INST(); CHECK_INST_ALLOWED
00964         yyextra->InsnStorage()->append(VM::INST::ACPY);
00965     }
00966 <IN_PRG>{ib}"ocpy"{ie}  {
00967         PI_INST(); CHECK_INST_ALLOWED
00968         yyextra->InsnStorage()->append(VM::INST::OCPY);
00969     }
00970 
00971 <IN_PRG>{ib}"cvb"[bsilfd]{ie}  {
00972         PI_INST(); CHECK_INST_ALLOWED
00973         VM::INST::IID inst;
00974         SWITCH_BSILFD(4,CVB)
00975         yyextra->InsnStorage()->append(inst);
00976     }
00977 <IN_PRG>{ib}"cvs"[bsilfd]{ie}  {
00978         PI_INST(); CHECK_INST_ALLOWED
00979         VM::INST::IID inst;
00980         SWITCH_BSILFD(4,CVS)
00981         yyextra->InsnStorage()->append(inst);
00982     }
00983 <IN_PRG>{ib}"cvi"[bsilfd]{ie}  {
00984         PI_INST(); CHECK_INST_ALLOWED
00985         VM::INST::IID inst;
00986         SWITCH_BSILFD(4,CVI)
00987         yyextra->InsnStorage()->append(inst);
00988     }
00989 <IN_PRG>{ib}"cvl"[bsilfd]{ie}  {
00990         PI_INST(); CHECK_INST_ALLOWED
00991         VM::INST::IID inst;
00992         SWITCH_BSILFD(4,CVL)
00993         yyextra->InsnStorage()->append(inst);
00994     }
00995 <IN_PRG>{ib}"cvf"[bsilfd]{ie}  {
00996         PI_INST(); CHECK_INST_ALLOWED
00997         VM::INST::IID inst;
00998         SWITCH_BSILFD(4,CVF)
00999         yyextra->InsnStorage()->append(inst);
01000     }
01001 <IN_PRG>{ib}"cvd"[bsilfd]{ie}  {
01002         PI_INST(); CHECK_INST_ALLOWED
01003         VM::INST::IID inst;
01004         SWITCH_BSILFD(4,CVD)
01005         yyextra->InsnStorage()->append(inst);
01006     }
01007 
01008 <IN_PRG>{ib}"call"{is}"$"{sint}{ie}  {
01009         PI_INST(); CHECK_INST_ALLOWED
01010         const char *s=yytext+5;
01011         VM::SymRef a;
01012         s=yyextra->_ParseInt(&a,s,'$');
01013         _CheckCmdEnd(s);
01014         yyextra->InsnStorage()->append(VM::INST::CALL,a);
01015     }
01016 <IN_PRG>{ib}"mcall"{is}"$"{sint}{ie}  {
01017         PI_INST(); CHECK_INST_ALLOWED
01018         const char *s=yytext+6;
01019         VM::SymRef a;
01020         s=yyextra->_ParseInt(&a,s,'$');
01021         _CheckCmdEnd(s);
01022         yyextra->InsnStorage()->append(VM::INST::MCALL,a);
01023     }
01024 <IN_PRG>{ib}"vmcall"{is}{uint}{ie}  {
01025         PI_INST(); CHECK_INST_ALLOWED
01026         const char *s=yytext+7;
01027         uint32 a;
01028         s=yyextra->_ParseInt(&a,s);
01029         _CheckCmdEnd(s);
01030         yyextra->InsnStorage()->append(VM::INST::VMCALL,a);
01031     }
01032 
01033 <IN_PRG>{ib}"ret"{bsilpaf_d_}{ie}  {
01034         PI_INST(); CHECK_INST_ALLOWED
01035         VM::INST::IID inst;
01036         SWITCH_BSILF_D_(4,RET)
01037         yyextra->InsnStorage()->append(inst);
01038     }
01039 <IN_PRG>{ib}"ret"{ie}  {
01040         PI_INST(); CHECK_INST_ALLOWED
01041         yyextra->InsnStorage()->append(VM::INST::RET);
01042     }
01043 
01044 <IN_PRG>{ib}"scast"{is}{typeid}{ie}  {
01045         PI_INST(); CHECK_INST_ALLOWED
01046         const char *s=yytext+6;
01047         VM::TypeID a;
01048         s=yyextra->_ParseInt(&a,s);
01049         _CheckCmdEnd(s);
01050         yyextra->InsnStorage()->append(VM::INST::SCAST,a);
01051     }
01052 <IN_PRG>{ib}"dcast"{is}{typeid}{ie}  {
01053         PI_INST(); CHECK_INST_ALLOWED
01054         const char *s=yytext+6;
01055         VM::TypeID a;
01056         s=yyextra->_ParseInt(&a,s);
01057         _CheckCmdEnd(s);
01058         yyextra->InsnStorage()->append(VM::INST::DCAST,a);
01059     }
01060 
01061 <IN_PRG>{ib}"adel"{ie}  {
01062         PI_INST(); CHECK_INST_ALLOWED
01063         yyextra->InsnStorage()->append(VM::INST::ADEL);
01064     }
01065 <IN_PRG>{ib}"odel"{ie}  {
01066         PI_INST(); CHECK_INST_ALLOWED
01067         yyextra->InsnStorage()->append(VM::INST::ODEL);
01068     }
01069 
01070 <IN_PRG>{ib}{name}{ie}  {
01071         PI_LINE();
01072         const char *s=yytext;
01073         while(isspace(*s)) ++s;
01074         const char *inst=s;
01075         while(!isspace(*s))  ++s;
01076         Error(yyextra->_MakeCurrLoc(),"illegal instruction \"%.*s\" or "
01077             "format violation",s-inst,inst);
01078         ++yyextra->n_errors;
01079         PI_START();
01080     }
01081     /* Skip comments which are alone in the line. */
01082 <IN_PRG>[ \t]*"#"[^\n]*\n  {  PI_LINE();  PI_START();  }
01083     /* Ignore empty lines and single newlines: */
01084 <IN_PRG>[ \t]*\n  {  PI_LINE();  PI_START();  }
01085     /* "Default" rule */
01086 <IN_PRG>.  {
01087         PI_TOK();
01088         Error(yyextra->_MakeCurrLoc(),"illegal instruction or "
01089             "format violation");
01090         ++yyextra->n_errors;
01091         /* Skip until next newline. */
01092         yy_push_state(IN_SKIPNL,yyscanner);
01093     }
01094 
01095     /*==========================<INITIAL / TOP LEVEL>=========================*/
01096     /* Match whitespace: (\r was filtered out earlier) */
01097 [ ]+  {
01098         PI_TOK();
01099         /* As this is not a token, re-set token start pos: */
01100         PI_START();
01101     }
01102 \n  {  PI_LINE();  PI_START();  }
01103 \t  {  PI_TAB();  PI_START();  }
01104 \f  {  PI_CHAR(yytext[0]);  PI_START();  }
01105 \v  {  PI_CHAR(yytext[0]);  PI_START();  }
01106     /* Optimized versions: */
01107 [ \t]+\n  {  PI_LINE();  PI_START();  }
01108 \t+[ ]+  {
01109         int i=0;
01110         for(; yytext[i]=='\t'; i++)  PI_TAB();
01111         PI_TOKL(yyleng-i);
01112         PI_START();
01113     }
01114 \n\t+[ ]+  {
01115         PI_LINE();
01116         int i=0;
01117         for(; yytext[i]=='\t'; i++)  PI_TAB();
01118         PI_TOKL(yyleng-i);
01119         PI_START();
01120     }
01121 
01122     /* Start comment: */
01123 "#"  {
01124         PI_TOK();
01125         yy_push_state(IN_CMT,yyscanner);
01126     }
01127 
01128     /* Start object/symbol description: */
01129 <INITIAL,IN_SYM,IN_LOC,IN_PRG,IN_INFO>"info"{wspace_opt}":"  {
01130         PI_STR(yytext,yyleng);
01131         
01132         // Pop other section state(s) currently on the stack. 
01133         while(YY_START!=INITIAL)  yy_pop_state(yyscanner);
01134         
01135         yy_push_state(IN_INFO,yyscanner);
01136         return(TextAsmScanner::T_info);
01137     }
01138 <INITIAL,IN_SYM,IN_LOC,IN_PRG,IN_INFO>"symbols"{wspace_opt}":"  {
01139         PI_STR(yytext,yyleng);
01140         
01141         // Pop other section state(s) currently on the stack. 
01142         while(YY_START!=INITIAL)  yy_pop_state(yyscanner);
01143         
01144         yy_push_state(IN_SYM,yyscanner);
01145         return(TextAsmScanner::T_symbols);
01146     }
01147 <INITIAL,IN_SYM,IN_LOC,IN_PRG,IN_INFO>"locations"{wspace_opt}":"  {
01148         PI_STR(yytext,yyleng);
01149         
01150         // Pop other section state(s) currently on the stack. 
01151         while(YY_START!=INITIAL)  yy_pop_state(yyscanner);
01152         
01153         yy_push_state(IN_LOC,yyscanner);
01154         return(TextAsmScanner::T_locations);
01155     }
01156 <INITIAL,IN_SYM,IN_LOC,IN_PRG,IN_INFO>"program"{wspace_opt}":"[ \t]*"\n"  {
01157         PI_LINE();
01158         
01159         // Pop other section state(s) currently on the stack. 
01160         while(YY_START!=INITIAL)  yy_pop_state(yyscanner);
01161         
01162         yy_push_state(IN_PRG,yyscanner);
01163         return(TextAsmScanner::T_program);
01164     }
01165 
01166 <<EOF>>  {
01167         /* The normal action would be to YYWarp() here but I cannot */
01168         /* because of the token buffer. */
01169         /*if(yyextra->_YYWrap())*/
01170         /*{  return(0);  }*/
01171         PI_EOF();
01172         return(0);
01173     }
01174 
01175     /* IN_PRG has special syntax: not included here. */
01176 <INITIAL,IN_SYM,IN_LOC,IN_INFO>{name}":"  {
01177         PI_TOK();
01178         yytext[yyleng-1]='\0';
01179         Error(yyextra->_MakeCurrLoc(),"illegal section \"%s\"",yytext);
01180         ++yyextra->n_errors;
01181         /* Skip until next whitespace. */
01182         yy_push_state(IN_SKIPSPC,yyscanner);
01183     }
01184 {name}  {
01185         PI_TOK();
01186         Error(yyextra->_MakeCurrLoc(),"illegal directive \"%s\" or "
01187             "format violation ",yytext);
01188         ++yyextra->n_errors;
01189         /* Skip until next whitespace. */
01190         yy_push_state(IN_SKIPSPC,yyscanner);
01191     }
01192 ";"  {
01193         // Should not happen here; only in case of error further up. 
01194         PI_TOK();
01195         return(TextAsmScanner::T_pop);
01196     }
01197 .  {
01198         PI_TOK();
01199         Error(yyextra->_MakeCurrLoc(),"illegal directive or format violation");
01200         ++yyextra->n_errors;
01201         /* Skip until next whitespace. */
01202         yy_push_state(IN_SKIPSPC,yyscanner);
01203     }
01204 
01205 %%
01206 
01207 // Special "trick"; 2nd time; see comment in scannerbase.h. 
01208 #define PREFIX_FlexScannerBase TASM_FlexScannerBase
01209 #define PREFIX_lex TASM_lex
01210 #define PREFIX_lex_init TASM_lex_init
01211 #define PREFIX_lex_destroy TASM_lex_destroy
01212 #define PREFIX_pop_buffer_state TASM_pop_buffer_state
01213 #define PREFIX_push_buffer_state TASM_push_buffer_state
01214 #define PREFIX_create_buffer TASM__create_buffer
01215 #define PREFIX_switch_to_buffer TASM__switch_to_buffer
01216 inline void PREFIX_set_extra(PREFIX_FlexScannerBase *arg,yyscan_t scanner)
01217     {  yyset_extra((TextAsmScanner*)arg,scanner);  }
01218 #define FLEX_BOTTOM_PART
01219 #include <lib/lex/scannerbase.cc>
01220 
01221 
01222 char *TextAsmScanner::_ParseNameStr(const char *str,const char *end)
01223 {
01224     // Skip any white space. Due to lexer rules, we WILL eventually find 
01225     // a non-white space. 
01226     while(isspace(*str))  ++str;
01227     
01228     // If end is not set, find it. 
01229     if(!end) for(end=str; *end; end++);
01230     
01231     // Copy string. ~Token() and Token::clear() are responsible for FREEing. 
01232     Assert(end>str);
01233     size_t len=end-str;
01234     char *nstr=ALLOC<char>(len+1);   // +1 for '\0' char
01235     if(*end=='\0')
01236     {  strcpy(nstr,str);  }
01237     else
01238     {  strncpy(nstr,str,len);  nstr[len]='\0';  }
01239     
01240     return(nstr);
01241 }
01242 
01243 
01244 template<typename T>const char *TextAsmScanner::_ParseInt(T *ret,
01245     const char *str,char prefix)
01246 {
01247     // Skip prefix if specified. 
01248     if(prefix)
01249     {
01250         //fprintf(stderr,"<%s,%c>",str,prefix);
01251         while(isspace(*str)) ++str;
01252         Assert(*str==prefix);
01253         ++str;
01254     }
01255     
01256     SError error;
01257     const char *end=ParseInt(ret,str,error,1);
01258     if(error)
01259     {
01260         Error(_MakeCurrLoc(),"parse error (%s): expected %d bit integer "
01261             "instead of \"%s\"",error.msg().str(),sizeof(T)*8,str);
01262         ++n_errors;
01263     }
01264     return(end);
01265 }
01266 
01267 template<typename T>const char *TextAsmScanner::_ParseInt0(T *ret,
01268     const char *str)
01269 {
01270     while(isspace(*str))  ++str;
01271     if(!*str)
01272     {  *ret=T(0);  return(str);  }
01273     
01274     SError error;
01275     const char *end=ParseInt(ret,str,error,1);
01276     if(error)
01277     {
01278         Error(_MakeCurrLoc(),"parse error (%s): expected %d bit integer "
01279             "instead of \"%s\"",error.msg().str(),sizeof(T)*8,str);
01280         ++n_errors;
01281     }
01282     return(end);
01283 }
01284 
01285 template<typename T>const char *TextAsmScanner::_ParseFloat(T *ret,
01286     const char *str)
01287 {
01288     while(isspace(*str))  ++str;
01289     if(!*str)
01290     {  *ret=T(0);  return(str);  }
01291     
01292     SError error;
01293     const char *end=ParseFloat(ret,str,error,1);
01294     if(error)
01295     {
01296         Error(_MakeCurrLoc(),"parse error (%s): expected %d bit float "
01297             "instead of \"%s\"",error.msg().str(),sizeof(T)*8,str);
01298         ++n_errors;
01299     }
01300     return(end);
01301 }
01302 
01303 
01304 const char *TextAsmScanner::_ParseTypeSpec(Token::Type *ts,const char *str)
01305 {
01306     const char *s=str;
01307     
01308     // First, parse type chars: max 2. 
01309     ts->tchar[0]='\0';
01310     ts->tchar[1]='\0';
01311     if(isalpha(*s))
01312     {  ts->tchar[0]=*s;  ++s;  }
01313     if(isalpha(*s))
01314     {  ts->tchar[1]=*s;  ++s;  }
01315     
01316     while(isspace(*s))  ++s;
01317     
01318     // Parse TYPEID if specified. 
01319     ts->tid=0;
01320     if(*s=='>')
01321     {
01322         Assert(!ts->tchar[1]);  // lexer rules ensure that
01323         ts->tchar[1]='>';
01324         
01325         ++s;
01326         s=_ParseInt(&ts->tid,s);
01327     }
01328     
01329     return(s);
01330 }
01331 
01332 
01333 void TextAsmScanner::_CheckInstAllowed_Failed()
01334 {
01335     Error(_MakeCurrLoc(),
01336         "cannot specify instruction outside function");
01337     ++n_errors;
01338 }
01339 
01340 
01341 const char *TextAsmScanner::TokID2String(TokID t)
01342 {
01343     switch(t)
01344     {
01345         case T_EOF:         return("EOF");
01346         
01347         case T_pop:         return("';'");
01348         case T_symbols:     return("symbol desc section");
01349         case T_locations:   return("location desc section");
01350         case T_program:     return("program instruction section");
01351         case T_info:        return("info section");
01352         
01353         case TS_namespace:  return("'namespace'");
01354         case TS_class:      return("'class'");
01355         case TS_base:       return("'base'");
01356         case TS_baseent:    return("base list entry");
01357         case TS_varent:     return("variable entry");
01358         case TS_size:       return("'size'");
01359         case TS_virtual:    return("'virtual'");
01360         case TS_vtable:     return("'vtable'");
01361         case TS_symref:     return("vtable block entry");
01362         case TS_vglobal:    return("'vglobal'");
01363         case TS_pglobal:    return("'pglobal'");
01364         case TS_symbols:    return("'symbols'");
01365         case TS_funcsym:    return("function symbol");
01366         case TS_varsym:     return("variable symbol");
01367         case TS_globvar:    return("global variable entry");
01368         
01369         case TP_slabel:     return("special label");  // s="string" actually...
01370         case TP_mlabel:     return("codemark label");
01371         case TP_rlabel:     return("symref label");
01372         
01373         case TI_abivers:    return("ABI version");
01374     }
01375     
01376     return("???");   // Should not happen. 
01377 }
01378 
01379 
01380 void TextAsmScanner::reset()
01381 {
01382     Assert(!insn_storage);  // Actually, the parser should take care of it. 
01383     DELETE(insn_storage);
01384 }
01385 
01386 
01387 TextAsmScanner::TextAsmScanner() : 
01388     TASM_FlexScannerBase()
01389 {
01390     // We do not need lookahead. 
01391     cfg.ahead_toks_wanted=1;  // (minimum)
01392     // And only 1 look back since all tokens are processed directly. 
01393     cfg.old_toks_wanted=1;
01394     
01395     insn_storage=NULL;
01396 }
01397 
01398 TextAsmScanner::~TextAsmScanner()
01399 {
01400     Assert(!insn_storage);  // Actually, the parser should take care of it. 
01401     DELETE(insn_storage);  // be sure
01402 }
01403 
01404 //------------------------------------------------------------------------------
01405 
01406 bool TextAsmScanner::Token::MayBeCleared() const
01407 {
01408     // Check magic indication that the token was used: 
01409     if(!str_val || *str_val=='\0')  return(1);
01410     return(0);
01411 }
01412 
01413 void TextAsmScanner::Token::clear(bool force)
01414 {
01415     // We need to deallocate the str_val if necessary. 
01416     if(!force)
01417     {  Assert(MayBeCleared());  }
01418     if(str_val)
01419     {  str_val=FREE(str_val);  }
01420     
01421     // Important: call higher level: 
01422     TokenEntry::clear();
01423 }
01424 
01425 
01426 #if 0   /* small test proggy */
01427 
01428 #include <lib/message/manager.h>
01429 #include <lib/message/handler_console.h>
01430 
01431 static const int MyDbg=0x10000000;
01432 
01433 static void _DoIt(const TLString &path)
01434 {
01435     TextAsmScanner scan;
01436     
01437     SError error;
01438     int rv=scan.SetInput(path,error,0);
01439     Debug(MyDbg,"SetInput=%d (%s)",rv,error.msg().str());
01440     
01441     for(;;)
01442     {
01443         TextAsmScanner::Token *tok=
01444             (TextAsmScanner::Token*)scan.LexNextToken();
01445         
01446         if(!tok)
01447         {  Debug(MyDbg,"-EOF-");  break;  }
01448         
01449         switch((TextAsmScanner::TokID)tok->token)
01450         {
01451             case TextAsmScanner::T_pop:
01452                 Debug(MyDbg,tok->lloc,"  (pop)");
01453                 break;
01454             case TextAsmScanner::T_symbols:
01455                 Debug(MyDbg,tok->lloc,"symbols:");
01456                 break;
01457             case TextAsmScanner::T_locations:
01458                 Debug(MyDbg,tok->lloc,"locations:");
01459                 break;
01460             case TextAsmScanner::T_program:
01461                 Debug(MyDbg,tok->lloc,"program:");
01462                 break;
01463             case TextAsmScanner::T_info:
01464                 Debug(MyDbg,tok->lloc,"info:");
01465                 break;
01466             case TextAsmScanner::TS_namespace:
01467                 Debug(MyDbg,tok->lloc,"  namespace: %s",tok->str_val);
01468                 break;
01469             case TextAsmScanner::TS_class:
01470                 Debug(MyDbg,tok->lloc,"  class: %d %s",tok->tid,tok->str_val);
01471                 break;
01472             case TextAsmScanner::TS_base:
01473                 Debug(MyDbg,tok->lloc,"  base: %d",tok->num);
01474                 break;
01475             case TextAsmScanner::TS_baseent:
01476                 Debug(MyDbg,tok->lloc,"  baseent: %d %u",tok->tid,tok->off);
01477                 break;
01478             case TextAsmScanner::TS_varent:
01479                 Debug(MyDbg,tok->lloc,"  typeent: %.2s%d %u %s",
01480                     tok->t.tchar,tok->t.tid,tok->off,
01481                     tok->str_val ? tok->str_val : "");
01482                 break;
01483             case TextAsmScanner::TS_size:
01484                 Debug(MyDbg,tok->lloc,"  size: %u %u,%u",
01485                     tok->size,tok->num_p,tok->num_v);
01486                 break;
01487             case TextAsmScanner::TS_virtual:
01488                 Debug(MyDbg,tok->lloc,"  virtual: %u",tok->num);
01489                 break;
01490             case TextAsmScanner::TS_vtable:
01491                 Debug(MyDbg,tok->lloc,"  vtable: %u",tok->num);
01492                 break;
01493             case TextAsmScanner::TS_symref:
01494                 Debug(MyDbg,tok->lloc,"  symref: %d",tok->symref);
01495                 break;
01496             case TextAsmScanner::TS_vglobal:
01497                 Debug(MyDbg,tok->lloc,"  vglobal: %u",tok->size);
01498                 break;
01499             case TextAsmScanner::TS_pglobal:
01500                 Debug(MyDbg,tok->lloc,"  pglobal: %u",tok->size);
01501                 break;
01502             case TextAsmScanner::TS_symbols:
01503                 Debug(MyDbg,tok->lloc,"  symbols:");
01504                 break;
01505             case TextAsmScanner::TS_funcsym:
01506                 Debug(MyDbg,tok->lloc,"  funcsym: %c $%d %s",
01507                     tok->ftype,tok->symref,tok->str_val);
01508                 break;
01509             case TextAsmScanner::TS_varsym:
01510                 Debug(MyDbg,tok->lloc,"  varsym: %.2s%d $%d %s",
01511                     tok->t.tchar,tok->t.tid,tok->symref,tok->str_val);
01512                 break;
01513             case TextAsmScanner::TS_globvar:
01514                 Debug(MyDbg,tok->lloc,"  globvar: %.2s%d %d $%d",
01515                     tok->t.tchar,tok->t.tid,tok->off,tok->symref);
01516                 break;
01517             case TextAsmScanner::TP_slabel:
01518                 Debug(MyDbg,tok->lloc,"  slabel: %s",tok->str_val);
01519                 break;
01520             case TextAsmScanner::TP_mlabel:
01521                 Debug(MyDbg,tok->lloc,"  mlabel: &%d",tok->codemark);
01522                 break;
01523             case TextAsmScanner::TP_rlabel:
01524                 Debug(MyDbg,tok->lloc,"  rlabel: $%d",tok->symref);
01525                 break;
01526             case TextAsmScanner::TI_abivers:
01527                 Debug(MyDbg,tok->lloc,"  abiversion: %s",tok->str_val);
01528                 break;
01529             default:
01530                 // This should not happen. 
01531                 Error(tok->lloc,"OOPS: unknown token %d ?!",
01532                     tok->token);
01533                 break;
01534         }
01535         
01536         // Mark string value in token as used. 
01537         if(tok->str_val)
01538         {  *tok->str_val='\0';  }
01539     }
01540 }
01541 
01542 int main(int argc,char **arg)
01543 {
01544     MessageManager::init();
01545     MessageHandler_Console cons_hdl(
01546         Message::MTAll,
01547         //Message::MTAllNonDebug,
01548         /*use_color=*/0);
01549     
01550     TLString path; // null ref for now
01551     if(argc>1)  path=arg[1];
01552     
01553     _DoIt(path);
01554     
01555     MessageManager::cleanup();
01556     return(0);
01557 }
01558 
01559 #endif

Generated on Sat Feb 19 22:33:47 2005 for Ray by doxygen 1.3.5