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