Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/wave/samples/waveidl/idllexer/idl.re @ 12

Last change on this file since 12 was 12, checked in by landauf, 18 years ago

added boost

File size: 16.7 KB
Line 
1/*=============================================================================
2    Boost.Wave: A Standard compliant C++ preprocessor library
3
4    Sample: IDL lexer
5
6    http://www.boost.org/
7
8    Copyright (c) 2001-2005 Hartmut Kaiser. Distributed under the Boost
9    Software License, Version 1.0. (See accompanying file
10    LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11=============================================================================*/
12
13#include <ctime>
14#include <cstdlib>
15#include <cstdio>
16#include <cstring>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20
21#include <boost/config.hpp>
22
23#if defined(BOOST_HAS_UNISTD_H)
24#include <unistd.h>
25#else
26#include <io.h>
27#endif
28
29#include <boost/assert.hpp>
30#include <boost/detail/workaround.hpp>
31
32// reuse the token ids and re2c helper functions from the default C++ lexer
33#include <boost/wave/token_ids.hpp>
34#include <boost/wave/cpplexer/re2clex/aq.hpp>
35#include <boost/wave/cpplexer/re2clex/scanner.hpp>
36
37#include "idl_re.hpp"
38
39#if defined(_MSC_VER) && !defined(__COMO__)
40#pragma warning (disable: 4101)     // 'foo' : unreferenced local variable
41#pragma warning (disable: 4102)     // 'foo' : unreferenced label
42#endif
43
44#define BSIZE     196608
45
46#define YYCTYPE   uchar
47#define YYCURSOR  cursor
48#define YYLIMIT   s->lim
49#define YYMARKER  s->ptr
50#define YYFILL(n) {cursor = fill(s, cursor);}
51
52//#define RET(i)    {s->cur = cursor; return (i);}
53#define RET(i)    \
54    { \
55        s->line += count_backslash_newlines(s, cursor); \
56        s->cur = cursor; \
57        return (i); \
58    } \
59    /**/
60
61///////////////////////////////////////////////////////////////////////////////
62namespace boost {
63namespace wave {
64namespace idllexer {
65namespace re2clex {
66
67#define RE2C_ASSERT BOOST_ASSERT
68
69int
70get_one_char(boost::wave::cpplexer::re2clex::Scanner *s)
71{
72    using namespace boost::wave::cpplexer::re2clex;
73    if (s->fd != -1) {
74    uchar val;
75   
76        if (read(s->fd, &val, sizeof(val)))
77            return val;
78    }
79    else if (0 != s->act) {
80        RE2C_ASSERT(s->first != 0 && s->last != 0);
81        RE2C_ASSERT(s->first <= s->act && s->act <= s->last);
82        if (s->act < s->last)
83            return *(s->act)++;
84    }
85    return -1;
86}
87
88std::ptrdiff_t
89rewind_stream (boost::wave::cpplexer::re2clex::Scanner *s, int cnt)
90{
91    if (s->fd != -1) {
92        return lseek(s->fd, cnt, SEEK_CUR);
93    }
94    else if (0 != s->act) {
95        RE2C_ASSERT(s->first != 0 && s->last != 0);
96        s->act += cnt;
97        RE2C_ASSERT(s->first <= s->act && s->act <= s->last);
98        return s->act - s->first;
99    }
100    return 0;
101}
102
103std::size_t
104get_first_eol_offset(boost::wave::cpplexer::re2clex::Scanner* s)
105{
106    if (!AQ_EMPTY(s->eol_offsets))
107    {
108        return s->eol_offsets->queue[s->eol_offsets->head];
109    }
110    else
111    {
112        return (unsigned int)-1;
113    }
114}
115
116void
117adjust_eol_offsets(boost::wave::cpplexer::re2clex::Scanner* s,
118    std::size_t adjustment)
119{
120    boost::wave::cpplexer::re2clex::aq_queue q;
121    std::size_t i;
122   
123    if (!s->eol_offsets)
124        s->eol_offsets = boost::wave::cpplexer::re2clex::aq_create();
125
126    q = s->eol_offsets;
127
128    if (AQ_EMPTY(q))
129        return;
130
131    i = q->head;
132    while (i != q->tail)
133    {
134        if (adjustment > q->queue[i])
135            q->queue[i] = 0;
136        else
137            q->queue[i] -= adjustment;
138        ++i;
139        if (i == q->max_size)
140            i = 0;
141    }
142    if (adjustment > q->queue[i])
143        q->queue[i] = 0;
144    else
145        q->queue[i] -= adjustment;
146}
147
148int
149count_backslash_newlines(boost::wave::cpplexer::re2clex::Scanner *s,
150    boost::wave::cpplexer::re2clex::uchar *cursor)
151{
152    using namespace boost::wave::cpplexer::re2clex;
153
154    std::size_t diff, offset;
155    int skipped = 0;
156   
157    /* figure out how many backslash-newlines skipped over unknowingly. */
158    diff = cursor - s->bot;
159    offset = get_first_eol_offset(s);
160    while (offset <= diff && offset != (unsigned int)-1)
161    {
162        skipped++;
163        boost::wave::cpplexer::re2clex::aq_pop(s->eol_offsets);
164        offset = get_first_eol_offset(s);
165    }
166    return skipped;
167}
168
169bool is_backslash(
170  boost::wave::cpplexer::re2clex::uchar *p,
171  boost::wave::cpplexer::re2clex::uchar *end, int &len)
172{
173    if (*p == '\\') {
174        len = 1;
175        return true;
176    }
177    else if (*p == '?' && *(p+1) == '?' && (p+2 < end && *(p+2) == '/')) {
178        len = 3;
179        return true;
180    }
181    return false;
182}
183
184boost::wave::cpplexer::re2clex::uchar *
185fill(boost::wave::cpplexer::re2clex::Scanner *s,
186    boost::wave::cpplexer::re2clex::uchar *cursor)
187{
188    using namespace std;    // some systems have memcpy etc. in namespace std
189    using namespace boost::wave::cpplexer::re2clex;
190
191    if(!s->eof)
192    {
193        uchar* p;
194        std::ptrdiff_t cnt = s->tok - s->bot;
195        if(cnt)
196        {
197            memcpy(s->bot, s->tok, s->lim - s->tok);
198            s->tok = s->bot;
199            s->ptr -= cnt;
200            cursor -= cnt;
201            s->lim -= cnt;
202            adjust_eol_offsets(s, cnt);
203        }
204
205        if((s->top - s->lim) < BSIZE)
206        {
207            uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
208            if (buf == 0)
209            {
210                using namespace std;      // some systems have printf in std
211                if (0 != s->error_proc)
212                    (*s->error_proc)(s, "Out of memory!");
213                else
214                    printf("Out of memory!\n");
215                   
216                /* get the scanner to stop */
217                *cursor = 0;
218                return cursor;
219            }
220
221            memcpy(buf, s->tok, s->lim - s->tok);
222            s->tok = buf;
223            s->ptr = &buf[s->ptr - s->bot];
224            cursor = &buf[cursor - s->bot];
225            s->lim = &buf[s->lim - s->bot];
226            s->top = &s->lim[BSIZE];
227            free(s->bot);
228            s->bot = buf;
229        }
230
231        if (s->fd != -1) {
232            if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE)
233            {
234                s->eof = &s->lim[cnt]; *(s->eof)++ = '\0';
235            }
236        }
237        else if (s->act != 0) {
238            cnt = s->last - s->act;
239            if (cnt > BSIZE)
240                cnt = BSIZE;
241            memcpy(s->lim, s->act, cnt);
242            s->act += cnt;
243            if (cnt != BSIZE)
244            {
245                s->eof = &s->lim[cnt]; *(s->eof)++ = '\0';
246            }
247        }
248       
249        /* backslash-newline erasing time */
250
251        /* first scan for backslash-newline and erase them */
252        for (p = s->lim; p < s->lim + cnt - 2; ++p)
253        {
254            int len = 0;
255            if (is_backslash(p, s->lim + cnt, len))
256            {
257                if (*(p+len) == '\n')
258                {
259                    int offset = len + 1;
260                    memmove(p, p + offset, s->lim + cnt - p - offset);
261                    cnt -= offset;
262                    --p;
263                    aq_enqueue(s->eol_offsets, p - s->bot + 1);   
264                }
265                else if (*(p+len) == '\r')
266                {
267                    if (*(p+len+1) == '\n')
268                    {
269                        int offset = len + 2;
270                        memmove(p, p + offset, s->lim + cnt - p - offset);
271                        cnt -= offset;
272                        --p;
273                    }
274                    else
275                    {
276                        int offset = len + 1;
277                        memmove(p, p + offset, s->lim + cnt - p - offset);
278                        cnt -= offset;
279                        --p;
280                    }
281                    aq_enqueue(s->eol_offsets, p - s->bot + 1);   
282                }
283            }
284        }
285
286        /* FIXME: the following code should be fixed to recognize correctly the
287                  trigraph backslash token */
288
289        /* check to see if what we just read ends in a backslash */
290        if (cnt >= 2)
291        {
292            uchar last = s->lim[cnt-1];
293            uchar last2 = s->lim[cnt-2];
294            /* check \ EOB */
295            if (last == '\\')
296            {
297                int next = get_one_char(s);
298                /* check for \ \n or \ \r or \ \r \n straddling the border */
299                if (next == '\n')
300                {
301                    --cnt; /* chop the final \, we've already read the \n. */
302                    boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
303                        cnt + (s->lim - s->bot));   
304                }
305                else if (next == '\r')
306                {
307                    int next2 = get_one_char(s);
308                    if (next2 == '\n')
309                    {
310                        --cnt; /* skip the backslash */
311                    }
312                    else
313                    {
314                        /* rewind one, and skip one char */
315                        rewind_stream(s, -1);
316                        --cnt;
317                    }
318                    boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
319                        cnt + (s->lim - s->bot));   
320                }
321                else if (next != -1) /* -1 means end of file */
322                {
323                    /* next was something else, so rewind the stream */
324                    lseek(s->fd, -1, SEEK_CUR);
325                }
326            }
327            /* check \ \r EOB */
328            else if (last == '\r' && last2 == '\\')
329            {
330                int next = get_one_char(s);
331                if (next == '\n')
332                {
333                    cnt -= 2; /* skip the \ \r */
334                }
335                else
336                {
337                    /* rewind one, and skip two chars */
338                    rewind_stream(s, -1);
339                    cnt -= 2;
340                }
341                boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
342                    cnt + (s->lim - s->bot));   
343            }
344            /* check \ \n EOB */
345            else if (last == '\n' && last2 == '\\')
346            {
347                cnt -= 2;
348                boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
349                    cnt + (s->lim - s->bot));   
350            }
351        }
352       
353        s->lim += cnt;
354        if (s->eof) /* eof needs adjusting if we erased backslash-newlines */
355        {
356            s->eof = s->lim;
357            *(s->eof)++ = '\0';
358        }
359    }
360    return cursor;
361}
362
363boost::wave::token_id 
364scan(boost::wave::cpplexer::re2clex::Scanner *s)
365{
366    using namespace boost::wave::cpplexer::re2clex;
367
368    uchar *cursor = s->tok = s->cur;
369
370/*!re2c
371any                = [\t\v\f\r\n\040-\377];
372OctalDigit         = [0-7];
373Digit              = [0-9];
374HexDigit           = [a-fA-F0-9];
375ExponentPart       = [Ee] [+-]? Digit+;
376FractionalConstant = (Digit* "." Digit+) | (Digit+ ".");
377FloatingSuffix     = [fF][lL]?|[lL][fF]?;
378IntegerSuffix      = [uU][lL]?|[lL][uU]?;
379FixedPointSuffix   = [dD];
380Backslash          = [\\]|"??/";
381EscapeSequence     = Backslash ([abfnrtv?'"] | Backslash | "x" HexDigit+ | OctalDigit OctalDigit? OctalDigit?);
382HexQuad            = HexDigit HexDigit HexDigit HexDigit;
383UniversalChar      = Backslash ("u" HexQuad | "U" HexQuad HexQuad);
384Newline            = "\r\n" | "\n" | "\r";
385PPSpace            = ([ \t]|("/*"(any\[*]|Newline|("*"+(any\[*/]|Newline)))*"*"+"/"))*;
386Pound              = "#" | "??=" | "%:";
387*/
388
389/*!re2c
390    "/*"            { goto ccomment; }
391    "//"            { goto cppcomment; }
392   
393    "TRUE"          { RET(T_TRUE); }
394    "FALSE"         { RET(T_FALSE); }
395   
396    "{"             { RET(T_LEFTBRACE); }
397    "}"             { RET(T_RIGHTBRACE); }
398    "["             { RET(T_LEFTBRACKET); }
399    "]"             { RET(T_RIGHTBRACKET); }
400    "#"             { RET(T_POUND); }
401    "##"            { RET(T_POUND_POUND); }
402    "("             { RET(T_LEFTPAREN); }
403    ")"             { RET(T_RIGHTPAREN); }
404    ";"             { RET(T_SEMICOLON); }
405    ":"             { RET(T_COLON); }
406    "?"             { RET(T_QUESTION_MARK); }
407    "."             { RET(T_DOT); }
408    "+"             { RET(T_PLUS); }
409    "-"             { RET(T_MINUS); }
410    "*"             { RET(T_STAR); }
411    "/"             { RET(T_DIVIDE); }
412    "%"             { RET(T_PERCENT); }
413    "^"             { RET(T_XOR); }
414    "&"             { RET(T_AND); }
415    "|"             { RET(T_OR); }
416    "~"             { RET(T_COMPL); }
417    "!"             { RET(T_NOT); }
418    "="             { RET(T_ASSIGN); }
419    "<"             { RET(T_LESS); }
420    ">"             { RET(T_GREATER); }
421    "<<"            { RET(T_SHIFTLEFT); }
422    ">>"            { RET(T_SHIFTRIGHT); }
423    "=="            { RET(T_EQUAL); }
424    "!="            { RET(T_NOTEQUAL); }
425    "<="            { RET(T_LESSEQUAL); }
426    ">="            { RET(T_GREATEREQUAL); }
427    "&&"            { RET(T_ANDAND); }
428    "||"            { RET(T_OROR); }
429    "++"            { RET(T_PLUSPLUS); }
430    "--"            { RET(T_MINUSMINUS); }
431    ","             { RET(T_COMMA); }
432
433    ([a-zA-Z_] | UniversalChar) ([a-zA-Z_0-9] | UniversalChar)*       
434        { RET(T_IDENTIFIER); }
435   
436    (("0" [xX] HexDigit+) | ("0" OctalDigit*) | ([1-9] Digit*)) IntegerSuffix?
437        { RET(T_INTLIT); }
438
439    ((FractionalConstant ExponentPart?) | (Digit+ ExponentPart)) FloatingSuffix?
440        { RET(T_FLOATLIT); }
441
442    (FractionalConstant | Digit+) FixedPointSuffix
443        { RET(T_FIXEDPOINTLIT); }
444       
445    "L"? (['] (EscapeSequence|any\[\n\r\\']|UniversalChar)+ ['])
446        { RET(T_CHARLIT); }
447   
448    "L"? (["] (EscapeSequence|any\[\n\r\\"]|UniversalChar)* ["])
449        { RET(T_STRINGLIT); }
450   
451
452    Pound PPSpace "include" PPSpace "<" (any\[\n\r>])+ ">"
453        { RET(T_PP_HHEADER); }
454
455    Pound PPSpace "include" PPSpace "\"" (any\[\n\r"])+ "\""
456        { RET(T_PP_QHEADER); }
457
458    Pound PPSpace "include" PPSpace
459        { RET(T_PP_INCLUDE); }
460
461    Pound PPSpace "if"        { RET(T_PP_IF); }
462    Pound PPSpace "ifdef"     { RET(T_PP_IFDEF); }
463    Pound PPSpace "ifndef"    { RET(T_PP_IFNDEF); }
464    Pound PPSpace "else"      { RET(T_PP_ELSE); }
465    Pound PPSpace "elif"      { RET(T_PP_ELIF); }
466    Pound PPSpace "endif"     { RET(T_PP_ENDIF); }
467    Pound PPSpace "define"    { RET(T_PP_DEFINE); }
468    Pound PPSpace "undef"     { RET(T_PP_UNDEF); }
469    Pound PPSpace "line"      { RET(T_PP_LINE); }
470    Pound PPSpace "error"     { RET(T_PP_ERROR); }
471    Pound PPSpace "pragma"    { RET(T_PP_PRAGMA); }
472
473    Pound PPSpace "warning"   { RET(T_PP_WARNING); }
474   
475    [ \t\v\f]+
476        { RET(T_SPACE); }
477
478    Newline
479    {
480        s->line++;
481        RET(T_NEWLINE);
482    }
483
484    "\000"
485    {
486        if(cursor != s->eof)
487        {
488            using namespace std;      // some systems have printf in std
489            if (0 != s->error_proc)
490                (*s->error_proc)(s, "'\\000' in input stream");
491            else
492                printf("Error: 0 in file\n");
493        }
494        RET(T_EOF);
495    }
496
497    any
498    {
499        /* if (0 != s->error_proc)
500            (*s->error_proc)(s, "Unexpected character: '%c'", *s->tok);
501        else
502            printf("unexpected character: '%c'\n", *s->tok);
503        */
504        RET(TOKEN_FROM_ID(*s->tok, UnknownTokenType));
505    }
506*/
507
508ccomment:
509/*!re2c
510    "*/"            { RET(T_CCOMMENT); }
511    Newline
512    {
513        /*if(cursor == s->eof) RET(T_EOF);*/
514        /*s->tok = cursor; */
515        s->line += count_backslash_newlines(s, cursor) +1;
516        goto ccomment;
517    }
518
519    any            { goto ccomment; }
520
521    "\000"
522    {
523        using namespace std;      // some systems have printf in std
524        if(cursor == s->eof)
525        {
526            if (s->error_proc)
527                (*s->error_proc)(s, "Unterminated comment");
528            else
529                printf("Error: Unterminated comment\n");
530        }
531        else
532        {
533            if (s->error_proc)
534                (*s->error_proc)(s, "'\\000' in input stream");
535            else
536                printf("Error: 0 in file");
537        }
538        /* adjust cursor such next call returns T_EOF */
539        --YYCURSOR;
540        /* the comment is unterminated, but nevertheless its a comment */
541        RET(T_CCOMMENT);
542    }
543
544*/
545
546cppcomment:
547/*!re2c
548    Newline
549    {
550        /*if(cursor == s->eof) RET(T_EOF); */
551        /*s->tok = cursor; */
552        s->line++;
553        RET(T_CPPCOMMENT);
554    }
555
556    any            { goto cppcomment; }
557
558    "\000"
559    {
560        using namespace std;      // some systems have printf in std
561        if(cursor != s->eof)
562        {
563            if (s->error_proc)
564                (*s->error_proc)(s, "'\\000' in input stream");
565            else
566                printf("Error: 0 in file");
567        }
568        /* adjust cursor such next call returns T_EOF */
569        --YYCURSOR;
570        /* the comment is unterminated, but nevertheless its a comment */
571        RET(T_CPPCOMMENT);
572    }
573*/
574
575} /* end of scan */
576
577#undef RE2C_ASSERT
578
579///////////////////////////////////////////////////////////////////////////////
580}   // namespace re2clex
581}   // namespace idllexer
582}   // namespace wave
583}   // namespace boost
Note: See TracBrowser for help on using the repository browser.