aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1997-09-16 16:25:59 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1997-09-16 16:25:59 -0300
commit60cc473bcfce079d1525fcffcfdfbeb66e35afa2 (patch)
tree368fec478cec8637af6346e69ec66722ab38a9cf
parent43a2ee6ea1b7825c1892de614cb38a3fe487a19f (diff)
downloadlua-60cc473bcfce079d1525fcffcfdfbeb66e35afa2.tar.gz
lua-60cc473bcfce079d1525fcffcfdfbeb66e35afa2.tar.bz2
lua-60cc473bcfce079d1525fcffcfdfbeb66e35afa2.zip
Lexical Analizer
-rw-r--r--lex.h18
-rw-r--r--llex.c (renamed from lex.c)272
-rw-r--r--llex.h21
3 files changed, 155 insertions, 156 deletions
diff --git a/lex.h b/lex.h
deleted file mode 100644
index 44172325..00000000
--- a/lex.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2** lex.h
3** TecCGraf - PUC-Rio
4** $Id: lex.h,v 1.3 1996/11/08 12:49:35 roberto Exp roberto $
5*/
6
7#ifndef lex_h
8#define lex_h
9
10#include "zio.h"
11
12void lua_setinput (ZIO *z);
13void luaI_syntaxerror (char *s);
14int luaY_lex (void);
15void luaI_addReserved (void);
16
17
18#endif
diff --git a/lex.c b/llex.c
index 59588d19..0cbce7eb 100644
--- a/lex.c
+++ b/llex.c
@@ -1,27 +1,58 @@
1char *rcs_lex = "$Id: lex.c,v 3.8 1997/07/30 22:00:50 roberto Exp roberto $"; 1/*
2** $Id: $
3** Lexical Analizer
4** See Copyright Notice in lua.h
5*/
2 6
3 7
4#include <ctype.h> 8#include <ctype.h>
5#include <string.h> 9#include <string.h>
6 10
7#include "auxlib.h" 11#include "lglobal.h"
8#include "luamem.h" 12#include "llex.h"
9#include "tree.h" 13#include "lmem.h"
10#include "table.h" 14#include "lobject.h"
11#include "lex.h" 15#include "lparser.h"
12#include "inout.h" 16#include "lstring.h"
17#include "ltokens.h"
13#include "luadebug.h" 18#include "luadebug.h"
14#include "parser.h" 19#include "lzio.h"
15 20
16#define MINBUFF 250
17 21
18static int current; /* look ahead character */ 22static int current; /* look ahead character */
19static ZIO *lex_z; 23static ZIO *lex_z;
20 24
21 25
26int luaX_linenumber;
27int lua_debug=0;
28
29
22#define next() (current = zgetc(lex_z)) 30#define next() (current = zgetc(lex_z))
23#define save(x) (yytext[tokensize++] = (x)) 31
24#define save_and_next() (save(current), next()) 32
33
34static void addReserved (void)
35{
36 static struct {
37 char *name;
38 int token;
39 } reserved [] = {
40 {"and", AND}, {"do", DO}, {"else", ELSE}, {"elseif", ELSEIF},
41 {"end", END}, {"function", FUNCTION}, {"if", IF}, {"local", LOCAL},
42 {"nil", NIL}, {"not", NOT}, {"or", OR}, {"repeat", REPEAT},
43 {"return", RETURN}, {"then", THEN}, {"until", UNTIL}, {"while", WHILE}
44 };
45 static int firsttime = 1;
46 if (firsttime) {
47 int i;
48 firsttime = 0;
49 for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) {
50 TaggedString *ts = luaS_new(reserved[i].name);
51 ts->marked = reserved[i].token; /* reserved word (always > 255) */
52 }
53 }
54}
55
25 56
26 57
27#define MAX_IFS 5 58#define MAX_IFS 5
@@ -37,6 +68,12 @@ static struct {
37static int iflevel; /* level of nested $if's */ 68static int iflevel; /* level of nested $if's */
38 69
39 70
71static struct textbuff {
72 char *text;
73 int tokensize;
74 int buffsize;
75} textbuff;
76
40 77
41static void firstline (void) 78static void firstline (void)
42{ 79{
@@ -47,77 +84,26 @@ static void firstline (void)
47} 84}
48 85
49 86
50void lua_setinput (ZIO *z) 87void luaX_setinput (ZIO *z)
51{ 88{
89 addReserved();
52 current = '\n'; 90 current = '\n';
53 lua_linenumber = 0; 91 luaX_linenumber = 0;
54 iflevel = 0; 92 iflevel = 0;
55 ifstate[0].skip = 0; 93 ifstate[0].skip = 0;
56 ifstate[0].elsepart = 1; /* to avoid a free $else */ 94 ifstate[0].elsepart = 1; /* to avoid a free $else */
57 lex_z = z; 95 lex_z = z;
58 firstline(); 96 firstline();
97 textbuff.buffsize = 20;
98 textbuff.text = luaM_buffer(textbuff.buffsize);
59} 99}
60 100
61 101
62static void luaI_auxsyntaxerror (char *s)
63{
64 luaL_verror("%s;\n> at line %d in file %s",
65 s, lua_linenumber, lua_parsedfile->str);
66}
67
68static void luaI_auxsynterrbf (char *s, char *token)
69{
70 if (token[0] == 0)
71 token = "<eof>";
72 luaL_verror("%s;\n> last token read: \"%s\" at line %d in file %s",
73 s, token, lua_linenumber, lua_parsedfile->str);
74}
75
76void luaI_syntaxerror (char *s)
77{
78 luaI_auxsynterrbf(s, luaI_buffer(1));
79}
80
81
82static struct
83 {
84 char *name;
85 int token;
86 } reserved [] = {
87 {"and", AND},
88 {"do", DO},
89 {"else", ELSE},
90 {"elseif", ELSEIF},
91 {"end", END},
92 {"function", FUNCTION},
93 {"if", IF},
94 {"local", LOCAL},
95 {"nil", NIL},
96 {"not", NOT},
97 {"or", OR},
98 {"repeat", REPEAT},
99 {"return", RETURN},
100 {"then", THEN},
101 {"until", UNTIL},
102 {"while", WHILE} };
103
104
105#define RESERVEDSIZE (sizeof(reserved)/sizeof(reserved[0]))
106
107
108void luaI_addReserved (void)
109{
110 int i;
111 for (i=0; i<RESERVEDSIZE; i++)
112 {
113 TaggedString *ts = luaI_createstring(reserved[i].name);
114 ts->marked = reserved[i].token; /* reserved word (always > 255) */
115 }
116}
117
118 102
119/* 103/*
120** Pragma handling 104** =======================================================
105** PRAGMAS
106** =======================================================
121*/ 107*/
122 108
123#define PRAGMASIZE 20 109#define PRAGMASIZE 20
@@ -131,12 +117,12 @@ static void skipspace (void)
131static int checkcond (char *buff) 117static int checkcond (char *buff)
132{ 118{
133 static char *opts[] = {"nil", "1"}; 119 static char *opts[] = {"nil", "1"};
134 int i = luaI_findstring(buff, opts); 120 int i = luaO_findstring(buff, opts);
135 if (i >= 0) return i; 121 if (i >= 0) return i;
136 else if (isalpha((unsigned char)buff[0]) || buff[0] == '_') 122 else if (isalpha((unsigned char)buff[0]) || buff[0] == '_')
137 return luaI_globaldefined(buff); 123 return luaG_globaldefined(buff);
138 else { 124 else {
139 luaI_auxsynterrbf("invalid $if condition", buff); 125 luaY_syntaxerror("invalid $if condition", buff);
140 return 0; /* to avoid warnings */ 126 return 0; /* to avoid warnings */
141 } 127 }
142} 128}
@@ -146,10 +132,10 @@ static void readname (char *buff)
146{ 132{
147 int i = 0; 133 int i = 0;
148 skipspace(); 134 skipspace();
149 while (isalnum((unsigned char)current) || current == '_') { 135 while (isalnum(current) || current == '_') {
150 if (i >= PRAGMASIZE) { 136 if (i >= PRAGMASIZE) {
151 buff[PRAGMASIZE] = 0; 137 buff[PRAGMASIZE] = 0;
152 luaI_auxsynterrbf("pragma too long", buff); 138 luaY_syntaxerror("pragma too long", buff);
153 } 139 }
154 buff[i++] = current; 140 buff[i++] = current;
155 next(); 141 next();
@@ -167,7 +153,7 @@ static void ifskip (void)
167 if (current == '\n') 153 if (current == '\n')
168 inclinenumber(); 154 inclinenumber();
169 else if (current == EOZ) 155 else if (current == EOZ)
170 luaI_auxsyntaxerror("input ends inside a $if"); 156 luaY_syntaxerror("input ends inside a $if", "");
171 else next(); 157 else next();
172 } 158 }
173} 159}
@@ -175,17 +161,17 @@ static void ifskip (void)
175 161
176static void inclinenumber (void) 162static void inclinenumber (void)
177{ 163{
178 static char *pragmas [] = 164 static char *pragmas [] =
179 {"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL}; 165 {"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL};
180 next(); /* skip '\n' */ 166 next(); /* skip '\n' */
181 ++lua_linenumber; 167 ++luaX_linenumber;
182 if (current == '$') { /* is a pragma? */ 168 if (current == '$') { /* is a pragma? */
183 char buff[PRAGMASIZE+1]; 169 char buff[PRAGMASIZE+1];
184 int ifnot = 0; 170 int ifnot = 0;
185 int skip = ifstate[iflevel].skip; 171 int skip = ifstate[iflevel].skip;
186 next(); /* skip $ */ 172 next(); /* skip $ */
187 readname(buff); 173 readname(buff);
188 switch (luaI_findstring(buff, pragmas)) { 174 switch (luaO_findstring(buff, pragmas)) {
189 case 0: /* debug */ 175 case 0: /* debug */
190 if (!skip) lua_debug = 1; 176 if (!skip) lua_debug = 1;
191 break; 177 break;
@@ -200,14 +186,14 @@ static void inclinenumber (void)
200 break; 186 break;
201 case 3: /* end */ 187 case 3: /* end */
202 if (iflevel-- == 0) 188 if (iflevel-- == 0)
203 luaI_auxsyntaxerror("unmatched $endif"); 189 luaY_syntaxerror("unmatched $end", "$end");
204 break; 190 break;
205 case 4: /* ifnot */ 191 case 4: /* ifnot */
206 ifnot = 1; 192 ifnot = 1;
207 /* go through */ 193 /* go through */
208 case 5: /* if */ 194 case 5: /* if */
209 if (iflevel == MAX_IFS-1) 195 if (iflevel == MAX_IFS-1)
210 luaI_auxsyntaxerror("too many nested `$ifs'"); 196 luaY_syntaxerror("too many nested `$ifs'", "$if");
211 readname(buff); 197 readname(buff);
212 iflevel++; 198 iflevel++;
213 ifstate[iflevel].elsepart = 0; 199 ifstate[iflevel].elsepart = 0;
@@ -216,48 +202,68 @@ static void inclinenumber (void)
216 break; 202 break;
217 case 6: /* else */ 203 case 6: /* else */
218 if (ifstate[iflevel].elsepart) 204 if (ifstate[iflevel].elsepart)
219 luaI_auxsyntaxerror("unmatched $else"); 205 luaY_syntaxerror("unmatched $else", "$else");
220 ifstate[iflevel].elsepart = 1; 206 ifstate[iflevel].elsepart = 1;
221 ifstate[iflevel].skip = 207 ifstate[iflevel].skip =
222 ifstate[iflevel-1].skip || ifstate[iflevel].condition; 208 ifstate[iflevel-1].skip || ifstate[iflevel].condition;
223 break; 209 break;
224 default: 210 default:
225 luaI_auxsynterrbf("invalid pragma", buff); 211 luaY_syntaxerror("invalid pragma", buff);
226 } 212 }
227 skipspace(); 213 skipspace();
228 if (current == '\n') /* pragma must end with a '\n' ... */ 214 if (current == '\n') /* pragma must end with a '\n' ... */
229 inclinenumber(); 215 inclinenumber();
230 else if (current != EOZ) /* or eof */ 216 else if (current != EOZ) /* or eof */
231 luaI_auxsyntaxerror("invalid pragma format"); 217 luaY_syntaxerror("invalid pragma format", buff);
232 ifskip(); 218 ifskip();
233 } 219 }
234} 220}
235 221
236static int read_long_string (char *yytext, int buffsize) 222
223/*
224** =======================================================
225** LEXICAL ANALIZER
226** =======================================================
227*/
228
229
230
231static void save (int c)
232{
233 if (textbuff.tokensize >= textbuff.buffsize)
234 textbuff.text = luaM_buffer(textbuff.buffsize *= 2);
235 textbuff.text[textbuff.tokensize++] = c;
236}
237
238
239char *luaX_lasttoken (void)
240{
241 save(0);
242 return textbuff.text;
243}
244
245
246#define save_and_next() (save(current), next())
247
248
249static int read_long_string (void)
237{ 250{
238 int cont = 0; 251 int cont = 0;
239 int tokensize = 2; /* '[[' already stored */ 252 while (1) {
240 while (1) 253 switch (current) {
241 {
242 if (buffsize-tokensize <= 2) /* may read more than 1 char in one cicle */
243 yytext = luaI_buffer(buffsize *= 2);
244 switch (current)
245 {
246 case EOZ: 254 case EOZ:
247 save(0); 255 save(0);
248 return WRONGTOKEN; 256 return WRONGTOKEN;
249 case '[': 257 case '[':
250 save_and_next(); 258 save_and_next();
251 if (current == '[') 259 if (current == '[') {
252 {
253 cont++; 260 cont++;
254 save_and_next(); 261 save_and_next();
255 } 262 }
256 continue; 263 continue;
257 case ']': 264 case ']':
258 save_and_next(); 265 save_and_next();
259 if (current == ']') 266 if (current == ']') {
260 {
261 if (cont == 0) goto endloop; 267 if (cont == 0) goto endloop;
262 cont--; 268 cont--;
263 save_and_next(); 269 save_and_next();
@@ -272,29 +278,26 @@ static int read_long_string (char *yytext, int buffsize)
272 } 278 }
273 } endloop: 279 } endloop:
274 save_and_next(); /* pass the second ']' */ 280 save_and_next(); /* pass the second ']' */
275 yytext[tokensize-2] = 0; /* erases ']]' */ 281 textbuff.text[textbuff.tokensize-2] = 0; /* erases ']]' */
276 luaY_lval.pTStr = luaI_createtempstring(yytext+2); 282 luaY_lval.pTStr = luaS_new(textbuff.text+2);
277 yytext[tokensize-2] = ']'; /* restores ']]' */ 283 textbuff.text[textbuff.tokensize-2] = ']'; /* restores ']]' */
278 save(0);
279 return STRING; 284 return STRING;
280} 285}
281 286
287
282int luaY_lex (void) 288int luaY_lex (void)
283{ 289{
284 static int linelasttoken = 0; 290 static int linelasttoken = 0;
285 double a; 291 double a;
286 int buffsize = MINBUFF; 292 textbuff.tokensize = 0;
287 char *yytext = luaI_buffer(buffsize);
288 yytext[1] = yytext[2] = yytext[3] = 0;
289 if (lua_debug) 293 if (lua_debug)
290 luaI_codedebugline(linelasttoken); 294 luaY_codedebugline(linelasttoken);
291 linelasttoken = lua_linenumber; 295 linelasttoken = luaX_linenumber;
292 while (1) { 296 while (1) {
293 int tokensize = 0;
294 switch (current) { 297 switch (current) {
295 case '\n': 298 case '\n':
296 inclinenumber(); 299 inclinenumber();
297 linelasttoken = lua_linenumber; 300 linelasttoken = luaX_linenumber;
298 continue; 301 continue;
299 302
300 case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */ 303 case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */
@@ -305,15 +308,15 @@ int luaY_lex (void)
305 save_and_next(); 308 save_and_next();
306 if (current != '-') return '-'; 309 if (current != '-') return '-';
307 do { next(); } while (current != '\n' && current != EOZ); 310 do { next(); } while (current != '\n' && current != EOZ);
311 textbuff.tokensize = 0;
308 continue; 312 continue;
309 313
310 case '[': 314 case '[':
311 save_and_next(); 315 save_and_next();
312 if (current != '[') return '['; 316 if (current != '[') return '[';
313 else 317 else {
314 {
315 save_and_next(); /* pass the second '[' */ 318 save_and_next(); /* pass the second '[' */
316 return read_long_string(yytext, buffsize); 319 return read_long_string();
317 } 320 }
318 321
319 case '=': 322 case '=':
@@ -337,24 +340,18 @@ int luaY_lex (void)
337 else { save_and_next(); return NE; } 340 else { save_and_next(); return NE; }
338 341
339 case '"': 342 case '"':
340 case '\'': 343 case '\'': {
341 {
342 int del = current; 344 int del = current;
343 save_and_next(); 345 save_and_next();
344 while (current != del) 346 while (current != del) {
345 { 347 switch (current) {
346 if (buffsize-tokensize <= 2) /* may read more than 1 char in one cicle */
347 yytext = luaI_buffer(buffsize *= 2);
348 switch (current)
349 {
350 case EOZ: 348 case EOZ:
351 case '\n': 349 case '\n':
352 save(0); 350 save(0);
353 return WRONGTOKEN; 351 return WRONGTOKEN;
354 case '\\': 352 case '\\':
355 next(); /* do not save the '\' */ 353 next(); /* do not save the '\' */
356 switch (current) 354 switch (current) {
357 {
358 case 'n': save('\n'); next(); break; 355 case 'n': save('\n'); next(); break;
359 case 't': save('\t'); next(); break; 356 case 't': save('\t'); next(); break;
360 case 'r': save('\r'); next(); break; 357 case 'r': save('\r'); next(); break;
@@ -368,9 +365,8 @@ int luaY_lex (void)
368 } 365 }
369 next(); /* skip delimiter */ 366 next(); /* skip delimiter */
370 save(0); 367 save(0);
371 luaY_lval.pTStr = luaI_createtempstring(yytext+1); 368 luaY_lval.pTStr = luaS_new(textbuff.text+1);
372 tokensize--; 369 textbuff.text[textbuff.tokensize-1] = del; /* restore delimiter */
373 save(del); save(0); /* restore delimiter */
374 return STRING; 370 return STRING;
375 } 371 }
376 372
@@ -386,7 +382,7 @@ int luaY_lex (void)
386 } 382 }
387 else return CONC; /* .. */ 383 else return CONC; /* .. */
388 } 384 }
389 else if (!isdigit((unsigned char)current)) return '.'; 385 else if (!isdigit(current)) return '.';
390 /* current is a digit: goes through to number */ 386 /* current is a digit: goes through to number */
391 a=0.0; 387 a=0.0;
392 goto fraction; 388 goto fraction;
@@ -397,35 +393,36 @@ int luaY_lex (void)
397 do { 393 do {
398 a=10.0*a+(current-'0'); 394 a=10.0*a+(current-'0');
399 save_and_next(); 395 save_and_next();
400 } while (isdigit((unsigned char)current)); 396 } while (isdigit(current));
401 if (current == '.') { 397 if (current == '.') {
402 save_and_next(); 398 save_and_next();
403 if (current == '.') 399 if (current == '.') {
404 luaI_syntaxerror( 400 save(0);
401 luaY_error(
405 "ambiguous syntax (decimal point x string concatenation)"); 402 "ambiguous syntax (decimal point x string concatenation)");
403 }
406 } 404 }
407 fraction: 405 fraction:
408 { double da=0.1; 406 { double da=0.1;
409 while (isdigit((unsigned char)current)) 407 while (isdigit(current))
410 { 408 {
411 a+=(current-'0')*da; 409 a+=(current-'0')*da;
412 da/=10.0; 410 da/=10.0;
413 save_and_next(); 411 save_and_next();
414 } 412 }
415 if (current == 'e' || current == 'E') 413 if (toupper(current) == 'E') {
416 {
417 int e=0; 414 int e=0;
418 int neg; 415 int neg;
419 double ea; 416 double ea;
420 save_and_next(); 417 save_and_next();
421 neg=(current=='-'); 418 neg=(current=='-');
422 if (current == '+' || current == '-') save_and_next(); 419 if (current == '+' || current == '-') save_and_next();
423 if (!isdigit((unsigned char)current)) { 420 if (!isdigit(current)) {
424 save(0); return WRONGTOKEN; } 421 save(0); return WRONGTOKEN; }
425 do { 422 do {
426 e=10.0*e+(current-'0'); 423 e=10.0*e+(current-'0');
427 save_and_next(); 424 save_and_next();
428 } while (isdigit((unsigned char)current)); 425 } while (isdigit(current));
429 for (ea=neg?0.1:10.0; e>0; e>>=1) 426 for (ea=neg?0.1:10.0; e>0; e>>=1)
430 { 427 {
431 if (e & 1) a*=ea; 428 if (e & 1) a*=ea;
@@ -433,28 +430,27 @@ int luaY_lex (void)
433 } 430 }
434 } 431 }
435 luaY_lval.vReal = a; 432 luaY_lval.vReal = a;
436 save(0);
437 return NUMBER; 433 return NUMBER;
438 } 434 }
439 435
440 case EOZ: 436 case EOZ:
441 save(0); 437 save(0);
442 if (iflevel > 0) 438 if (iflevel > 0)
443 luaI_syntaxerror("missing $endif"); 439 luaY_error("missing $endif");
444 return 0; 440 return 0;
445 441
446 default: 442 default:
447 if (current != '_' && !isalpha((unsigned char)current)) { 443 if (current != '_' && !isalpha(current)) {
448 save_and_next(); 444 save_and_next();
449 return yytext[0]; 445 return textbuff.text[0];
450 } 446 }
451 else { /* identifier or reserved word */ 447 else { /* identifier or reserved word */
452 TaggedString *ts; 448 TaggedString *ts;
453 do { 449 do {
454 save_and_next(); 450 save_and_next();
455 } while (isalnum((unsigned char)current) || current == '_'); 451 } while (isalnum(current) || current == '_');
456 save(0); 452 save(0);
457 ts = luaI_createtempstring(yytext); 453 ts = luaS_new(textbuff.text);
458 if (ts->marked > 255) 454 if (ts->marked > 255)
459 return ts->marked; /* reserved word */ 455 return ts->marked; /* reserved word */
460 luaY_lval.pTStr = ts; 456 luaY_lval.pTStr = ts;
diff --git a/llex.h b/llex.h
new file mode 100644
index 00000000..709f98b6
--- /dev/null
+++ b/llex.h
@@ -0,0 +1,21 @@
1/*
2** $Id: $
3** Lexical Analizer
4** See Copyright Notice in lua.h
5*/
6
7#ifndef llex_h
8#define llex_h
9
10#include "lobject.h"
11#include "lzio.h"
12
13
14extern int luaX_linenumber;
15
16int luaY_lex (void);
17void luaX_setinput (ZIO *z);
18char *luaX_lasttoken (void);
19
20
21#endif