Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wslexer.c File Reference

#include "wsint.h"
#include "wsstree.h"
#include "wsgram.h"

Include dependency graph for wslexer.c:

Include dependency graph

Go to the source code of this file.

Defines

#define WS_IS_DECIMAL_DIGIT(ch)   ('0' <= (ch) && (ch) <= '9')
#define WS_DECIMAL_TO_INT(ch)   ((ch) - '0')
#define WS_IS_NON_ZERO_DIGIT(ch)   ('1' <= (ch) && (ch) <= '9')
#define WS_IS_OCTAL_DIGIT(ch)   ('0' <= (ch) && (ch) <= '7')
#define WS_OCTAL_TO_INT(ch)   ((ch) - '0')
#define WS_IS_HEX_DIGIT(ch)
#define WS_HEX_TO_INT(ch)
#define WS_IS_IDENTIFIER_LETTER(ch)
#define N(n)   n, sizeof(n) - 1

Functions

WsBool lookup_keyword (char *id, size_t len, int *token_return)
WsUInt32 buffer_to_int (WsCompilerPtr compiler, WsBuffer *buffer)
WsBool read_float_from_point (WsCompiler *compiler, WsBuffer *buffer, WsFloat *result)
WsBool read_float_from_exp (WsCompiler *compiler, WsBuffer *buffer, WsFloat *result)
int ws_yy_lex (YYSTYPE *yylval, YYLTYPE *yylloc, void *context)

Variables

struct {
   char *   name
   size_t   name_len
   int   token
keywords []
int num_keywords = sizeof(keywords) / sizeof(keywords[0])


Define Documentation

#define N  )     n, sizeof(n) - 1
 

Definition at line 149 of file wslexer.c.

#define WS_DECIMAL_TO_INT ch   )     ((ch) - '0')
 

Definition at line 81 of file wslexer.c.

#define WS_HEX_TO_INT ch   ) 
 

Value:

('0' <= (ch) && (ch) <= '9'     \
     ? ((ch) - '0')         \
     : ('a' <= (ch) && (ch) <= 'f'  \
       ? ((ch) - 'a' + 10)      \
       : (ch) - 'A' + 10))

Definition at line 99 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_IS_DECIMAL_DIGIT ch   )     ('0' <= (ch) && (ch) <= '9')
 

Definition at line 78 of file wslexer.c.

Referenced by read_float_from_exp(), read_float_from_point(), and ws_yy_lex().

#define WS_IS_HEX_DIGIT ch   ) 
 

Value:

(('0' <= (ch) && (ch) <= '9')   \
                             || ('a' <= (ch) && (ch) <= 'f')    \
                             || ('A' <= (ch) && (ch) <= 'F'))

Definition at line 94 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_IS_IDENTIFIER_LETTER ch   ) 
 

Value:

(('a' <= (ch) && (ch) <= 'z')       \
     || ('A' <= (ch) && (ch) <= 'Z')    \
     || (ch) == '_')

Definition at line 108 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_IS_NON_ZERO_DIGIT ch   )     ('1' <= (ch) && (ch) <= '9')
 

Definition at line 85 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_IS_OCTAL_DIGIT ch   )     ('0' <= (ch) && (ch) <= '7')
 

Definition at line 88 of file wslexer.c.

Referenced by ws_yy_lex().

#define WS_OCTAL_TO_INT ch   )     ((ch) - '0')
 

Definition at line 91 of file wslexer.c.

Referenced by ws_yy_lex().


Function Documentation

WsUInt32 buffer_to_int WsCompilerPtr  compiler,
WsBuffer buffer
[static]
 

Definition at line 909 of file wslexer.c.

References ws_buffer_append_space(), ws_buffer_ptr(), ws_error_memory(), WS_INT32_MAX, ws_src_error(), WsBuffer, WsCompilerPtr, and WsUInt32.

Referenced by ws_yy_lex().

00910 {
00911     unsigned char *p;
00912     unsigned long value;
00913 
00914     /* Terminate the string. */
00915     if (!ws_buffer_append_space(buffer, &p, 1)) {
00916         ws_error_memory(compiler);
00917         return 0;
00918     }
00919     p[0] = '\0';
00920 
00921     /* Convert the buffer into an integer number.  The base is taken
00922        from the bufer. */
00923     errno = 0;
00924     value = strtoul((char *) ws_buffer_ptr(buffer), NULL, 0);
00925 
00926     /* Check for overflow.  We accept WS_INT32_MAX + 1 because we might
00927      * be parsing the numeric part of '-2147483648'. */
00928     if (errno == ERANGE || value > (WsUInt32) WS_INT32_MAX + 1)
00929         ws_src_error(compiler, 0, "integer literal too large");
00930 
00931     /* All done. */
00932     return (WsUInt32) value;
00933 }

