xref: /illumos-gate/usr/src/uts/common/fs/zfs/lua/llex.c (revision 46ac8fdf)
1dfc11533SChris Williamson /*
2dfc11533SChris Williamson ** $Id: llex.c,v 2.63.1.3 2015/02/09 17:56:34 roberto Exp $
3dfc11533SChris Williamson ** Lexical Analyzer
4dfc11533SChris Williamson ** See Copyright Notice in lua.h
5dfc11533SChris Williamson */
6dfc11533SChris Williamson 
7dfc11533SChris Williamson #include <sys/zfs_context.h>
8dfc11533SChris Williamson 
9dfc11533SChris Williamson #define llex_c
10dfc11533SChris Williamson #define LUA_CORE
11dfc11533SChris Williamson 
12dfc11533SChris Williamson #include "lua.h"
13dfc11533SChris Williamson 
14dfc11533SChris Williamson #include "lctype.h"
15dfc11533SChris Williamson #include "ldo.h"
16dfc11533SChris Williamson #include "llex.h"
17dfc11533SChris Williamson #include "lobject.h"
18dfc11533SChris Williamson #include "lparser.h"
19dfc11533SChris Williamson #include "lstate.h"
20dfc11533SChris Williamson #include "lstring.h"
21dfc11533SChris Williamson #include "ltable.h"
22dfc11533SChris Williamson #include "lzio.h"
23dfc11533SChris Williamson 
24dfc11533SChris Williamson 
25dfc11533SChris Williamson 
26dfc11533SChris Williamson #define next(ls) (ls->current = zgetc(ls->z))
27dfc11533SChris Williamson 
28dfc11533SChris Williamson 
29dfc11533SChris Williamson 
30dfc11533SChris Williamson #define currIsNewline(ls)	(ls->current == '\n' || ls->current == '\r')
31dfc11533SChris Williamson 
32dfc11533SChris Williamson 
33dfc11533SChris Williamson /* ORDER RESERVED */
34dfc11533SChris Williamson static const char *const luaX_tokens [] = {
35dfc11533SChris Williamson     "and", "break", "do", "else", "elseif",
36dfc11533SChris Williamson     "end", "false", "for", "function", "goto", "if",
37dfc11533SChris Williamson     "in", "local", "nil", "not", "or", "repeat",
38dfc11533SChris Williamson     "return", "then", "true", "until", "while",
39dfc11533SChris Williamson     "..", "...", "==", ">=", "<=", "~=", "::", "<eof>",
40dfc11533SChris Williamson     "<number>", "<name>", "<string>"
41dfc11533SChris Williamson };
42dfc11533SChris Williamson 
43dfc11533SChris Williamson 
44dfc11533SChris Williamson #define save_and_next(ls) (save(ls, ls->current), next(ls))
45dfc11533SChris Williamson 
46dfc11533SChris Williamson 
47dfc11533SChris Williamson static l_noret lexerror (LexState *ls, const char *msg, int token);
48dfc11533SChris Williamson 
49dfc11533SChris Williamson 
save(LexState * ls,int c)50dfc11533SChris Williamson static void save (LexState *ls, int c) {
51dfc11533SChris Williamson   Mbuffer *b = ls->buff;
52dfc11533SChris Williamson   if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
53dfc11533SChris Williamson     size_t newsize;
54dfc11533SChris Williamson     if (luaZ_sizebuffer(b) >= MAX_SIZET/2)
55dfc11533SChris Williamson       lexerror(ls, "lexical element too long", 0);
56dfc11533SChris Williamson     newsize = luaZ_sizebuffer(b) * 2;
57dfc11533SChris Williamson     luaZ_resizebuffer(ls->L, b, newsize);
58dfc11533SChris Williamson   }
59dfc11533SChris Williamson   b->buffer[luaZ_bufflen(b)++] = cast(char, c);
60dfc11533SChris Williamson }
61dfc11533SChris Williamson 
62dfc11533SChris Williamson 
luaX_init(lua_State * L)63dfc11533SChris Williamson void luaX_init (lua_State *L) {
64dfc11533SChris Williamson   int i;
65dfc11533SChris Williamson   for (i=0; i<NUM_RESERVED; i++) {
66dfc11533SChris Williamson     TString *ts = luaS_new(L, luaX_tokens[i]);
67dfc11533SChris Williamson     luaS_fix(ts);  /* reserved words are never collected */
68dfc11533SChris Williamson     ts->tsv.extra = cast_byte(i+1);  /* reserved word */
69dfc11533SChris Williamson   }
70dfc11533SChris Williamson }
71dfc11533SChris Williamson 
72dfc11533SChris Williamson 
luaX_token2str(LexState * ls,int token)73dfc11533SChris Williamson const char *luaX_token2str (LexState *ls, int token) {
74dfc11533SChris Williamson   if (token < FIRST_RESERVED) {  /* single-byte symbols? */
75dfc11533SChris Williamson     lua_assert(token == cast(unsigned char, token));
76dfc11533SChris Williamson     return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) :
77dfc11533SChris Williamson                               luaO_pushfstring(ls->L, "char(%d)", token);
78dfc11533SChris Williamson   }
79dfc11533SChris Williamson   else {
80dfc11533SChris Williamson     const char *s = luaX_tokens[token - FIRST_RESERVED];
81dfc11533SChris Williamson     if (token < TK_EOS)  /* fixed format (symbols and reserved words)? */
82dfc11533SChris Williamson       return luaO_pushfstring(ls->L, LUA_QS, s);
83dfc11533SChris Williamson     else  /* names, strings, and numerals */
84dfc11533SChris Williamson       return s;
85dfc11533SChris Williamson   }
86dfc11533SChris Williamson }
87dfc11533SChris Williamson 
88dfc11533SChris Williamson 
txtToken(LexState * ls,int token)89dfc11533SChris Williamson static const char *txtToken (LexState *ls, int token) {
90dfc11533SChris Williamson   switch (token) {
91dfc11533SChris Williamson     case TK_NAME:
92dfc11533SChris Williamson     case TK_STRING:
93dfc11533SChris Williamson     case TK_NUMBER:
94dfc11533SChris Williamson       save(ls, '\0');
95dfc11533SChris Williamson       return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff));
96dfc11533SChris Williamson     default:
97dfc11533SChris Williamson       return luaX_token2str(ls, token);
98dfc11533SChris Williamson   }
99dfc11533SChris Williamson }
100dfc11533SChris Williamson 
101dfc11533SChris Williamson 
lexerror(LexState * ls,const char * msg,int token)102dfc11533SChris Williamson static l_noret lexerror (LexState *ls, const char *msg, int token) {
103dfc11533SChris Williamson   char buff[LUA_IDSIZE];
104dfc11533SChris Williamson   luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE);
105dfc11533SChris Williamson   msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
106dfc11533SChris Williamson   if (token)
107dfc11533SChris Williamson     luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token));
108dfc11533SChris Williamson   luaD_throw(ls->L, LUA_ERRSYNTAX);
109dfc11533SChris Williamson }
110dfc11533SChris Williamson 
111dfc11533SChris Williamson 
luaX_syntaxerror(LexState * ls,const char * msg)112dfc11533SChris Williamson l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
113dfc11533SChris Williamson   lexerror(ls, msg, ls->t.token);
114dfc11533SChris Williamson }
115dfc11533SChris Williamson 
116dfc11533SChris Williamson 
117dfc11533SChris Williamson /*
118dfc11533SChris Williamson ** creates a new string and anchors it in function's table so that
119dfc11533SChris Williamson ** it will not be collected until the end of the function's compilation
120dfc11533SChris Williamson ** (by that time it should be anchored in function's prototype)
121dfc11533SChris Williamson */
luaX_newstring(LexState * ls,const char * str,size_t l)122dfc11533SChris Williamson TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
123dfc11533SChris Williamson   lua_State *L = ls->L;
124dfc11533SChris Williamson   TValue *o;  /* entry for `str' */
125dfc11533SChris Williamson   TString *ts = luaS_newlstr(L, str, l);  /* create new string */
126dfc11533SChris Williamson   setsvalue2s(L, L->top++, ts);  /* temporarily anchor it in stack */
127dfc11533SChris Williamson   o = luaH_set(L, ls->fs->h, L->top - 1);
128dfc11533SChris Williamson   if (ttisnil(o)) {  /* not in use yet? (see 'addK') */
129dfc11533SChris Williamson     /* boolean value does not need GC barrier;
130dfc11533SChris Williamson        table has no metatable, so it does not need to invalidate cache */
131dfc11533SChris Williamson     setbvalue(o, 1);  /* t[string] = true */
132dfc11533SChris Williamson     luaC_checkGC(L);
133dfc11533SChris Williamson   }
134dfc11533SChris Williamson   else {  /* string already present */
135dfc11533SChris Williamson     ts = rawtsvalue(keyfromval(o));  /* re-use value previously stored */
136dfc11533SChris Williamson   }
137dfc11533SChris Williamson   L->top--;  /* remove string from stack */
138dfc11533SChris Williamson   return ts;
139dfc11533SChris Williamson }
140dfc11533SChris Williamson 
141dfc11533SChris Williamson 
142dfc11533SChris Williamson /*
143dfc11533SChris Williamson ** increment line number and skips newline sequence (any of
144dfc11533SChris Williamson ** \n, \r, \n\r, or \r\n)
145dfc11533SChris Williamson */
inclinenumber(LexState * ls)146dfc11533SChris Williamson static void inclinenumber (LexState *ls) {
147dfc11533SChris Williamson   int old = ls->current;
148dfc11533SChris Williamson   lua_assert(currIsNewline(ls));
149dfc11533SChris Williamson   next(ls);  /* skip `\n' or `\r' */
150dfc11533SChris Williamson   if (currIsNewline(ls) && ls->current != old)
151dfc11533SChris Williamson     next(ls);  /* skip `\n\r' or `\r\n' */
152dfc11533SChris Williamson   if (++ls->linenumber >= MAX_INT)
153dfc11533SChris Williamson     lexerror(ls, "chunk has too many lines", 0);
154dfc11533SChris Williamson }
155dfc11533SChris Williamson 
156dfc11533SChris Williamson 
luaX_setinput(lua_State * L,LexState * ls,ZIO * z,TString * source,int firstchar)157dfc11533SChris Williamson void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
158dfc11533SChris Williamson                     int firstchar) {
159dfc11533SChris Williamson   ls->decpoint = '.';
160dfc11533SChris Williamson   ls->L = L;
161dfc11533SChris Williamson   ls->current = firstchar;
162dfc11533SChris Williamson   ls->lookahead.token = TK_EOS;  /* no look-ahead token */
163dfc11533SChris Williamson   ls->z = z;
164dfc11533SChris Williamson   ls->fs = NULL;
165dfc11533SChris Williamson   ls->linenumber = 1;
166dfc11533SChris Williamson   ls->lastline = 1;
167dfc11533SChris Williamson   ls->source = source;
168dfc11533SChris Williamson   ls->envn = luaS_new(L, LUA_ENV);  /* create env name */
169dfc11533SChris Williamson   luaS_fix(ls->envn);  /* never collect this name */
170dfc11533SChris Williamson   luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER);  /* initialize buffer */
171dfc11533SChris Williamson }
172dfc11533SChris Williamson 
173dfc11533SChris Williamson 
174dfc11533SChris Williamson 
175dfc11533SChris Williamson /*
176dfc11533SChris Williamson ** =======================================================
177dfc11533SChris Williamson ** LEXICAL ANALYZER
178dfc11533SChris Williamson ** =======================================================
179dfc11533SChris Williamson */
180dfc11533SChris Williamson 
181dfc11533SChris Williamson 
182dfc11533SChris Williamson 
check_next(LexState * ls,const char * set)183dfc11533SChris Williamson static int check_next (LexState *ls, const char *set) {
184dfc11533SChris Williamson   if (ls->current == '\0' || !strchr(set, ls->current))
185dfc11533SChris Williamson     return 0;
186dfc11533SChris Williamson   save_and_next(ls);
187dfc11533SChris Williamson   return 1;
188dfc11533SChris Williamson }
189dfc11533SChris Williamson 
190dfc11533SChris Williamson 
191dfc11533SChris Williamson /*
192dfc11533SChris Williamson ** change all characters 'from' in buffer to 'to'
193dfc11533SChris Williamson */
buffreplace(LexState * ls,char from,char to)194dfc11533SChris Williamson static void buffreplace (LexState *ls, char from, char to) {
195dfc11533SChris Williamson   size_t n = luaZ_bufflen(ls->buff);
196dfc11533SChris Williamson   char *p = luaZ_buffer(ls->buff);
197dfc11533SChris Williamson   while (n--)
198dfc11533SChris Williamson     if (p[n] == from) p[n] = to;
199dfc11533SChris Williamson }
200dfc11533SChris Williamson 
201dfc11533SChris Williamson 
202dfc11533SChris Williamson #if !defined(getlocaledecpoint)
203dfc11533SChris Williamson #define getlocaledecpoint()	(localeconv()->decimal_point[0])
204dfc11533SChris Williamson #endif
205dfc11533SChris Williamson 
206dfc11533SChris Williamson 
207dfc11533SChris Williamson #define buff2d(b,e)	luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e)
208dfc11533SChris Williamson 
209dfc11533SChris Williamson /*
210dfc11533SChris Williamson ** in case of format error, try to change decimal point separator to
211dfc11533SChris Williamson ** the one defined in the current locale and check again
212dfc11533SChris Williamson */
trydecpoint(LexState * ls,SemInfo * seminfo)213dfc11533SChris Williamson static void trydecpoint (LexState *ls, SemInfo *seminfo) {
214dfc11533SChris Williamson   char old = ls->decpoint;
215dfc11533SChris Williamson   ls->decpoint = getlocaledecpoint();
216dfc11533SChris Williamson   buffreplace(ls, old, ls->decpoint);  /* try new decimal separator */
217dfc11533SChris Williamson   if (!buff2d(ls->buff, &seminfo->r)) {
218dfc11533SChris Williamson     /* format error with correct decimal point: no more options */
219dfc11533SChris Williamson     buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */
220dfc11533SChris Williamson     lexerror(ls, "malformed number", TK_NUMBER);
221dfc11533SChris Williamson   }
222dfc11533SChris Williamson }
223dfc11533SChris Williamson 
224dfc11533SChris Williamson 
225dfc11533SChris Williamson /* LUA_NUMBER */
226dfc11533SChris Williamson /*
227dfc11533SChris Williamson ** this function is quite liberal in what it accepts, as 'luaO_str2d'
228dfc11533SChris Williamson ** will reject ill-formed numerals.
229dfc11533SChris Williamson */
read_numeral(LexState * ls,SemInfo * seminfo)230dfc11533SChris Williamson static void read_numeral (LexState *ls, SemInfo *seminfo) {
231dfc11533SChris Williamson   const char *expo = "Ee";
232dfc11533SChris Williamson   int first = ls->current;
233dfc11533SChris Williamson   lua_assert(lisdigit(ls->current));
234dfc11533SChris Williamson   save_and_next(ls);
235dfc11533SChris Williamson   if (first == '0' && check_next(ls, "Xx"))  /* hexadecimal? */
236dfc11533SChris Williamson     expo = "Pp";
237dfc11533SChris Williamson   for (;;) {
238dfc11533SChris Williamson     if (check_next(ls, expo))  /* exponent part? */
239dfc11533SChris Williamson       check_next(ls, "+-");  /* optional exponent sign */
240dfc11533SChris Williamson     if (lisxdigit(ls->current) || ls->current == '.')
241dfc11533SChris Williamson       save_and_next(ls);
242dfc11533SChris Williamson     else  break;
243dfc11533SChris Williamson   }
244dfc11533SChris Williamson   save(ls, '\0');
245dfc11533SChris Williamson   buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */
246dfc11533SChris Williamson   if (!buff2d(ls->buff, &seminfo->r))  /* format error? */
247dfc11533SChris Williamson     trydecpoint(ls, seminfo); /* try to update decimal point separator */
248dfc11533SChris Williamson }
249dfc11533SChris Williamson 
250dfc11533SChris Williamson 
251dfc11533SChris Williamson /*
252dfc11533SChris Williamson ** skip a sequence '[=*[' or ']=*]' and return its number of '='s or
253dfc11533SChris Williamson ** -1 if sequence is malformed
254dfc11533SChris Williamson */
skip_sep(LexState * ls)255dfc11533SChris Williamson static int skip_sep (LexState *ls) {
256dfc11533SChris Williamson   int count = 0;
257dfc11533SChris Williamson   int s = ls->current;
258dfc11533SChris Williamson   lua_assert(s == '[' || s == ']');
259dfc11533SChris Williamson   save_and_next(ls);
260dfc11533SChris Williamson   while (ls->current == '=') {
261dfc11533SChris Williamson     save_and_next(ls);
262dfc11533SChris Williamson     count++;
263dfc11533SChris Williamson   }
264dfc11533SChris Williamson   return (ls->current == s) ? count : (-count) - 1;
265dfc11533SChris Williamson }
266dfc11533SChris Williamson 
267dfc11533SChris Williamson 
read_long_string(LexState * ls,SemInfo * seminfo,int sep)268dfc11533SChris Williamson static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
269dfc11533SChris Williamson   save_and_next(ls);  /* skip 2nd `[' */
270dfc11533SChris Williamson   if (currIsNewline(ls))  /* string starts with a newline? */
271dfc11533SChris Williamson     inclinenumber(ls);  /* skip it */
272dfc11533SChris Williamson   for (;;) {
273dfc11533SChris Williamson     switch (ls->current) {
274dfc11533SChris Williamson       case EOZ:
275dfc11533SChris Williamson         lexerror(ls, (seminfo) ? "unfinished long string" :
276dfc11533SChris Williamson                                  "unfinished long comment", TK_EOS);
277dfc11533SChris Williamson         break;  /* to avoid warnings */
278dfc11533SChris Williamson       case ']': {
279dfc11533SChris Williamson         if (skip_sep(ls) == sep) {
280dfc11533SChris Williamson           save_and_next(ls);  /* skip 2nd `]' */
281dfc11533SChris Williamson           goto endloop;
282dfc11533SChris Williamson         }
283dfc11533SChris Williamson         break;
284dfc11533SChris Williamson       }
285dfc11533SChris Williamson       case '\n': case '\r': {
286dfc11533SChris Williamson         save(ls, '\n');
287dfc11533SChris Williamson         inclinenumber(ls);
288dfc11533SChris Williamson         if (!seminfo) luaZ_resetbuffer(ls->buff);  /* avoid wasting space */
289dfc11533SChris Williamson         break;
290dfc11533SChris Williamson       }
291dfc11533SChris Williamson       default: {
292dfc11533SChris Williamson         if (seminfo) save_and_next(ls);
293dfc11533SChris Williamson         else next(ls);
294dfc11533SChris Williamson       }
295dfc11533SChris Williamson     }
296dfc11533SChris Williamson   } endloop:
297dfc11533SChris Williamson   if (seminfo)
298dfc11533SChris Williamson     seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
299dfc11533SChris Williamson                                      luaZ_bufflen(ls->buff) - 2*(2 + sep));
300dfc11533SChris Williamson }
301dfc11533SChris Williamson 
302dfc11533SChris Williamson 
escerror(LexState * ls,int * c,int n,const char * msg)303dfc11533SChris Williamson static void escerror (LexState *ls, int *c, int n, const char *msg) {
304dfc11533SChris Williamson   int i;
305dfc11533SChris Williamson   luaZ_resetbuffer(ls->buff);  /* prepare error message */
306dfc11533SChris Williamson   save(ls, '\\');
307dfc11533SChris Williamson   for (i = 0; i < n && c[i] != EOZ; i++)
308dfc11533SChris Williamson     save(ls, c[i]);
309dfc11533SChris Williamson   lexerror(ls, msg, TK_STRING);
310dfc11533SChris Williamson }
311dfc11533SChris Williamson 
312dfc11533SChris Williamson 
readhexaesc(LexState * ls)313dfc11533SChris Williamson static int readhexaesc (LexState *ls) {
314dfc11533SChris Williamson   int c[3], i;  /* keep input for error message */
315dfc11533SChris Williamson   int r = 0;  /* result accumulator */
316dfc11533SChris Williamson   c[0] = 'x';  /* for error message */
317dfc11533SChris Williamson   for (i = 1; i < 3; i++) {  /* read two hexadecimal digits */
318dfc11533SChris Williamson     c[i] = next(ls);
319dfc11533SChris Williamson     if (!lisxdigit(c[i]))
320dfc11533SChris Williamson       escerror(ls, c, i + 1, "hexadecimal digit expected");
321dfc11533SChris Williamson     r = (r << 4) + luaO_hexavalue(c[i]);
322dfc11533SChris Williamson   }
323dfc11533SChris Williamson   return r;
324dfc11533SChris Williamson }
325dfc11533SChris Williamson 
326dfc11533SChris Williamson 
readdecesc(LexState * ls)327dfc11533SChris Williamson static int readdecesc (LexState *ls) {
328dfc11533SChris Williamson   int c[3], i;
329dfc11533SChris Williamson   int r = 0;  /* result accumulator */
330dfc11533SChris Williamson   for (i = 0; i < 3 && lisdigit(ls->current); i++) {  /* read up to 3 digits */
331dfc11533SChris Williamson     c[i] = ls->current;
332dfc11533SChris Williamson     r = 10*r + c[i] - '0';
333dfc11533SChris Williamson     next(ls);
334dfc11533SChris Williamson   }
335dfc11533SChris Williamson   if (r > UCHAR_MAX)
336dfc11533SChris Williamson     escerror(ls, c, i, "decimal escape too large");
337dfc11533SChris Williamson   return r;
338dfc11533SChris Williamson }
339dfc11533SChris Williamson 
340dfc11533SChris Williamson 
read_string(LexState * ls,int del,SemInfo * seminfo)341dfc11533SChris Williamson static void read_string (LexState *ls, int del, SemInfo *seminfo) {
342dfc11533SChris Williamson   save_and_next(ls);  /* keep delimiter (for error messages) */
343dfc11533SChris Williamson   while (ls->current != del) {
344dfc11533SChris Williamson     switch (ls->current) {
345dfc11533SChris Williamson       case EOZ:
346dfc11533SChris Williamson         lexerror(ls, "unfinished string", TK_EOS);
347dfc11533SChris Williamson         break;  /* to avoid warnings */
348dfc11533SChris Williamson       case '\n':
349dfc11533SChris Williamson       case '\r':
350dfc11533SChris Williamson         lexerror(ls, "unfinished string", TK_STRING);
351dfc11533SChris Williamson         break;  /* to avoid warnings */
352dfc11533SChris Williamson       case '\\': {  /* escape sequences */
353dfc11533SChris Williamson         int c;  /* final character to be saved */
354dfc11533SChris Williamson         next(ls);  /* do not save the `\' */
355dfc11533SChris Williamson         switch (ls->current) {
356dfc11533SChris Williamson           case 'a': c = '\a'; goto read_save;
357dfc11533SChris Williamson           case 'b': c = '\b'; goto read_save;
358dfc11533SChris Williamson           case 'f': c = '\f'; goto read_save;
359dfc11533SChris Williamson           case 'n': c = '\n'; goto read_save;
360dfc11533SChris Williamson           case 'r': c = '\r'; goto read_save;
361dfc11533SChris Williamson           case 't': c = '\t'; goto read_save;
362dfc11533SChris Williamson           case 'v': c = '\v'; goto read_save;
363dfc11533SChris Williamson           case 'x': c = readhexaesc(ls); goto read_save;
364dfc11533SChris Williamson           case '\n': case '\r':
365dfc11533SChris Williamson             inclinenumber(ls); c = '\n'; goto only_save;
366dfc11533SChris Williamson           case '\\': case '\"': case '\'':
367dfc11533SChris Williamson             c = ls->current; goto read_save;
368dfc11533SChris Williamson           case EOZ: goto no_save;  /* will raise an error next loop */
369dfc11533SChris Williamson           case 'z': {  /* zap following span of spaces */
370dfc11533SChris Williamson             next(ls);  /* skip the 'z' */
371dfc11533SChris Williamson             while (lisspace(ls->current)) {
372dfc11533SChris Williamson               if (currIsNewline(ls)) inclinenumber(ls);
373dfc11533SChris Williamson               else next(ls);
374dfc11533SChris Williamson             }
375dfc11533SChris Williamson             goto no_save;
376dfc11533SChris Williamson           }
377dfc11533SChris Williamson           default: {
378dfc11533SChris Williamson             if (!lisdigit(ls->current))
379dfc11533SChris Williamson               escerror(ls, &ls->current, 1, "invalid escape sequence");
380dfc11533SChris Williamson             /* digital escape \ddd */
381dfc11533SChris Williamson             c = readdecesc(ls);
382dfc11533SChris Williamson             goto only_save;
383dfc11533SChris Williamson           }
384dfc11533SChris Williamson         }
385dfc11533SChris Williamson        read_save: next(ls);  /* read next character */
386dfc11533SChris Williamson        only_save: save(ls, c);  /* save 'c' */
387dfc11533SChris Williamson        no_save: break;
388dfc11533SChris Williamson       }
389dfc11533SChris Williamson       default:
390dfc11533SChris Williamson         save_and_next(ls);
391dfc11533SChris Williamson     }
392dfc11533SChris Williamson   }
393dfc11533SChris Williamson   save_and_next(ls);  /* skip delimiter */
394dfc11533SChris Williamson   seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
395dfc11533SChris Williamson                                    luaZ_bufflen(ls->buff) - 2);
396dfc11533SChris Williamson }
397dfc11533SChris Williamson 
398dfc11533SChris Williamson 
llex(LexState * ls,SemInfo * seminfo)399dfc11533SChris Williamson static int llex (LexState *ls, SemInfo *seminfo) {
400dfc11533SChris Williamson   luaZ_resetbuffer(ls->buff);
401dfc11533SChris Williamson   for (;;) {
402dfc11533SChris Williamson     switch (ls->current) {
403dfc11533SChris Williamson       case '\n': case '\r': {  /* line breaks */
404dfc11533SChris Williamson         inclinenumber(ls);
405dfc11533SChris Williamson         break;
406dfc11533SChris Williamson       }
407dfc11533SChris Williamson       case ' ': case '\f': case '\t': case '\v': {  /* spaces */
408dfc11533SChris Williamson         next(ls);
409dfc11533SChris Williamson         break;
410dfc11533SChris Williamson       }
411dfc11533SChris Williamson       case '-': {  /* '-' or '--' (comment) */
412dfc11533SChris Williamson         next(ls);
413dfc11533SChris Williamson         if (ls->current != '-') return '-';
414dfc11533SChris Williamson         /* else is a comment */
415dfc11533SChris Williamson         next(ls);
416dfc11533SChris Williamson         if (ls->current == '[') {  /* long comment? */
417dfc11533SChris Williamson           int sep = skip_sep(ls);
418dfc11533SChris Williamson           luaZ_resetbuffer(ls->buff);  /* `skip_sep' may dirty the buffer */
419dfc11533SChris Williamson           if (sep >= 0) {
420dfc11533SChris Williamson             read_long_string(ls, NULL, sep);  /* skip long comment */
421dfc11533SChris Williamson             luaZ_resetbuffer(ls->buff);  /* previous call may dirty the buff. */
422dfc11533SChris Williamson             break;
423dfc11533SChris Williamson           }
424dfc11533SChris Williamson         }
425dfc11533SChris Williamson         /* else short comment */
426dfc11533SChris Williamson         while (!currIsNewline(ls) && ls->current != EOZ)
427dfc11533SChris Williamson           next(ls);  /* skip until end of line (or end of file) */
428dfc11533SChris Williamson         break;
429dfc11533SChris Williamson       }
430dfc11533SChris Williamson       case '[': {  /* long string or simply '[' */
431dfc11533SChris Williamson         int sep = skip_sep(ls);
432dfc11533SChris Williamson         if (sep >= 0) {
433dfc11533SChris Williamson           read_long_string(ls, seminfo, sep);
434dfc11533SChris Williamson           return TK_STRING;
435dfc11533SChris Williamson         }
436dfc11533SChris Williamson         else if (sep == -1) return '[';
437dfc11533SChris Williamson         else lexerror(ls, "invalid long string delimiter", TK_STRING);
438dfc11533SChris Williamson       }
439dfc11533SChris Williamson       case '=': {
440dfc11533SChris Williamson         next(ls);
441dfc11533SChris Williamson         if (ls->current != '=') return '=';
442dfc11533SChris Williamson         else { next(ls); return TK_EQ; }
443dfc11533SChris Williamson       }
444dfc11533SChris Williamson       case '<': {
445dfc11533SChris Williamson         next(ls);
446dfc11533SChris Williamson         if (ls->current != '=') return '<';
447dfc11533SChris Williamson         else { next(ls); return TK_LE; }
448dfc11533SChris Williamson       }
449dfc11533SChris Williamson       case '>': {
450dfc11533SChris Williamson         next(ls);
451dfc11533SChris Williamson         if (ls->current != '=') return '>';
452dfc11533SChris Williamson         else { next(ls); return TK_GE; }
453dfc11533SChris Williamson       }
454dfc11533SChris Williamson       case '~': {
455dfc11533SChris Williamson         next(ls);
456dfc11533SChris Williamson         if (ls->current != '=') return '~';
457dfc11533SChris Williamson         else { next(ls); return TK_NE; }
458dfc11533SChris Williamson       }
459dfc11533SChris Williamson       case ':': {
460dfc11533SChris Williamson         next(ls);
461dfc11533SChris Williamson         if (ls->current != ':') return ':';
462dfc11533SChris Williamson         else { next(ls); return TK_DBCOLON; }
463dfc11533SChris Williamson       }
464dfc11533SChris Williamson       case '"': case '\'': {  /* short literal strings */
465dfc11533SChris Williamson         read_string(ls, ls->current, seminfo);
466dfc11533SChris Williamson         return TK_STRING;
467dfc11533SChris Williamson       }
468dfc11533SChris Williamson       case '.': {  /* '.', '..', '...', or number */
469dfc11533SChris Williamson         save_and_next(ls);
470dfc11533SChris Williamson         if (check_next(ls, ".")) {
471dfc11533SChris Williamson           if (check_next(ls, "."))
472dfc11533SChris Williamson             return TK_DOTS;   /* '...' */
473dfc11533SChris Williamson           else return TK_CONCAT;   /* '..' */
474dfc11533SChris Williamson         }
475dfc11533SChris Williamson         else if (!lisdigit(ls->current)) return '.';
476dfc11533SChris Williamson         /* else go through */
477dfc11533SChris Williamson       }
478*46ac8fdfSToomas Soome       /* FALLTHROUGH */
479dfc11533SChris Williamson       case '0': case '1': case '2': case '3': case '4':
480dfc11533SChris Williamson       case '5': case '6': case '7': case '8': case '9': {
481dfc11533SChris Williamson         read_numeral(ls, seminfo);
482dfc11533SChris Williamson         return TK_NUMBER;
483dfc11533SChris Williamson       }
484dfc11533SChris Williamson       case EOZ: {
485dfc11533SChris Williamson         return TK_EOS;
486dfc11533SChris Williamson       }
487dfc11533SChris Williamson       default: {
488dfc11533SChris Williamson         if (lislalpha(ls->current)) {  /* identifier or reserved word? */
489dfc11533SChris Williamson           TString *ts;
490dfc11533SChris Williamson           do {
491dfc11533SChris Williamson             save_and_next(ls);
492dfc11533SChris Williamson           } while (lislalnum(ls->current));
493dfc11533SChris Williamson           ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
494dfc11533SChris Williamson                                   luaZ_bufflen(ls->buff));
495dfc11533SChris Williamson           seminfo->ts = ts;
496dfc11533SChris Williamson           if (isreserved(ts))  /* reserved word? */
497dfc11533SChris Williamson             return ts->tsv.extra - 1 + FIRST_RESERVED;
498dfc11533SChris Williamson           else {
499dfc11533SChris Williamson             return TK_NAME;
500dfc11533SChris Williamson           }
501dfc11533SChris Williamson         }
502dfc11533SChris Williamson         else {  /* single-char tokens (+ - / ...) */
503dfc11533SChris Williamson           int c = ls->current;
504dfc11533SChris Williamson           next(ls);
505dfc11533SChris Williamson           return c;
506dfc11533SChris Williamson         }
507dfc11533SChris Williamson       }
508dfc11533SChris Williamson     }
509dfc11533SChris Williamson   }
510dfc11533SChris Williamson }
511dfc11533SChris Williamson 
512dfc11533SChris Williamson 
luaX_next(LexState * ls)513dfc11533SChris Williamson void luaX_next (LexState *ls) {
514dfc11533SChris Williamson   ls->lastline = ls->linenumber;
515dfc11533SChris Williamson   if (ls->lookahead.token != TK_EOS) {  /* is there a look-ahead token? */
516dfc11533SChris Williamson     ls->t = ls->lookahead;  /* use this one */
517dfc11533SChris Williamson     ls->lookahead.token = TK_EOS;  /* and discharge it */
518dfc11533SChris Williamson   }
519dfc11533SChris Williamson   else
520dfc11533SChris Williamson     ls->t.token = llex(ls, &ls->t.seminfo);  /* read next token */
521dfc11533SChris Williamson }
522dfc11533SChris Williamson 
523dfc11533SChris Williamson 
luaX_lookahead(LexState * ls)524dfc11533SChris Williamson int luaX_lookahead (LexState *ls) {
525dfc11533SChris Williamson   lua_assert(ls->lookahead.token == TK_EOS);
526dfc11533SChris Williamson   ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
527dfc11533SChris Williamson   return ls->lookahead.token;
528dfc11533SChris Williamson }
529dfc11533SChris Williamson 
530