aboutsummaryrefslogtreecommitdiff
path: root/lex.c
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 /lex.c
parent43a2ee6ea1b7825c1892de614cb38a3fe487a19f (diff)
downloadlua-60cc473bcfce079d1525fcffcfdfbeb66e35afa2.tar.gz
lua-60cc473bcfce079d1525fcffcfdfbeb66e35afa2.tar.bz2
lua-60cc473bcfce079d1525fcffcfdfbeb66e35afa2.zip
Lexical Analizer
Diffstat (limited to 'lex.c')
-rw-r--r--lex.c466
1 files changed, 0 insertions, 466 deletions
diff --git a/lex.c b/lex.c
deleted file mode 100644
index 59588d19..00000000
--- a/lex.c
+++ /dev/null
@@ -1,466 +0,0 @@
1char *rcs_lex = "$Id: lex.c,v 3.8 1997/07/30 22:00:50 roberto Exp roberto $";
2
3
4#include <ctype.h>
5#include <string.h>
6
7#include "auxlib.h"
8#include "luamem.h"
9#include "tree.h"
10#include "table.h"
11#include "lex.h"
12#include "inout.h"
13#include "luadebug.h"
14#include "parser.h"
15
16#define MINBUFF 250
17
18static int current; /* look ahead character */
19static ZIO *lex_z;
20
21
22#define next() (current = zgetc(lex_z))
23#define save(x) (yytext[tokensize++] = (x))
24#define save_and_next() (save(current), next())
25
26
27#define MAX_IFS 5
28
29/* "ifstate" keeps the state of each nested $if the lexical is dealing with. */
30
31static struct {
32 int elsepart; /* true if its in the $else part */
33 int condition; /* true if $if condition is true */
34 int skip; /* true if part must be skiped */
35} ifstate[MAX_IFS];
36
37static int iflevel; /* level of nested $if's */
38
39
40
41static void firstline (void)
42{
43 int c = zgetc(lex_z);
44 if (c == '#')
45 while((c=zgetc(lex_z)) != '\n' && c != EOZ) /* skip first line */;
46 zungetc(lex_z);
47}
48
49
50void lua_setinput (ZIO *z)
51{
52 current = '\n';
53 lua_linenumber = 0;
54 iflevel = 0;
55 ifstate[0].skip = 0;
56 ifstate[0].elsepart = 1; /* to avoid a free $else */
57 lex_z = z;
58 firstline();
59}
60
61
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
119/*
120** Pragma handling
121*/
122
123#define PRAGMASIZE 20
124
125static void skipspace (void)
126{
127 while (current == ' ' || current == '\t') next();
128}
129
130
131static int checkcond (char *buff)
132{
133 static char *opts[] = {"nil", "1"};
134 int i = luaI_findstring(buff, opts);
135 if (i >= 0) return i;
136 else if (isalpha((unsigned char)buff[0]) || buff[0] == '_')
137 return luaI_globaldefined(buff);
138 else {
139 luaI_auxsynterrbf("invalid $if condition", buff);
140 return 0; /* to avoid warnings */
141 }
142}
143
144
145static void readname (char *buff)
146{
147 int i = 0;
148 skipspace();
149 while (isalnum((unsigned char)current) || current == '_') {
150 if (i >= PRAGMASIZE) {
151 buff[PRAGMASIZE] = 0;
152 luaI_auxsynterrbf("pragma too long", buff);
153 }
154 buff[i++] = current;
155 next();
156 }
157 buff[i] = 0;
158}
159
160
161static void inclinenumber (void);
162
163
164static void ifskip (void)
165{
166 while (ifstate[iflevel].skip) {
167 if (current == '\n')
168 inclinenumber();
169 else if (current == EOZ)
170 luaI_auxsyntaxerror("input ends inside a $if");
171 else next();
172 }
173}
174
175
176static void inclinenumber (void)
177{
178 static char *pragmas [] =
179 {"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL};
180 next(); /* skip '\n' */
181 ++lua_linenumber;
182 if (current == '$') { /* is a pragma? */
183 char buff[PRAGMASIZE+1];
184 int ifnot = 0;
185 int skip = ifstate[iflevel].skip;
186 next(); /* skip $ */
187 readname(buff);
188 switch (luaI_findstring(buff, pragmas)) {
189 case 0: /* debug */
190 if (!skip) lua_debug = 1;
191 break;
192 case 1: /* nodebug */
193 if (!skip) lua_debug = 0;
194 break;
195 case 2: /* endinput */
196 if (!skip) {
197 current = EOZ;
198 iflevel = 0; /* to allow $endinput inside a $if */
199 }
200 break;
201 case 3: /* end */
202 if (iflevel-- == 0)
203 luaI_auxsyntaxerror("unmatched $endif");
204 break;
205 case 4: /* ifnot */
206 ifnot = 1;
207 /* go through */
208 case 5: /* if */
209 if (iflevel == MAX_IFS-1)
210 luaI_auxsyntaxerror("too many nested `$ifs'");
211 readname(buff);
212 iflevel++;
213 ifstate[iflevel].elsepart = 0;
214 ifstate[iflevel].condition = checkcond(buff) ? !ifnot : ifnot;
215 ifstate[iflevel].skip = skip || !ifstate[iflevel].condition;
216 break;
217 case 6: /* else */
218 if (ifstate[iflevel].elsepart)
219 luaI_auxsyntaxerror("unmatched $else");
220 ifstate[iflevel].elsepart = 1;
221 ifstate[iflevel].skip =
222 ifstate[iflevel-1].skip || ifstate[iflevel].condition;
223 break;
224 default:
225 luaI_auxsynterrbf("invalid pragma", buff);
226 }
227 skipspace();
228 if (current == '\n') /* pragma must end with a '\n' ... */
229 inclinenumber();
230 else if (current != EOZ) /* or eof */
231 luaI_auxsyntaxerror("invalid pragma format");
232 ifskip();
233 }
234}
235
236static int read_long_string (char *yytext, int buffsize)
237{
238 int cont = 0;
239 int tokensize = 2; /* '[[' already stored */
240 while (1)
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:
247 save(0);
248 return WRONGTOKEN;
249 case '[':
250 save_and_next();
251 if (current == '[')
252 {
253 cont++;
254 save_and_next();
255 }
256 continue;
257 case ']':
258 save_and_next();
259 if (current == ']')
260 {
261 if (cont == 0) goto endloop;
262 cont--;
263 save_and_next();
264 }
265 continue;
266 case '\n':
267 save('\n');
268 inclinenumber();
269 continue;
270 default:
271 save_and_next();
272 }
273 } endloop:
274 save_and_next(); /* pass the second ']' */
275 yytext[tokensize-2] = 0; /* erases ']]' */
276 luaY_lval.pTStr = luaI_createtempstring(yytext+2);
277 yytext[tokensize-2] = ']'; /* restores ']]' */
278 save(0);
279 return STRING;
280}
281
282int luaY_lex (void)
283{
284 static int linelasttoken = 0;
285 double a;
286 int buffsize = MINBUFF;
287 char *yytext = luaI_buffer(buffsize);
288 yytext[1] = yytext[2] = yytext[3] = 0;
289 if (lua_debug)
290 luaI_codedebugline(linelasttoken);
291 linelasttoken = lua_linenumber;
292 while (1) {
293 int tokensize = 0;
294 switch (current) {
295 case '\n':
296 inclinenumber();
297 linelasttoken = lua_linenumber;
298 continue;
299
300 case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */
301 next();
302 continue;
303
304 case '-':
305 save_and_next();
306 if (current != '-') return '-';
307 do { next(); } while (current != '\n' && current != EOZ);
308 continue;
309
310 case '[':
311 save_and_next();
312 if (current != '[') return '[';
313 else
314 {
315 save_and_next(); /* pass the second '[' */
316 return read_long_string(yytext, buffsize);
317 }
318
319 case '=':
320 save_and_next();
321 if (current != '=') return '=';
322 else { save_and_next(); return EQ; }
323
324 case '<':
325 save_and_next();
326 if (current != '=') return '<';
327 else { save_and_next(); return LE; }
328
329 case '>':
330 save_and_next();
331 if (current != '=') return '>';
332 else { save_and_next(); return GE; }
333
334 case '~':
335 save_and_next();
336 if (current != '=') return '~';
337 else { save_and_next(); return NE; }
338
339 case '"':
340 case '\'':
341 {
342 int del = current;
343 save_and_next();
344 while (current != del)
345 {
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:
351 case '\n':
352 save(0);
353 return WRONGTOKEN;
354 case '\\':
355 next(); /* do not save the '\' */
356 switch (current)
357 {
358 case 'n': save('\n'); next(); break;
359 case 't': save('\t'); next(); break;
360 case 'r': save('\r'); next(); break;
361 case '\n': save('\n'); inclinenumber(); break;
362 default : save_and_next(); break;
363 }
364 break;
365 default:
366 save_and_next();
367 }
368 }
369 next(); /* skip delimiter */
370 save(0);
371 luaY_lval.pTStr = luaI_createtempstring(yytext+1);
372 tokensize--;
373 save(del); save(0); /* restore delimiter */
374 return STRING;
375 }
376
377 case '.':
378 save_and_next();
379 if (current == '.')
380 {
381 save_and_next();
382 if (current == '.')
383 {
384 save_and_next();
385 return DOTS; /* ... */
386 }
387 else return CONC; /* .. */
388 }
389 else if (!isdigit((unsigned char)current)) return '.';
390 /* current is a digit: goes through to number */
391 a=0.0;
392 goto fraction;
393
394 case '0': case '1': case '2': case '3': case '4':
395 case '5': case '6': case '7': case '8': case '9':
396 a=0.0;
397 do {
398 a=10.0*a+(current-'0');
399 save_and_next();
400 } while (isdigit((unsigned char)current));
401 if (current == '.') {
402 save_and_next();
403 if (current == '.')
404 luaI_syntaxerror(
405 "ambiguous syntax (decimal point x string concatenation)");
406 }
407 fraction:
408 { double da=0.1;
409 while (isdigit((unsigned char)current))
410 {
411 a+=(current-'0')*da;
412 da/=10.0;
413 save_and_next();
414 }
415 if (current == 'e' || current == 'E')
416 {
417 int e=0;
418 int neg;
419 double ea;
420 save_and_next();
421 neg=(current=='-');
422 if (current == '+' || current == '-') save_and_next();
423 if (!isdigit((unsigned char)current)) {
424 save(0); return WRONGTOKEN; }
425 do {
426 e=10.0*e+(current-'0');
427 save_and_next();
428 } while (isdigit((unsigned char)current));
429 for (ea=neg?0.1:10.0; e>0; e>>=1)
430 {
431 if (e & 1) a*=ea;
432 ea*=ea;
433 }
434 }
435 luaY_lval.vReal = a;
436 save(0);
437 return NUMBER;
438 }
439
440 case EOZ:
441 save(0);
442 if (iflevel > 0)
443 luaI_syntaxerror("missing $endif");
444 return 0;
445
446 default:
447 if (current != '_' && !isalpha((unsigned char)current)) {
448 save_and_next();
449 return yytext[0];
450 }
451 else { /* identifier or reserved word */
452 TaggedString *ts;
453 do {
454 save_and_next();
455 } while (isalnum((unsigned char)current) || current == '_');
456 save(0);
457 ts = luaI_createtempstring(yytext);
458 if (ts->marked > 255)
459 return ts->marked; /* reserved word */
460 luaY_lval.pTStr = ts;
461 return NAME;
462 }
463 }
464 }
465}
466