LCOV - code coverage report
Current view: directory - src - llex.c Found Hit Coverage
Test: Lua 5.1.4 Lines: 241 200 83.0 %
Date: 2009-09-13
Colors: not hit hit

       1                 : /*
       2                 : ** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $
       3                 : ** Lexical Analyzer
       4                 : ** See Copyright Notice in lua.h
       5                 : */
       6                 : 
       7                 : 
       8                 : #include <ctype.h>
       9                 : #include <locale.h>
      10                 : #include <string.h>
      11                 : 
      12                 : #define llex_c
      13                 : #define LUA_CORE
      14                 : 
      15                 : #include "lua.h"
      16                 : 
      17                 : #include "ldo.h"
      18                 : #include "llex.h"
      19                 : #include "lobject.h"
      20                 : #include "lparser.h"
      21                 : #include "lstate.h"
      22                 : #include "lstring.h"
      23                 : #include "ltable.h"
      24                 : #include "lzio.h"
      25                 : 
      26                 : 
      27                 : 
      28                 : #define next(ls) (ls->current = zgetc(ls->z))
      29                 : 
      30                 : 
      31                 : 
      32                 : 
      33                 : #define currIsNewline(ls)       (ls->current == '\n' || ls->current == '\r')
      34                 : 
      35                 : 
      36                 : /* ORDER RESERVED */
      37                 : const char *const luaX_tokens [] = {
      38                 :     "and", "break", "do", "else", "elseif",
      39                 :     "end", "false", "for", "function", "if",
      40                 :     "in", "local", "nil", "not", "or", "repeat",
      41                 :     "return", "then", "true", "until", "while",
      42                 :     "..", "...", "==", ">=", "<=", "~=",
      43                 :     "<number>", "<name>", "<string>", "<eof>",
      44                 :     NULL
      45                 : };
      46                 : 
      47                 : 
      48                 : #define save_and_next(ls) (save(ls, ls->current), next(ls))
      49                 : 
      50                 : 
      51          190520 : static void save (LexState *ls, int c) {
      52          190520 :   Mbuffer *b = ls->buff;
      53          190520 :   if (b->n + 1 > b->buffsize) {
      54                 :     size_t newsize;
      55              59 :     if (b->buffsize >= MAX_SIZET/2)
      56               0 :       luaX_lexerror(ls, "lexical element too long", 0);
      57              59 :     newsize = b->buffsize * 2;
      58              59 :     luaZ_resizebuffer(ls->L, b, newsize);
      59                 :   }
      60          190520 :   b->buffer[b->n++] = cast(char, c);
      61          190520 : }
      62                 : 
      63                 : 
      64              35 : void luaX_init (lua_State *L) {
      65                 :   int i;
      66             770 :   for (i=0; i<NUM_RESERVED; i++) {
      67             735 :     TString *ts = luaS_new(L, luaX_tokens[i]);
      68             735 :     luaS_fix(ts);  /* reserved words are never collected */
      69                 :     lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
      70             735 :     ts->tsv.reserved = cast_byte(i+1);  /* reserved word */
      71                 :   }
      72              35 : }
      73                 : 
      74                 : 
      75                 : #define MAXSRC          80
      76                 : 
      77                 : 
      78               7 : const char *luaX_token2str (LexState *ls, int token) {
      79               7 :   if (token < FIRST_RESERVED) {
      80                 :     lua_assert(token == cast(unsigned char, token));
      81               5 :     return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) :
      82                 :                               luaO_pushfstring(ls->L, "%c", token);
      83                 :   }
      84                 :   else
      85               2 :     return luaX_tokens[token-FIRST_RESERVED];
      86                 : }
      87                 : 
      88                 : 
      89               7 : static const char *txtToken (LexState *ls, int token) {
      90               7 :   switch (token) {
      91                 :     case TK_NAME:
      92                 :     case TK_STRING:
      93                 :     case TK_NUMBER:
      94               0 :       save(ls, '\0');
      95               0 :       return luaZ_buffer(ls->buff);
      96                 :     default:
      97               7 :       return luaX_token2str(ls, token);
      98                 :   }
      99                 : }
     100                 : 
     101                 : 
     102               7 : void luaX_lexerror (LexState *ls, const char *msg, int token) {
     103                 :   char buff[MAXSRC];
     104               7 :   luaO_chunkid(buff, getstr(ls->source), MAXSRC);
     105               7 :   msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
     106               7 :   if (token)
     107               7 :     luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token));
     108               7 :   luaD_throw(ls->L, LUA_ERRSYNTAX);
     109               0 : }
     110                 : 
     111                 : 
     112               7 : void luaX_syntaxerror (LexState *ls, const char *msg) {
     113               7 :   luaX_lexerror(ls, msg, ls->t.token);
     114               0 : }
     115                 : 
     116                 : 
     117           36291 : TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
     118           36291 :   lua_State *L = ls->L;
     119           36291 :   TString *ts = luaS_newlstr(L, str, l);
     120           36291 :   TValue *o = luaH_setstr(L, ls->fs->h, ts);  /* entry for `str' */
     121           36291 :   if (ttisnil(o))
     122           20538 :     setbvalue(o, 1);  /* make sure `str' will not be collected */
     123           36291 :   return ts;
     124                 : }
     125                 : 
     126                 : 
     127           15372 : static void inclinenumber (LexState *ls) {
     128           15372 :   int old = ls->current;
     129                 :   lua_assert(currIsNewline(ls));
     130           15372 :   next(ls);  /* skip `\n' or `\r' */
     131           15372 :   if (currIsNewline(ls) && ls->current != old)
     132               0 :     next(ls);  /* skip `\n\r' or `\r\n' */
     133           15372 :   if (++ls->linenumber >= MAX_INT)
     134               0 :     luaX_syntaxerror(ls, "chunk has too many lines");
     135           15372 : }
     136                 : 
     137                 : 
     138             291 : void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
     139             291 :   ls->decpoint = '.';
     140             291 :   ls->L = L;
     141             291 :   ls->lookahead.token = TK_EOS;  /* no look-ahead token */
     142             291 :   ls->z = z;
     143             291 :   ls->fs = NULL;
     144             291 :   ls->linenumber = 1;
     145             291 :   ls->lastline = 1;
     146             291 :   ls->source = source;
     147             291 :   luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER);  /* initialize buffer */
     148             291 :   next(ls);  /* read first char */
     149             291 : }
     150                 : 
     151                 : 
     152                 : 
     153                 : /*
     154                 : ** =======================================================
     155                 : ** LEXICAL ANALYZER
     156                 : ** =======================================================
     157                 : */
     158                 : 
     159                 : 
     160                 : 
     161            7198 : static int check_next (LexState *ls, const char *set) {
     162            7198 :   if (!strchr(set, ls->current))
     163            5683 :     return 0;
     164            1515 :   save_and_next(ls);
     165            1515 :   return 1;
     166                 : }
     167                 : 
     168                 : 
     169            2023 : static void buffreplace (LexState *ls, char from, char to) {
     170            2023 :   size_t n = luaZ_bufflen(ls->buff);
     171            2023 :   char *p = luaZ_buffer(ls->buff);
     172            8719 :   while (n--)
     173            4673 :     if (p[n] == from) p[n] = to;
     174            2023 : }
     175                 : 
     176                 : 
     177               0 : static void trydecpoint (LexState *ls, SemInfo *seminfo) {
     178                 :   /* format error: try to update decimal point separator */
     179               0 :   struct lconv *cv = localeconv();
     180               0 :   char old = ls->decpoint;
     181               0 :   ls->decpoint = (cv ? cv->decimal_point[0] : '.');
     182               0 :   buffreplace(ls, old, ls->decpoint);  /* try updated decimal separator */
     183               0 :   if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
     184                 :     /* format error with correct decimal point: no more options */
     185               0 :     buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */
     186               0 :     luaX_lexerror(ls, "malformed number", TK_NUMBER);
     187                 :   }
     188               0 : }
     189                 : 
     190                 : 
     191                 : /* LUA_NUMBER */
     192            2645 : static void read_numeral (LexState *ls, SemInfo *seminfo) {
     193                 :   lua_assert(isdigit(ls->current));
     194                 :   do {
     195            2645 :     save_and_next(ls);
     196            2645 :   } while (isdigit(ls->current) || ls->current == '.');
     197            2023 :   if (check_next(ls, "Ee"))  /* `E'? */
     198               2 :     check_next(ls, "+-");  /* optional exponent sign */
     199            4048 :   while (isalnum(ls->current) || ls->current == '_')
     200               2 :     save_and_next(ls);
     201            2023 :   save(ls, '\0');
     202            2023 :   buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */
     203            2023 :   if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r))  /* format error? */
     204               0 :     trydecpoint(ls, seminfo); /* try to update decimal point separator */
     205            2023 : }
     206                 : 
     207                 : 
     208             811 : static int skip_sep (LexState *ls) {
     209             811 :   int count = 0;
     210             811 :   int s = ls->current;
     211                 :   lua_assert(s == '[' || s == ']');
     212             811 :   save_and_next(ls);
     213            1622 :   while (ls->current == '=') {
     214               0 :     save_and_next(ls);
     215               0 :     count++;
     216                 :   }
     217             811 :   return (ls->current == s) ? count : (-count) - 1;
     218                 : }
     219                 : 
     220                 : 
     221             160 : static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
     222             160 :   int cont = 0;
     223                 :   (void)(cont);  /* avoid warnings when `cont' is not used */
     224             160 :   save_and_next(ls);  /* skip 2nd `[' */
     225             160 :   if (currIsNewline(ls))  /* string starts with a newline? */
     226              46 :     inclinenumber(ls);  /* skip it */
     227                 :   for (;;) {
     228           11295 :     switch (ls->current) {
     229                 :       case EOZ:
     230               0 :         luaX_lexerror(ls, (seminfo) ? "unfinished long string" :
     231                 :                                    "unfinished long comment", TK_EOS);
     232               0 :         break;  /* to avoid warnings */
     233                 : #if defined(LUA_COMPAT_LSTR)
     234                 :       case '[': {
     235               0 :         if (skip_sep(ls) == sep) {
     236               0 :           save_and_next(ls);  /* skip 2nd `[' */
     237               0 :           cont++;
     238                 : #if LUA_COMPAT_LSTR == 1
     239               0 :           if (sep == 0)
     240               0 :             luaX_lexerror(ls, "nesting of [[...]] is deprecated", '[');
     241                 : #endif
     242                 :         }
     243               0 :         break;
     244                 :       }
     245                 : #endif
     246                 :       case ']': {
     247             160 :         if (skip_sep(ls) == sep) {
     248             160 :           save_and_next(ls);  /* skip 2nd `]' */
     249                 : #if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2
     250                 :           cont--;
     251                 :           if (sep == 0 && cont >= 0) break;
     252                 : #endif
     253             160 :           goto endloop;
     254                 :         }
     255               0 :         break;
     256                 :       }
     257                 :       case '\n':
     258                 :       case '\r': {
     259             640 :         save(ls, '\n');
     260             640 :         inclinenumber(ls);
     261             640 :         if (!seminfo) luaZ_resetbuffer(ls->buff);  /* avoid wasting space */
     262             640 :         break;
     263                 :       }
     264                 :       default: {
     265           10495 :         if (seminfo) save_and_next(ls);
     266            8476 :         else next(ls);
     267                 :       }
     268                 :     }
     269           11135 :   } endloop:
     270             160 :   if (seminfo)
     271              57 :     seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
     272                 :                                      luaZ_bufflen(ls->buff) - 2*(2 + sep));
     273             160 : }
     274                 : 
     275                 : 
     276            4321 : static void read_string (LexState *ls, int del, SemInfo *seminfo) {
     277            4321 :   save_and_next(ls);
     278           51404 :   while (ls->current != del) {
     279           42762 :     switch (ls->current) {
     280                 :       case EOZ:
     281               0 :         luaX_lexerror(ls, "unfinished string", TK_EOS);
     282               0 :         continue;  /* to avoid warnings */
     283                 :       case '\n':
     284                 :       case '\r':
     285               0 :         luaX_lexerror(ls, "unfinished string", TK_STRING);
     286               0 :         continue;  /* to avoid warnings */
     287                 :       case '\\': {
     288                 :         int c;
     289             543 :         next(ls);  /* do not save the `\' */
     290             543 :         switch (ls->current) {
     291               0 :           case 'a': c = '\a'; break;
     292               0 :           case 'b': c = '\b'; break;
     293              10 :           case 'f': c = '\f'; break;
     294             313 :           case 'n': c = '\n'; break;
     295              10 :           case 'r': c = '\r'; break;
     296             168 :           case 't': c = '\t'; break;
     297               0 :           case 'v': c = '\v'; break;
     298                 :           case '\n':  /* go through */
     299               0 :           case '\r': save(ls, '\n'); inclinenumber(ls); continue;
     300               0 :           case EOZ: continue;  /* will raise an error next loop */
     301                 :           default: {
     302              42 :             if (!isdigit(ls->current))
     303              18 :               save_and_next(ls);  /* handles \\, \", \', and \? */
     304                 :             else {  /* \xxx */
     305              24 :               int i = 0;
     306              24 :               c = 0;
     307                 :               do {
     308              57 :                 c = 10*c + (ls->current-'0');
     309              57 :                 next(ls);
     310              57 :               } while (++i<3 && isdigit(ls->current));
     311              24 :               if (c > UCHAR_MAX)
     312               0 :                 luaX_lexerror(ls, "escape sequence too large", TK_STRING);
     313              24 :               save(ls, c);
     314                 :             }
     315              42 :             continue;
     316                 :           }
     317                 :         }
     318             501 :         save(ls, c);
     319             501 :         next(ls);
     320             501 :         continue;
     321                 :       }
     322                 :       default:
     323           42219 :         save_and_next(ls);
     324                 :     }
     325                 :   }
     326            4321 :   save_and_next(ls);  /* skip delimiter */
     327            4321 :   seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
     328                 :                                    luaZ_bufflen(ls->buff) - 2);
     329            4321 : }
     330                 : 
     331                 : 
     332           66659 : static int llex (LexState *ls, SemInfo *seminfo) {
     333           66659 :   luaZ_resetbuffer(ls->buff);
     334                 :   for (;;) {
     335          170000 :     switch (ls->current) {
     336                 :       case '\n':
     337                 :       case '\r': {
     338           14686 :         inclinenumber(ls);
     339           14686 :         continue;
     340                 :       }
     341                 :       case '-': {
     342            1341 :         next(ls);
     343            1341 :         if (ls->current != '-') return '-';
     344                 :         /* else is a comment */
     345            1184 :         next(ls);
     346            1184 :         if (ls->current == '[') {
     347             103 :           int sep = skip_sep(ls);
     348             103 :           luaZ_resetbuffer(ls->buff);  /* `skip_sep' may dirty the buffer */
     349             103 :           if (sep >= 0) {
     350             103 :             read_long_string(ls, NULL, sep);  /* long comment */
     351             103 :             luaZ_resetbuffer(ls->buff);
     352             103 :             continue;
     353                 :           }
     354                 :         }
     355                 :         /* else short comment */
     356           22449 :         while (!currIsNewline(ls) && ls->current != EOZ)
     357           20287 :           next(ls);
     358            1081 :         continue;
     359                 :       }
     360                 :       case '[': {
     361             548 :         int sep = skip_sep(ls);
     362             548 :         if (sep >= 0) {
     363              57 :           read_long_string(ls, seminfo, sep);
     364              57 :           return TK_STRING;
     365                 :         }
     366             491 :         else if (sep == -1) return '[';
     367               0 :         else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
     368                 :       }
     369                 :       case '=': {
     370            3389 :         next(ls);
     371            3389 :         if (ls->current != '=') return '=';
     372             455 :         else { next(ls); return TK_EQ; }
     373                 :       }
     374                 :       case '<': {
     375             147 :         next(ls);
     376             147 :         if (ls->current != '=') return '<';
     377              58 :         else { next(ls); return TK_LE; }
     378                 :       }
     379                 :       case '>': {
     380             128 :         next(ls);
     381             128 :         if (ls->current != '=') return '>';
     382              69 :         else { next(ls); return TK_GE; }
     383                 :       }
     384                 :       case '~': {
     385             217 :         next(ls);
     386             217 :         if (ls->current != '=') return '~';
     387             217 :         else { next(ls); return TK_NE; }
     388                 :       }
     389                 :       case '"':
     390                 :       case '\'': {
     391            4321 :         read_string(ls, ls->current, seminfo);
     392            4321 :         return TK_STRING;
     393                 :       }
     394                 :       case '.': {
     395            3687 :         save_and_next(ls);
     396            3687 :         if (check_next(ls, ".")) {
     397            1486 :           if (check_next(ls, "."))
     398              26 :             return TK_DOTS;   /* ... */
     399            1460 :           else return TK_CONCAT;   /* .. */
     400                 :         }
     401            2201 :         else if (!isdigit(ls->current)) return '.';
     402                 :         else {
     403               0 :           read_numeral(ls, seminfo);
     404               0 :           return TK_NUMBER;
     405                 :         }
     406                 :       }
     407                 :       case EOZ: {
     408             284 :         return TK_EOS;
     409                 :       }
     410                 :       default: {
     411          141252 :         if (isspace(ls->current)) {
     412                 :           lua_assert(!currIsNewline(ls));
     413           87471 :           next(ls);
     414           87471 :           continue;
     415                 :         }
     416           53781 :         else if (isdigit(ls->current)) {
     417            2023 :           read_numeral(ls, seminfo);
     418            2023 :           return TK_NUMBER;
     419                 :         }
     420           51758 :         else if (isalpha(ls->current) || ls->current == '_') {
     421                 :           /* identifier or reserved word */
     422                 :           TString *ts;
     423                 :           do {
     424          125454 :             save_and_next(ls);
     425          125454 :           } while (isalnum(ls->current) || ls->current == '_');
     426           31206 :           ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
     427                 :                                   luaZ_bufflen(ls->buff));
     428           31206 :           if (ts->tsv.reserved > 0)  /* reserved word? */
     429           10274 :             return ts->tsv.reserved - 1 + FIRST_RESERVED;
     430                 :           else {
     431           20932 :             seminfo->ts = ts;
     432           20932 :             return TK_NAME;
     433                 :           }
     434                 :         }
     435                 :         else {
     436           20552 :           int c = ls->current;
     437           20552 :           next(ls);
     438           20552 :           return c;  /* single-char tokens (+ - / ...) */
     439                 :         }
     440                 :       }
     441                 :     }
     442          103341 :   }
     443                 : }
     444                 : 
     445                 : 
     446           66659 : void luaX_next (LexState *ls) {
     447           66659 :   ls->lastline = ls->linenumber;
     448           66659 :   if (ls->lookahead.token != TK_EOS) {  /* is there a look-ahead token? */
     449             373 :     ls->t = ls->lookahead;  /* use this one */
     450             373 :     ls->lookahead.token = TK_EOS;  /* and discharge it */
     451                 :   }
     452                 :   else
     453           66286 :     ls->t.token = llex(ls, &ls->t.seminfo);  /* read next token */
     454           66659 : }
     455                 : 
     456                 : 
     457             373 : void luaX_lookahead (LexState *ls) {
     458                 :   lua_assert(ls->lookahead.token == TK_EOS);
     459             373 :   ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
     460             373 : }
     461                 : 

Generated by: LCOV version 1.7