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