Here is the call graph for this function:

WsBool lookup_keyword char *  id,
size_t  len,
int *  token_return
[static]
 

Definition at line 876 of file wslexer.c.

References keywords, name, result, and WsBool.

Referenced by ws_yy_lex().

00877 {
00878     int left = 0, center, right = num_keywords;
00879 
00880     while (left < right) {
00881         size_t l;
00882         int result;
00883 
00884         center = left + (right - left) / 2;
00885 
00886         l = keywords[center].name_len;
00887         if (len < l)
00888             l = len;
00889 
00890         result = memcmp(id, keywords[center].name, l);
00891         if (result < 0 || (result == 0 && len < keywords[center].name_len))
00892             /* The possible match is smaller. */
00893             right = center;
00894         else if (result > 0 || (result == 0 && len > keywords[center].name_len))
00895             /* The possible match is bigger. */
00896             left = center + 1;
00897         else {
00898             /* Found a match. */
00899             *token_return = keywords[center].token;
00900             return WS_TRUE;
00901         }
00902     }
00903 
00904     /* No match. */
00905     return WS_FALSE;
00906 }

WsBool read_float_from_exp WsCompiler compiler,
WsBuffer buffer,
WsFloat result
[static]
 

Definition at line 959 of file wslexer.c.

References WsCompilerRec::input, result, ws_buffer_append_space(), ws_buffer_ptr(), ws_error_memory(), ws_ieee754_encode_single(), WS_IS_DECIMAL_DIGIT, ws_src_error(), ws_stream_getc(), ws_stream_ungetc(), WsBool, WsBuffer, WsCompiler, and WsUInt32.

Referenced by read_float_from_point(), and ws_yy_lex().

00961 {
00962     WsUInt32 ch;
00963     unsigned char *p;
00964     int sign = '+';
00965     unsigned char buf[4];
00966 
00967     /* Do we have an exponent part. */
00968     if (!ws_stream_getc(compiler->input, &ch))
00969         goto done;
00970     if (ch != 'e' && ch != 'E') {
00971         /* No exponent part. */
00972         ws_stream_ungetc(compiler->input, ch);
00973         goto done;
00974     }
00975 
00976     /* Sign. */
00977     if (!ws_stream_getc(compiler->input, &ch)) {
00978         /* This is an error. */
00979         ws_src_error(compiler, 0, "truncated float literal");
00980         return WS_FALSE;
00981     }
00982     if (ch == '-')
00983         sign = '-';
00984     else if (ch == '+')
00985         sign = '+';
00986     else
00987         ws_stream_ungetc(compiler->input, ch);
00988 
00989     /* DecimalDigits. */
00990     if (!ws_stream_getc(compiler->input, &ch)) {
00991         ws_src_error(compiler, 0, "truncated float literal");
00992         return WS_FALSE;
00993     }
00994     if (!WS_IS_DECIMAL_DIGIT(ch)) {
00995         ws_src_error(compiler, 0, "no decimal digits in exponent part");
00996         return WS_FALSE;
00997     }
00998 
00999     /* Append exponent part read so far. */
01000     if (!ws_buffer_append_space(buffer, &p, 2)) {
01001         ws_error_memory(compiler);
01002         return WS_FALSE;
01003     }
01004     p[0] = 'e';
01005     p[1] = sign;
01006 
01007     /* Read decimal digits. */
01008     while (WS_IS_DECIMAL_DIGIT(ch)) {
01009         if (!ws_buffer_append_space(buffer, &p, 1)) {
01010             ws_error_memory(compiler);
01011             return WS_FALSE;
01012         }
01013         p[0] = (unsigned char) ch;
01014 
01015         if (!ws_stream_getc(compiler->input, &ch))
01016             /* EOF.  This is ok. */
01017             goto done;
01018     }
01019     /* Unget the extra character. */
01020     ws_stream_ungetc(compiler->input, ch);
01021 
01022     /* FALLTHROUGH */
01023 
01024 done:
01025 
01026     if (!ws_buffer_append_space(buffer, &p, 1)) {
01027         ws_error_memory(compiler);
01028         return WS_FALSE;
01029     }
01030     p[0] = 0;
01031 
01032     /* Now the buffer contains a valid floating point number. */
01033     *result = (WsFloat) strtod((char *) ws_buffer_ptr(buffer), NULL);
01034 
01035     /* Check that the generated floating point number fits to
01036        `float32'. */
01037     if (*result == HUGE_VAL || *result == -HUGE_VAL
01038         || ws_ieee754_encode_single(*result, buf) != WS_IEEE754_OK)
01039         ws_src_error(compiler, 0, "floating point literal too large");
01040 
01041     return WS_TRUE;
01042 }

