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