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

/ray/src/lib/lex/test-scanner.ll

Go to the documentation of this file.
00001 %{
00002 /*
00003  * lib/lex/test-scanner.ll
00004  * 
00005  * Test and demo scanner. 
00006  * 
00007  * Copyright (c) 2002--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 
00026 #include <lib/message/message.h>
00027 
00028 #include <lib/lex/test-scanner.h>
00029 
00030 #include <lib/lex/test-grammar.h>
00031 
00032 
00033 #define YY_EXTRA_TYPE  class TestScanner*
00034 
00035 // Special "trick": include scannerbase.cc for the first time: 
00036 #include "scannerbase.cc"
00037 
00038 // Get pointer where to store token info (string/integer/float val...)
00039 #define TOK()    ((TestScanner::TestToken*)(yyextra->_tok_ptr()))
00040 
00041 %}
00042 
00043 /* Generate scanner file by using: 
00044  * flex -s test-scanner.ll    [works with flex >= 2.5.10] */
00045 
00046 %pointer
00047 %option 8bit
00048 %option reentrant
00049 /*%option bison-bridge*/
00050 /* option bison-locations does NOT calculate locations; just passes 
00051  * the structure to store the pos. Then, I don't need it. */
00052 /*%option bison-locations*/
00053 /*%option yylineno*/
00054 %option nodefault
00055 %option noyywrap
00056 %option stack
00058 %option prefix="TEST_"
00059 %option outfile="test-scanner.cc"
00060 /*%option header-file="test-scanner.hh"*/
00061 
00062     /*IN_CMT    -> C-style comment   */
00063     /*IN_CPPCMT -> C++-style comment */
00064 %x IN_CMT
00065 %x IN_CPPCMT
00066 
00067 identifier  [[:alpha:]_][[:alnum:]_]*
00068 ninteger    [[:digit:]]+
00069 xinteger    (0?[[:digit:]]+)|(0x[[:xdigit:]]+)
00070 
00071 %%
00072 
00073 "//"  {
00074         PI_TOK();
00075         yy_push_state(IN_CPPCMT,yyscanner);
00076     }
00077 <IN_CPPCMT>.*\n  {
00078         PI_LINE();
00079         PI_START();
00080         yy_pop_state(yyscanner);
00081     }
00082 <IN_CPPCMT><<EOF>>  {
00083         PI_EOF();
00084         PI_TOK();
00085         PI_START();
00086         yy_pop_state(yyscanner);
00087         return(0);
00088     }
00089     /* This rule will normally not match (only if terminated by EOF). */
00090 <IN_CPPCMT>.  {
00091         PI_CHAR(yytext[0]);
00092     }
00093 
00094 "/*"  {
00095         PI_TOK();
00096         yy_push_state(IN_CMT,yyscanner);
00097         yyextra->nested_comment_warned=0;
00098         yyextra->newlines_in_ccomment=0;
00099     }
00100 <IN_CMT>"*/"  {
00101         PI_TOK();
00102         PI_START();
00103         yy_pop_state(yyscanner);
00104     }
00105 <IN_CMT>"/*"  {
00106         PI_START();  /* BEFORE PI_TOK here. */
00107         PI_TOK();
00108         if(yyextra->allow_nested_comments)
00109         {
00110             if(yyextra->allow_nested_comments>=2 && 
00111                !yyextra->nested_comment_warned)
00112             {
00113                 Warning(yyextra->_MakeCurrLoc(),"nested C-style comment\n");
00114                 ++yyextra->nested_comment_warned;
00115             }
00116             yy_push_state(IN_CMT,yyscanner);
00117         }
00118         PI_START();
00119     }
00120 <IN_CMT>[^\n/\*]*\n    {  PI_LINE();  ++yyextra->newlines_in_ccomment;  }
00121 <IN_CMT>[^\n\r\t/\*]*  {  PI_TOK();  }
00122     /* The following rule cannot be matched. */
00123     /* <IN_CMT>\n     {  PI_LINE();  ++yyextra->newlines_in_ccomment;  } */
00124 <IN_CMT>\t             {  PI_TAB();  }
00125 <IN_CMT><<EOF>>  {
00126         PI_EOF();
00127         PI_TOK();
00128         /* FIXME: we do not yet report where the unterminated comment starts!!! */
00129         Error(yyextra->_MakeCurrEndLoc(),"unterminated C-style comment\n");
00130         ++yyextra->n_errors;
00131         while(YY_START==IN_CMT)
00132         {  yy_pop_state(yyscanner);  }
00133         return(0);
00134     }
00135 <IN_CMT>.              {  PI_TOK();  /* single '*' would fail otherwise */  }
00136 
00137     /* Match whitespace: */
00138 [ \t]+  {
00139         PI_STR(yytext,yyleng);
00140         /* As this is not a token, re-set token start pos: */
00141         PI_START();
00142     }
00143 \n  {  PI_LINE();  PI_START();  }
00144 
00145 
00146 "if"      {  PI_TOK();  return(TS_IF);  }
00147 "else"    {  PI_TOK();  return(TS_ELSE);  }
00148 
00149 {xinteger}  {
00150         PI_TOK();
00151         // Parse integer value: 
00152         int ival=strtol(yytext,NULL,0);
00153         // Set result in token: 
00154         TOK()->lval.int_val=ival;
00155         // Return "token". 
00156         return(TS_INTEGER);
00157     }
00158 {identifier}  {
00159         PI_TOK();
00160         // "Parse" identifier (no-op) and store in token value: 
00161         TOK()->lval.string_val=ALLOC<char>(yyleng+1);
00162         strncpy(TOK()->lval.string_val,yytext,yyleng);
00163         TOK()->lval.string_val[yyleng]='\0';
00164         return(TS_IDENTIFIER);
00165     }
00166 
00167 <<EOF>>  {
00168         /* The normal action would be to YYWarp() here but I cannot */
00169         /* because of the token buffer. */
00170         /*if(yyextra->_YYWrap())*/
00171         /*{  return(0);  }*/
00172         PI_EOF();
00173         return(0);
00174     }
00175 
00176 .   {  PI_TOK();  return(yytext[0]);  }
00177 
00178 %%
00179 
00180 // Special "trick"; 2nd time; see comment in scannerbase.h. 
00181 #define PREFIX_FlexScannerBase TEST_FlexScannerBase
00182 #define PREFIX_lex TEST_lex
00183 #define PREFIX_lex_init TEST_lex_init
00184 #define PREFIX_lex_destroy TEST_lex_destroy
00185 #define PREFIX_pop_buffer_state TEST_pop_buffer_state
00186 #define PREFIX_push_buffer_state TEST_push_buffer_state
00187 #define PREFIX_create_buffer TEST__create_buffer
00188 #define PREFIX_switch_to_buffer TEST__switch_to_buffer
00189 inline void PREFIX_set_extra(PREFIX_FlexScannerBase *arg,yyscan_t scanner)
00190     {  yyset_extra((TestScanner*)arg,scanner);  }
00191 #define FLEX_BOTTOM_PART
00192 #include "scannerbase.cc"
00193 
00194 
00195 void TestScanner::reset()
00196 {
00197     nested_comment_warned=0;
00198     newlines_in_ccomment=0;
00199 }
00200 
00201 
00202 TestScanner::TestScanner() : 
00203     TEST_FlexScannerBase()
00204 {
00205     nested_comment_warned=0;
00206     newlines_in_ccomment=0;
00207     
00208     allow_nested_comments=1;
00209 }
00210 
00211 TestScanner::~TestScanner()
00212 {
00213     
00214 }
00215 
00216 //------------------------------------------------------------------------------
00217 
00218 bool TestScanner::TestToken::MayBeCleared() const
00219 {
00220     if(token!=TS_IDENTIFIER)  return(1);
00221     // Check magic indication that the token was used: 
00222     if(!lval.string_val || *lval.string_val=='\0')  return(1);
00223     return(0);
00224 }
00225 
00226 void TestScanner::TestToken::clear(bool force)
00227 {
00228     // We need to deallocate the string_val if necessary; 
00229     // this is only the case for the TS_IDENTIFIER token. 
00230     if(!force)
00231     {  Assert(MayBeCleared());  }
00232     if(token==TS_IDENTIFIER)
00233     {  lval.string_val=FREE(lval.string_val);  }
00234     
00235     // Important: call higher level: 
00236     TokenEntry::clear();
00237 }

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