Here is the call graph for this function:

WsBool read_float_from_point WsCompiler compiler,
WsBuffer buffer,
WsFloat result
[static]
 

Definition at line 936 of file wslexer.c.

References WsCompilerRec::input, read_float_from_exp(), result, ws_buffer_append_space(), ws_error_memory(), WS_IS_DECIMAL_DIGIT, ws_stream_getc(), ws_stream_ungetc(), WsBool, WsBuffer, WsCompiler, and WsUInt32.

Referenced by ws_yy_lex().

00938 {
00939     WsUInt32 ch;
00940     unsigned char *p;
00941 
00942     while (ws_stream_getc(compiler->input, &ch)) {
00943         if (WS_IS_DECIMAL_DIGIT(ch)) {
00944             if (!ws_buffer_append_space(buffer, &p, 1)) {
00945                 ws_error_memory(compiler);
00946                 return WS_FALSE;
00947             }
00948             p[0] = (unsigned char) ch;
00949         } else {
00950             ws_stream_ungetc(compiler->input, ch);
00951             break;
00952         }
00953     }
00954 
00955     return read_float_from_exp(compiler, buffer, result);
00956 }

Here is the call graph for this function:

int ws_yy_lex YYSTYPE yylval,
YYLTYPE yylloc,
void *  context
 

Definition at line 221 of file wslexer.c.

References buffer_to_int(), COMPILER_MAGIC, YYLTYPE::first_line, gw_assert, YYSTYPE::identifier, WsCompilerRec::input, YYSTYPE::integer, WsCompilerRec::linenum, lookup_keyword(), WsCompilerRec::magic, read_float_from_exp(), read_float_from_point(), YYSTYPE::string, token, type, YYSTYPE::vfloat, ws_buffer_append_space(), ws_buffer_init(), ws_buffer_len(), ws_buffer_uninit(), ws_error_memory(), ws_free(), WS_HEX_TO_INT, WS_IS_DECIMAL_DIGIT, WS_IS_HEX_DIGIT, WS_IS_IDENTIFIER_LETTER, WS_IS_NON_ZERO_DIGIT, WS_IS_OCTAL_DIGIT, ws_lexer_register_block(), ws_lexer_register_utf8(), ws_malloc(), WS_OCTAL_TO_INT, ws_realloc(), ws_src_error(), ws_stream_getc(), ws_stream_ungetc(), ws_utf8_alloc(), ws_utf8_append_char(), ws_utf8_free(), WsBool, WsBuffer, WsCompiler, WsUInt32, WsUtf8String, yylloc, and yylval.

