Imported from ../lua-3.2.tar.gz.
[lua.git] / src / llex.c
blob2d607d996ff171162548d3bd7c18188d8657d088
1 /*
2 ** $Id: llex.c,v 1.36 1999/06/17 17:04:03 roberto Exp $
3 ** Lexical Analyzer
4 ** See Copyright Notice in lua.h
5 */
8 #include <ctype.h>
9 #include <string.h>
11 #include "lauxlib.h"
12 #include "llex.h"
13 #include "lmem.h"
14 #include "lobject.h"
15 #include "lparser.h"
16 #include "lstate.h"
17 #include "lstring.h"
18 #include "luadebug.h"
19 #include "lzio.h"
23 #define next(LS) (LS->current = zgetc(LS->lex_z))
26 #define save(c) luaL_addchar(c)
27 #define save_and_next(LS) (save(LS->current), next(LS))
30 char *reserved [] = {"and", "do", "else", "elseif", "end", "function",
31 "if", "local", "nil", "not", "or", "repeat", "return", "then",
32 "until", "while"};
35 void luaX_init (void) {
36 int i;
37 for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) {
38 TaggedString *ts = luaS_new(reserved[i]);
39 ts->head.marked = FIRST_RESERVED+i; /* reserved word (always > 255) */
44 #define MAXSRC 80
46 void luaX_syntaxerror (LexState *ls, char *s, char *token) {
47 char buff[MAXSRC];
48 luaL_chunkid(buff, zname(ls->lex_z), sizeof(buff));
49 if (token[0] == '\0')
50 token = "<eof>";
51 luaL_verror("%.100s;\n last token read: `%.50s' at line %d in %.80s",
52 s, token, ls->linenumber, buff);
56 void luaX_error (LexState *ls, char *s) {
57 save('\0');
58 luaX_syntaxerror(ls, s, luaL_buffer());
62 void luaX_token2str (int token, char *s) {
63 if (token < 255) {
64 s[0] = (char)token;
65 s[1] = '\0';
67 else
68 strcpy(s, reserved[token-FIRST_RESERVED]);
72 static void luaX_invalidchar (LexState *ls, int c) {
73 char buff[8];
74 sprintf(buff, "0x%02X", c);
75 luaX_syntaxerror(ls, "invalid control char", buff);
79 static void firstline (LexState *LS)
81 int c = zgetc(LS->lex_z);
82 if (c == '#')
83 while ((c=zgetc(LS->lex_z)) != '\n' && c != EOZ) /* skip first line */;
84 zungetc(LS->lex_z);
88 void luaX_setinput (LexState *LS, ZIO *z)
90 LS->current = '\n';
91 LS->linenumber = 0;
92 LS->iflevel = 0;
93 LS->ifstate[0].skip = 0;
94 LS->ifstate[0].elsepart = 1; /* to avoid a free $else */
95 LS->lex_z = z;
96 LS->fs = NULL;
97 firstline(LS);
98 luaL_resetbuffer();
104 ** =======================================================
105 ** PRAGMAS
106 ** =======================================================
109 #ifndef PRAGMASIZE
110 #define PRAGMASIZE 80 /* arbitrary limit */
111 #endif
113 static void skipspace (LexState *LS) {
114 while (LS->current == ' ' || LS->current == '\t' || LS->current == '\r')
115 next(LS);
119 static int checkcond (LexState *LS, char *buff) {
120 static char *opts[] = {"nil", "1", NULL};
121 int i = luaL_findstring(buff, opts);
122 if (i >= 0) return i;
123 else if (isalpha((unsigned char)buff[0]) || buff[0] == '_')
124 return luaS_globaldefined(buff);
125 else {
126 luaX_syntaxerror(LS, "invalid $if condition", buff);
127 return 0; /* to avoid warnings */
132 static void readname (LexState *LS, char *buff) {
133 int i = 0;
134 skipspace(LS);
135 while (isalnum(LS->current) || LS->current == '_') {
136 if (i >= PRAGMASIZE) {
137 buff[PRAGMASIZE] = 0;
138 luaX_syntaxerror(LS, "pragma too long", buff);
140 buff[i++] = (char)LS->current;
141 next(LS);
143 buff[i] = 0;
147 static void inclinenumber (LexState *LS);
150 static void ifskip (LexState *LS) {
151 while (LS->ifstate[LS->iflevel].skip) {
152 if (LS->current == '\n')
153 inclinenumber(LS);
154 else if (LS->current == EOZ)
155 luaX_error(LS, "input ends inside a $if");
156 else next(LS);
161 static void inclinenumber (LexState *LS) {
162 static char *pragmas [] =
163 {"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL};
164 next(LS); /* skip '\n' */
165 ++LS->linenumber;
166 if (LS->current == '$') { /* is a pragma? */
167 char buff[PRAGMASIZE+1];
168 int ifnot = 0;
169 int skip = LS->ifstate[LS->iflevel].skip;
170 next(LS); /* skip $ */
171 readname(LS, buff);
172 switch (luaL_findstring(buff, pragmas)) {
173 case 0: /* debug */
174 if (!skip) L->debug = 1;
175 break;
176 case 1: /* nodebug */
177 if (!skip) L->debug = 0;
178 break;
179 case 2: /* endinput */
180 if (!skip) {
181 LS->current = EOZ;
182 LS->iflevel = 0; /* to allow $endinput inside a $if */
184 break;
185 case 3: /* end */
186 if (LS->iflevel-- == 0)
187 luaX_syntaxerror(LS, "unmatched $end", "$end");
188 break;
189 case 4: /* ifnot */
190 ifnot = 1;
191 /* go through */
192 case 5: /* if */
193 if (LS->iflevel == MAX_IFS-1)
194 luaX_syntaxerror(LS, "too many nested $ifs", "$if");
195 readname(LS, buff);
196 LS->iflevel++;
197 LS->ifstate[LS->iflevel].elsepart = 0;
198 LS->ifstate[LS->iflevel].condition = checkcond(LS, buff) ? !ifnot : ifnot;
199 LS->ifstate[LS->iflevel].skip = skip || !LS->ifstate[LS->iflevel].condition;
200 break;
201 case 6: /* else */
202 if (LS->ifstate[LS->iflevel].elsepart)
203 luaX_syntaxerror(LS, "unmatched $else", "$else");
204 LS->ifstate[LS->iflevel].elsepart = 1;
205 LS->ifstate[LS->iflevel].skip = LS->ifstate[LS->iflevel-1].skip ||
206 LS->ifstate[LS->iflevel].condition;
207 break;
208 default:
209 luaX_syntaxerror(LS, "unknown pragma", buff);
211 skipspace(LS);
212 if (LS->current == '\n') /* pragma must end with a '\n' ... */
213 inclinenumber(LS);
214 else if (LS->current != EOZ) /* or eof */
215 luaX_syntaxerror(LS, "invalid pragma format", buff);
216 ifskip(LS);
223 ** =======================================================
224 ** LEXICAL ANALIZER
225 ** =======================================================
230 static int read_long_string (LexState *LS) {
231 int cont = 0;
232 for (;;) {
233 switch (LS->current) {
234 case EOZ:
235 luaX_error(LS, "unfinished long string");
236 return EOS; /* to avoid warnings */
237 case '[':
238 save_and_next(LS);
239 if (LS->current == '[') {
240 cont++;
241 save_and_next(LS);
243 continue;
244 case ']':
245 save_and_next(LS);
246 if (LS->current == ']') {
247 if (cont == 0) goto endloop;
248 cont--;
249 save_and_next(LS);
251 continue;
252 case '\n':
253 save('\n');
254 inclinenumber(LS);
255 continue;
256 default:
257 save_and_next(LS);
259 } endloop:
260 save_and_next(LS); /* skip the second ']' */
261 LS->seminfo.ts = luaS_newlstr(L->Mbuffer+(L->Mbuffbase+2),
262 L->Mbuffnext-L->Mbuffbase-4);
263 return STRING;
267 int luaX_lex (LexState *LS) {
268 luaL_resetbuffer();
269 for (;;) {
270 switch (LS->current) {
272 case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */
273 next(LS);
274 continue;
276 case '\n':
277 inclinenumber(LS);
278 continue;
280 case '-':
281 save_and_next(LS);
282 if (LS->current != '-') return '-';
283 do { next(LS); } while (LS->current != '\n' && LS->current != EOZ);
284 luaL_resetbuffer();
285 continue;
287 case '[':
288 save_and_next(LS);
289 if (LS->current != '[') return '[';
290 else {
291 save_and_next(LS); /* pass the second '[' */
292 return read_long_string(LS);
295 case '=':
296 save_and_next(LS);
297 if (LS->current != '=') return '=';
298 else { save_and_next(LS); return EQ; }
300 case '<':
301 save_and_next(LS);
302 if (LS->current != '=') return '<';
303 else { save_and_next(LS); return LE; }
305 case '>':
306 save_and_next(LS);
307 if (LS->current != '=') return '>';
308 else { save_and_next(LS); return GE; }
310 case '~':
311 save_and_next(LS);
312 if (LS->current != '=') return '~';
313 else { save_and_next(LS); return NE; }
315 case '"':
316 case '\'': {
317 int del = LS->current;
318 save_and_next(LS);
319 while (LS->current != del) {
320 switch (LS->current) {
321 case EOZ:
322 case '\n':
323 luaX_error(LS, "unfinished string");
324 return EOS; /* to avoid warnings */
325 case '\\':
326 next(LS); /* do not save the '\' */
327 switch (LS->current) {
328 case 'a': save('\a'); next(LS); break;
329 case 'b': save('\b'); next(LS); break;
330 case 'f': save('\f'); next(LS); break;
331 case 'n': save('\n'); next(LS); break;
332 case 'r': save('\r'); next(LS); break;
333 case 't': save('\t'); next(LS); break;
334 case 'v': save('\v'); next(LS); break;
335 case '\n': save('\n'); inclinenumber(LS); break;
336 default : {
337 if (isdigit(LS->current)) {
338 int c = 0;
339 int i = 0;
340 do {
341 c = 10*c + (LS->current-'0');
342 next(LS);
343 } while (++i<3 && isdigit(LS->current));
344 if (c != (unsigned char)c)
345 luaX_error(LS, "escape sequence too large");
346 save(c);
348 else { /* handles \, ", ', and ? */
349 save(LS->current);
350 next(LS);
352 break;
355 break;
356 default:
357 save_and_next(LS);
360 save_and_next(LS); /* skip delimiter */
361 LS->seminfo.ts = luaS_newlstr(L->Mbuffer+(L->Mbuffbase+1),
362 L->Mbuffnext-L->Mbuffbase-2);
363 return STRING;
366 case '.':
367 save_and_next(LS);
368 if (LS->current == '.')
370 save_and_next(LS);
371 if (LS->current == '.')
373 save_and_next(LS);
374 return DOTS; /* ... */
376 else return CONC; /* .. */
378 else if (!isdigit(LS->current)) return '.';
379 goto fraction; /* LS->current is a digit: goes through to number */
381 case '0': case '1': case '2': case '3': case '4':
382 case '5': case '6': case '7': case '8': case '9':
383 do {
384 save_and_next(LS);
385 } while (isdigit(LS->current));
386 if (LS->current == '.') {
387 save_and_next(LS);
388 if (LS->current == '.') {
389 save('.');
390 luaX_error(LS,
391 "ambiguous syntax (decimal point x string concatenation)");
394 fraction:
395 while (isdigit(LS->current))
396 save_and_next(LS);
397 if (toupper(LS->current) == 'E') {
398 save_and_next(LS); /* read 'E' */
399 save_and_next(LS); /* read '+', '-' or first digit */
400 while (isdigit(LS->current))
401 save_and_next(LS);
403 save('\0');
404 LS->seminfo.r = luaO_str2d(L->Mbuffer+L->Mbuffbase);
405 if (LS->seminfo.r < 0)
406 luaX_error(LS, "invalid numeric format");
407 return NUMBER;
409 case EOZ:
410 if (LS->iflevel > 0)
411 luaX_error(LS, "input ends inside a $if");
412 return EOS;
414 default:
415 if (LS->current != '_' && !isalpha(LS->current)) {
416 int c = LS->current;
417 if (iscntrl(c))
418 luaX_invalidchar(LS, c);
419 save_and_next(LS);
420 return c;
422 else { /* identifier or reserved word */
423 TaggedString *ts;
424 do {
425 save_and_next(LS);
426 } while (isalnum(LS->current) || LS->current == '_');
427 save('\0');
428 ts = luaS_new(L->Mbuffer+L->Mbuffbase);
429 if (ts->head.marked >= FIRST_RESERVED)
430 return ts->head.marked; /* reserved word */
431 LS->seminfo.ts = ts;
432 return NAME;