00222 {
00223     WsCompiler *compiler = (WsCompiler *) context;
00224     WsUInt32 ch, ch2;
00225     WsBuffer buffer;
00226     unsigned char *p;
00227     WsBool success;
00228 
00229     /* Just check that we get the correct amount of arguments. */
00230     gw_assert(compiler->magic == COMPILER_MAGIC);
00231 
00232     while (ws_stream_getc(compiler->input, &ch)) {
00233         /* Save the token's line number. */
00234         yylloc->first_line = compiler->linenum;
00235 
00236         switch (ch) {
00237         case '\t':      /* Whitespace characters. */
00238         case '\v':
00239         case '\f':
00240         case ' ':
00241             continue;
00242 
00243         case '\n':      /* Line terminators. */
00244         case '\r':
00245             if (ch == '\r' && ws_stream_getc(compiler->input, &ch2)) {
00246                 if (ch2 != '\n')
00247                     ws_stream_ungetc(compiler->input, ch2);
00248             }
00249             compiler->linenum++;
00250             continue;
00251 
00252         case '!':       /* !, != */
00253             if (ws_stream_getc(compiler->input, &ch2)) {
00254                 if (ch2 == '=')
00255                     return tNE;
00256 
00257                 ws_stream_ungetc(compiler->input, ch2);
00258             }
00259             return '!';
00260 
00261         case '%':       /* %, %= */
00262             if (ws_stream_getc(compiler->input, &ch2)) {
00263                 if (ch2 == '=')
00264                     return tREMA;
00265 
00266                 ws_stream_ungetc(compiler->input, ch2);
00267             }
00268             return '%';
00269 
00270         case '&':       /* &, &&, &= */
00271             if (ws_stream_getc(compiler->input, &ch2)) {
00272                 if (ch2 == '&')
00273                     return tAND;
00274                 if (ch2 == '=')
00275                     return tANDA;
00276 
00277                 ws_stream_ungetc(compiler->input, ch2);
00278             }
00279             return '&';
00280 
00281         case '*':       /* *, *= */
00282             if (ws_stream_getc(compiler->input, &ch2)) {
00283                 if (ch2 == '=')
00284                     return tMULA;
00285 
00286                 ws_stream_ungetc(compiler->input, ch2);
00287             }
00288             return '*';
00289 
00290         case '+':       /* +, ++, += */
00291             if (ws_stream_getc(compiler->input, &ch2)) {
00292                 if (ch2 == '+')
00293                     return tPLUSPLUS;
00294                 if (ch2 == '=')
00295                     return tADDA;
00296 
00297                 ws_stream_ungetc(compiler->input, ch2);
00298             }
00299             return '+';
00300 
00301         case '-':       /* -, --, -= */
00302             if (ws_stream_getc(compiler->input, &ch2)) {
00303                 if (ch2 == '-')
00304                     return tMINUSMINUS;
00305                 if (ch2 == '=')
00306                     return tSUBA;
00307 
00308                 ws_stream_ungetc(compiler->input, ch2);
00309             }
00310             return '-';
00311 
00312         case '.':
00313             if (ws_stream_getc(compiler->input, &ch2)) {
00314                 if (WS_IS_DECIMAL_DIGIT(ch2)) {
00315                     /* DecimalFloatLiteral. */
00316                     ws_buffer_init(&buffer);
00317 
00318                     if (!ws_buffer_append_space(&buffer, &p, 2)) {
00319                         ws_error_memory(compiler);
00320                         ws_buffer_uninit(&buffer);
00321                         return EOF;
00322                     }
00323 
00324                     p[0] = '.';
00325                     p[1] = (unsigned char) ch2;
00326 
00327                     success = read_float_from_point(compiler, &buffer,
00328                                                     &yylval->vfloat);
00329                     ws_buffer_uninit(&buffer);
00330 
00331                     if (!success)
00332                         return EOF;
00333 
00334                     return tFLOAT;
00335                 }
00336 
00337                 ws_stream_ungetc(compiler->input, ch2);
00338             }
00339             return '.';
00340 
00341         case '/':       /* /, /=, block or a single line comment */
00342             if (ws_stream_getc(compiler->input, &ch2)) {
00343                 if (ch2 == '*') {
00344                     /* Block comment. */
00345                     while (1) {
00346                         if (!ws_stream_getc(compiler->input, &ch)) {
00347                             ws_src_error(compiler, 0, "EOF in comment");
00348                             return EOF;
00349                         }
00350 
00351                         if (ch == '\n' || ch == '\r') {
00352                             /* Line terminators. */
00353                             if (ch == '\r' && ws_stream_getc(compiler->input,
00354                                                              &ch2)) {
00355                                 if (ch2 != '\n')
00356                                     ws_stream_ungetc(compiler->input, ch2);
00357                             }
00358                             compiler->linenum++;
00359 
00360                             /* Continue reading the block comment. */
00361                             continue;
00362                         }
00363 
00364                         if (ch == '*' && ws_stream_getc(compiler->input, &ch2)) {
00365                             if (ch2 == '/')
00366                                 /* The end of the comment found. */
00367                                 break;
00368                             ws_stream_ungetc(compiler->input, ch2);
00369                         }
00370                     }
00371                     /* Continue after the comment. */
00372                     continue;
00373                 }
00374                 if (ch2 == '/') {
00375                     /* Single line comment. */
00376                     while (1) {
00377                         if (!ws_stream_getc(compiler->input, &ch))
00378                             /* The end of input stream reached.  We accept
00379                                this as a valid comment terminator. */
00380                             break;
00381 
00382                         if (ch == '\n' || ch == '\r') {
00383                             /* Line terminators. */
00384                             if (ch == '\r' && ws_stream_getc(compiler->input,
00385                                                              &ch2)) {
00386                                 if (ch2 != '\n')
00387                                     ws_stream_ungetc(compiler->input, ch2);
00388                             }
00389                             /* The end of the line (and the comment)
00390                                                     reached. */
00391                             compiler->linenum++;
00392                             break;
00393                         }
00394                     }
00395                     /* Continue after the comment. */
00396                     continue;
00397                 }
00398                 if (ch2 == '=')
00399                     return tDIVA;
00400 
00401                 ws_stream_ungetc(compiler->input, ch2);
00402             }
00403             return '/';
00404 
00405         case '<':       /* <, <<, <<=, <= */
00406             if (ws_stream_getc(compiler->input, &ch2)) {
00407                 if (ch2 == '<') {
00408                     if (ws_stream_getc(compiler->input, &ch2)) {
00409                         if (ch2 == '=')
00410                             return tLSHIFTA;
00411 
00412                         ws_stream_ungetc(compiler->input, ch2);
00413                     }
00414                     return tLSHIFT;
00415                 }
00416                 if (ch2 == '=')
00417                     return tLE;
00418 
00419                 ws_stream_ungetc(compiler->input, ch2);
00420             }
00421             return '<';
00422 
00423         case '=':       /* =, == */
00424             if (ws_stream_getc(compiler->input, &ch2)) {
00425                 if (ch2 == '=')
00426                     return tEQ;
00427 
00428                 ws_stream_ungetc(compiler->input, ch2);
00429             }
00430             return '=';
00431 
00432         case '>':       /* >, >=, >>, >>=, >>>, >>>= */
00433             if (ws_stream_getc(compiler->input, &ch2)) {
00434                 if (ch2 == '>') {
00435                     if (ws_stream_getc(compiler->input, &ch2)) {
00436                         if (ch2 == '>') {
00437                             if (ws_stream_getc(compiler->input, &ch2)) {
00438                                 if (ch2 == '=')
00439                                     return tRSZSHIFTA;
00440 
00441                                 ws_stream_ungetc(compiler->input, ch2);
00442                             }
00443                             return tRSZSHIFT;
00444                         }
00445                         if (ch2 == '=')
00446                             return tRSSHIFTA;
00447 
00448                         ws_stream_ungetc(compiler->input, ch2);
00449                     }
00450                     return tRSSHIFT;
00451                 }
00452                 if (ch2 == '=')
00453                     return tGE;
00454 
00455                 ws_stream_ungetc(compiler->input, ch2);
00456             }
00457             return '>';
00458 
00459         case '^':       /* ^, ^= */
00460             if (ws_stream_getc(compiler->input, &ch2)) {
00461                 if (ch2 == '=')
00462                     return tXORA;
00463 
00464                 ws_stream_ungetc(compiler->input, ch2);
00465             }
00466             return '^';
00467 
00468         case '|':       /* |, |=, || */
00469             if (ws_stream_getc(compiler->input, &ch2)) {
00470                 if (ch2 == '=')
00471                     return tORA;
00472                 if (ch2 == '|')
00473                     return tOR;
00474 
00475                 ws_stream_ungetc(compiler->input, ch2);
00476             }
00477             return '|';
00478 
00479         case '#':       /* The simple cases. */
00480         case '(':
00481         case ')':
00482         case ',':
00483         case ':':
00484         case ';':
00485         case '?':
00486         case '{':
00487         case '}':
00488         case '~':
00489             return (int) ch;
00490 
00491         case '\'':      /* String literals. */
00492         case '"':
00493             {
00494                 WsUInt32 string_end_ch = ch;
00495                 WsUtf8String *str = ws_utf8_alloc();
00496 
00497                 if (str == NULL) {
00498                     ws_error_memory(compiler);
00499                     return EOF;
00500                 }
00501 
00502                 while (1) {
00503                     if (!ws_stream_getc(compiler->input, &ch)) {
00504 eof_in_string_literal:
00505                         ws_src_error(compiler, 0, "EOF in string literal");
00506                         ws_utf8_free(str);
00507                         return EOF;
00508                     }
00509                     if (ch == string_end_ch)
00510                         /* The end of string reached. */
00511                         break;
00512 
00513                     if (ch == '\\') {
00514                         /* An escape sequence. */
00515                         if (!ws_stream_getc(compiler->input, &ch))
00516                             goto eof_in_string_literal;
00517 
00518                         switch (ch) {
00519                         case '\'':
00520                         case '"':
00521                         case '\\':
00522                         case '/':
00523                             /* The character as-is. */
00524                             break;
00525 
00526                         case 'b':
00527                             ch = '\b';
00528                             break;
00529 
00530                         case 'f':
00531                             ch = '\f';
00532                             break;
00533 
00534                         case 'n':
00535                             ch = '\n';
00536                             break;
00537 
00538                         case 'r':
00539                             ch = '\r';
00540                             break;
00541 
00542                         case 't':
00543                             ch = '\t';
00544                             break;
00545 
00546                         case 'x':
00547                         case 'u':
00548                             {
00549                                 int i, len;
00550                                 int type = ch;
00551 
00552                                 if (ch == 'x')
00553                                     len = 2;
00554                                 else
00555                                     len = 4;
00556 
00557                                 ch = 0;
00558                                 for (i = 0; i < len; i++) {
00559                                     if (!ws_stream_getc(compiler->input, &ch2))
00560                                         goto eof_in_string_literal;
00561                                     if (!WS_IS_HEX_DIGIT(ch2)) {
00562                                         ws_src_error(compiler, 0,
00563                                                      "malformed `\\%c' escape in "
00564                                                      "string literal", (char) type);
00565                                         ch = 0;
00566                                         break;
00567                                     }
00568                                     ch *= 16;
00569                                     ch += WS_HEX_TO_INT(ch2);
00570                                 }
00571                             }
00572                             break;
00573 
00574                         default:
00575                             if (WS_IS_OCTAL_DIGIT(ch)) {
00576                                 int i;
00577                                 int limit = 3;
00578 
00579                                 ch = WS_OCTAL_TO_INT(ch);
00580                                 if (ch > 3)
00581                                     limit = 2;
00582 
00583                                 for (i = 1; i < limit; i++) {
00584                                     if (!ws_stream_getc(compiler->input, &ch2))
00585                                         goto eof_in_string_literal;
00586                                     if (!WS_IS_OCTAL_DIGIT(ch2)) {
00587                                         ws_stream_ungetc(compiler->input, ch2);
00588                                         break;
00589                                     }
00590 
00591                                     ch *= 8;
00592                                     ch += WS_OCTAL_TO_INT(ch2);
00593                                 }
00594                             } else {
00595                                 ws_src_error(compiler, 0,
00596                                              "unknown escape sequence `\\%c' in "
00597                                              "string literal", (char) ch);
00598                                 ch = 0;
00599                             }
00600                             break;
00601                         }
00602                         /* FALLTHROUGH */
00603                     }
00604 
00605                     if (!ws_utf8_append_char(str, ch)) {
00606                         ws_error_memory(compiler);
00607                         ws_utf8_free(str);
00608                         return EOF;
00609                     }
00610                 }
00611 
00612                 if (!ws_lexer_register_utf8(compiler, str)) {
00613                     ws_error_memory(compiler);
00614                     ws_utf8_free(str);
00615                     return EOF;
00616                 }
00617 
00618                 gw_assert(str != NULL);
00619                 yylval->string = str;
00620 
00621                 return tSTRING;
00622             }
00623             break;
00624 
00625         default:
00626             /* Identifiers, keywords and number constants. */
00627 
00628             if (WS_IS_IDENTIFIER_LETTER(ch)) {
00629                 WsBool got;
00630                 int token;
00631                 unsigned char *p;
00632                 unsigned char *np;
00633                 size_t len = 0;
00634 
00635                 /* An identifier or a keyword.  We start with a 256
00636                  * bytes long buffer but it is expanded dynamically if
00637                  * needed.  However, 256 should be enought for most
00638                  * cases since the byte-code format limits the function
00639                  * names to 255 characters. */
00640                 p = ws_malloc(256);
00641                 if (p == NULL) {
00642                     ws_error_memory(compiler);
00643                     return EOF;
00644                 }
00645 
00646                 do {
00647                     /* Add one extra for the possible terminator
00648                        character. */
00649                     np = ws_realloc(p, len + 2);
00650                     if (np == NULL) {
00651                         ws_error_memory(compiler);
00652                         ws_free(p);
00653                         return EOF;
00654                     }
00655 
00656                     p = np;
00657 
00658                     /* This is ok since the only valid identifier names
00659                      * can be written in 7 bit ASCII. */
00660                     p[len++] = (unsigned char) ch;
00661                 } while ((got = ws_stream_getc(compiler->input, &ch))
00662                          && (WS_IS_IDENTIFIER_LETTER(ch)
00663                              || WS_IS_DECIMAL_DIGIT(ch)));
00664 
00665                 if (got)
00666                     /* Put back the terminator character. */
00667                     ws_stream_ungetc(compiler->input, ch);
00668 
00669                 /* Is it a keyword? */
00670                 if (lookup_keyword((char *) p, len, &token)) {
00671                     /* Yes it is... */
00672                     ws_free(p);
00673 
00674                     /* ...except one case: `div='. */
00675                     if (token == tIDIV) {
00676                         if (ws_stream_getc(compiler->input, &ch)) {
00677                             if (ch == '=')
00678                                 return tIDIVA;
00679 
00680                             ws_stream_ungetc(compiler->input, ch);
00681                         }
00682                     }
00683 
00684                     /* Return the token value. */
00685                     return token;
00686                 }
00687 
00688                 /* It is a normal identifier.  Let's pad the name with a
00689                           null-character.  We have already allocated space for
00690                           it. */
00691                 p[len] = '\0';
00692 
00693                 if (!ws_lexer_register_block(compiler, p)) {
00694                     ws_error_memory(compiler);
00695                     ws_free(p);
00696                     return EOF;
00697                 }
00698 
00699                 gw_assert(p != NULL);
00700                 yylval->identifier = (char *) p;
00701 
00702                 return tIDENTIFIER;
00703             }
00704 
00705             if (WS_IS_NON_ZERO_DIGIT(ch)) {
00706                 /* A decimal integer literal or a decimal float
00707                           literal. */
00708 
00709                 ws_buffer_init(&buffer);
00710                 if (!ws_buffer_append_space(&buffer, &p, 1)) {
00711 number_error_memory:
00712                     ws_error_memory(compiler);
00713                     ws_buffer_uninit(&buffer);
00714                     return EOF;
00715                 }
00716                 p[0] = ch;
00717 
00718                 while (ws_stream_getc(compiler->input, &ch)) {
00719                     if (WS_IS_DECIMAL_DIGIT(ch)) {
00720                         if (!ws_buffer_append_space(&buffer, &p, 1))
00721                             goto number_error_memory;
00722                         p[0] = ch;
00723                     } else if (ch == '.' || ch == 'e' || ch == 'E') {
00724                         /* DecimalFloatLiteral. */
00725                         if (ch == '.') {
00726                             if (!ws_buffer_append_space(&buffer, &p, 1))
00727                                 goto number_error_memory;
00728                             p[0] = '.';
00729 
00730                             success = read_float_from_point(compiler, &buffer,
00731                                                             &yylval->vfloat);
00732                         } else {
00733                             ws_stream_ungetc(compiler->input, ch);
00734 
00735                             success = read_float_from_exp(compiler, &buffer,
00736                                                           &yylval->vfloat);
00737                         }
00738                         ws_buffer_uninit(&buffer);
00739 
00740                         if (!success)
00741                             return EOF;
00742 
00743                         return tFLOAT;
00744                     } else {
00745                         ws_stream_ungetc(compiler->input, ch);
00746                         break;
00747                     }
00748                 }
00749 
00750                 /* Now the buffer contains an integer number as a
00751                           string.  Let's convert it to an integer number. */
00752                 yylval->integer = buffer_to_int(compiler, &buffer);
00753                 ws_buffer_uninit(&buffer);
00754 
00755                 /* Read a DecimalIntegerLiteral. */
00756                 return tINTEGER;
00757             }
00758 
00759             if (ch == '0') {
00760                 /* The integer constant 0, an octal number or a
00761                    HexIntegerLiteral. */
00762                 if (ws_stream_getc(compiler->input, &ch2)) {
00763                     if (ch2 == 'x' || ch2 == 'X') {
00764                         /* HexIntegerLiteral. */
00765 
00766                         ws_buffer_init(&buffer);
00767                         if (!ws_buffer_append_space(&buffer, &p, 2))
00768                             goto number_error_memory;
00769 
00770                         p[0] = '0';
00771                         p[1] = 'x';
00772 
00773                         while (ws_stream_getc(compiler->input, &ch)) {
00774                             if (WS_IS_HEX_DIGIT(ch)) {
00775                                 if (!ws_buffer_append_space(&buffer, &p, 1))
00776                                     goto number_error_memory;
00777                                 p[0] = ch;
00778                             } else {
00779                                 ws_stream_ungetc(compiler->input, ch);
00780                                 break;
00781                             }
00782                         }
00783 
00784                         if (ws_buffer_len(&buffer) == 2) {
00785                             ws_buffer_uninit(&buffer);
00786                             ws_src_error(compiler, 0,
00787                                          "numeric constant with no digits");
00788                             yylval->integer = 0;
00789                             return tINTEGER;
00790                         }
00791 
00792                         /* Now the buffer contains an integer number as
00793                          * a string.  Let's convert it to an integer
00794                          * number. */
00795                         yylval->integer = buffer_to_int(compiler, &buffer);
00796                         ws_buffer_uninit(&buffer);
00797 
00798                         /* Read a HexIntegerLiteral. */
00799                         return tINTEGER;
00800                     }
00801                     if (WS_IS_OCTAL_DIGIT(ch2)) {
00802                         /* OctalIntegerLiteral. */
00803 
00804                         ws_buffer_init(&buffer);
00805                         if (!ws_buffer_append_space(&buffer, &p, 2))
00806                             goto number_error_memory;
00807 
00808                         p[0] = '0';
00809                         p[1] = ch2;
00810 
00811                         while (ws_stream_getc(compiler->input, &ch)) {
00812                             if (WS_IS_OCTAL_DIGIT(ch)) {
00813                                 if (!ws_buffer_append_space(&buffer, &p, 1))
00814                                     goto number_error_memory;
00815                                 p[0] = ch;
00816                             } else {
00817                                 ws_stream_ungetc(compiler->input, ch);
00818                                 break;
00819                             }
00820                         }
00821 
00822                         /* Convert the buffer into an intger number. */
00823                         yylval->integer = buffer_to_int(compiler, &buffer);
00824                         ws_buffer_uninit(&buffer);
00825 
00826                         /* Read an OctalIntegerLiteral. */
00827                         return tINTEGER;
00828                     }
00829                     if (ch2 == '.' || ch2 == 'e' || ch2 == 'E') {
00830                         /* DecimalFloatLiteral. */
00831                         ws_buffer_init(&buffer);
00832 
00833                         if (ch2 == '.') {
00834                             if (!ws_buffer_append_space(&buffer, &p, 1))
00835                                 goto number_error_memory;
00836                             p[0] = '.';
00837 
00838                             success = read_float_from_point(compiler, &buffer,
00839                                                             &yylval->vfloat);
00840                         } else {
00841                             ws_stream_ungetc(compiler->input, ch);
00842 
00843                             success = read_float_from_exp(compiler, &buffer,
00844                                                           &yylval->vfloat);
00845                         }
00846                         ws_buffer_uninit(&buffer);
00847 
00848                         if (!success)
00849                             return EOF;
00850 
00851                         return tFLOAT;
00852                     }
00853 
00854                     ws_stream_ungetc(compiler->input, ch2);
00855                 }
00856 
00857                 /* Integer literal 0. */
00858                 yylval->integer = 0;
00859                 return tINTEGER;
00860             }
00861 
00862             /* Garbage found from the input stream. */
00863             ws_src_error(compiler, 0,
00864                          "garbage found from the input stream: character=0x%x",
00865                          ch);
00866             return EOF;
00867             break;
00868         }
00869     }
00870 
00871     return EOF;
00872 }

Here is the call graph for this function:


Variable Documentation

struct { ... } keywords[] [static]
 

Referenced by lookup_keyword().

char* name
 

Definition at line 155 of file wslexer.c.

size_t name_len
 

Definition at line 156 of file wslexer.c.

Referenced by http_header_find_first_real(), ws_bc_add_pragma_user_agent_property(), ws_bc_add_pragma_user_agent_property_and_scheme(), and ws_bc_encode().

int num_keywords = sizeof(keywords) / sizeof(keywords[0]) [static]
 

Definition at line 217 of file wslexer.c.

int token
 

Definition at line 157 of file wslexer.c.

Referenced by attr_dict_construct(), flag_date_length(), is_token(), parse_ota_syncsettings(), parse_url_value(), soap_format_xml(), wml_init(), and ws_yy_lex().

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.