lex.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. char *rcs_lex = "$Id: lex.c,v 3.2 1997/04/14 15:30:29 roberto Exp roberto $";
  2. #include <ctype.h>
  3. #include <string.h>
  4. #include "auxlib.h"
  5. #include "luamem.h"
  6. #include "tree.h"
  7. #include "table.h"
  8. #include "lex.h"
  9. #include "inout.h"
  10. #include "luadebug.h"
  11. #include "parser.h"
  12. #define MINBUFF 250
  13. #define next() (current = input())
  14. #define save(x) (yytext[tokensize++] = (x))
  15. #define save_and_next() (save(current), next())
  16. static int current; /* look ahead character */
  17. static Input input; /* input function */
  18. #define MAX_IFS 10
  19. /* "ifstate" keeps the state of each nested $if the lexical is
  20. ** dealing with. The first bit indicates whether the $if condition
  21. ** is false or true. The second bit indicates whether the lexical is
  22. ** inside the "then" part (0) or the "else" part (2)
  23. */
  24. static int ifstate[MAX_IFS]; /* 0 => then part - condition false */
  25. /* 1 => then part - condition true */
  26. /* 2 => else part - condition false */
  27. /* 3 => else part - condition true */
  28. static int iflevel; /* level of nested $if's */
  29. void lua_setinput (Input fn)
  30. {
  31. current = '\n';
  32. lua_linenumber = 0;
  33. iflevel = 0;
  34. input = fn;
  35. }
  36. static void luaI_auxsyntaxerror (char *s)
  37. {
  38. luaL_verror("%s;\n> at line %d in file %s",
  39. s, lua_linenumber, lua_parsedfile);
  40. }
  41. static void luaI_auxsynterrbf (char *s, char *token)
  42. {
  43. if (token[0] == 0)
  44. token = "<eof>";
  45. luaL_verror("%s;\n> last token read: \"%s\" at line %d in file %s",
  46. s, token, lua_linenumber, lua_parsedfile);
  47. }
  48. void luaI_syntaxerror (char *s)
  49. {
  50. luaI_auxsynterrbf(s, luaI_buffer(1));
  51. }
  52. static struct
  53. {
  54. char *name;
  55. int token;
  56. } reserved [] = {
  57. {"and", AND},
  58. {"do", DO},
  59. {"else", ELSE},
  60. {"elseif", ELSEIF},
  61. {"end", END},
  62. {"function", FUNCTION},
  63. {"if", IF},
  64. {"local", LOCAL},
  65. {"nil", NIL},
  66. {"not", NOT},
  67. {"or", OR},
  68. {"repeat", REPEAT},
  69. {"return", RETURN},
  70. {"then", THEN},
  71. {"until", UNTIL},
  72. {"while", WHILE} };
  73. #define RESERVEDSIZE (sizeof(reserved)/sizeof(reserved[0]))
  74. void luaI_addReserved (void)
  75. {
  76. int i;
  77. for (i=0; i<RESERVEDSIZE; i++)
  78. {
  79. TaggedString *ts = lua_createstring(reserved[i].name);
  80. ts->marked = reserved[i].token; /* reserved word (always > 255) */
  81. }
  82. }
  83. /*
  84. ** Pragma handling
  85. */
  86. #define PRAGMASIZE 20
  87. static void skipspace (void)
  88. {
  89. while (current == ' ' || current == '\t') next();
  90. }
  91. static int checkcond (char *buff)
  92. {
  93. if (strcmp(buff, "nil") == 0)
  94. return 0;
  95. else if (strcmp(buff, "1") == 0)
  96. return 1;
  97. else if (isalpha((unsigned char)buff[0]) || buff[0] == '_')
  98. return luaI_globaldefined(buff);
  99. else {
  100. luaI_auxsynterrbf("invalid $if condition", buff);
  101. return 0; /* to avoid warnings */
  102. }
  103. }
  104. static void readname (char *buff)
  105. {
  106. int i = 0;
  107. skipspace();
  108. while (isalnum((unsigned char)current) || current == '_') {
  109. if (i >= PRAGMASIZE) {
  110. buff[PRAGMASIZE] = 0;
  111. luaI_auxsynterrbf("pragma too long", buff);
  112. }
  113. buff[i++] = current;
  114. next();
  115. }
  116. buff[i] = 0;
  117. }
  118. static void inclinenumber (void);
  119. static void ifskip (int thisiflevel)
  120. {
  121. if (thisiflevel < 0) return;
  122. while (iflevel > thisiflevel &&
  123. (ifstate[thisiflevel] == 0 || ifstate[thisiflevel] == 3)) {
  124. if (current == '\n')
  125. inclinenumber();
  126. else if (current == 0)
  127. luaI_auxsyntaxerror("input ends inside a $if");
  128. else next();
  129. }
  130. }
  131. static void inclinenumber (void)
  132. {
  133. static char *pragmas [] =
  134. {"debug", "nodebug", "end", "ifnot", "if", "else", "endinput", NULL};
  135. next(); /* skip '\n' */
  136. ++lua_linenumber;
  137. if (current == '$') { /* is a pragma? */
  138. char buff[PRAGMASIZE+1];
  139. int ifnot = 0;
  140. next(); /* skip $ */
  141. readname(buff);
  142. switch (luaI_findstring(buff, pragmas)) {
  143. case 0: /* debug */
  144. lua_debug = 1;
  145. break;
  146. case 1: /* nodebug */
  147. lua_debug = 0;
  148. break;
  149. case 2: /* end */
  150. if (--iflevel < 0)
  151. luaI_auxsyntaxerror("unmatched $endif");
  152. break;
  153. case 3: /* ifnot */
  154. ifnot = 1;
  155. /* go through */
  156. case 4: /* if */
  157. if (iflevel == MAX_IFS)
  158. luaI_auxsyntaxerror("too many nested `$ifs'");
  159. readname(buff);
  160. ifstate[iflevel++] = checkcond(buff) ? !ifnot : ifnot;
  161. break;
  162. case 5: /* else */
  163. if (iflevel <= 0 || (ifstate[iflevel-1] & 2))
  164. luaI_auxsyntaxerror("unmatched $else");
  165. ifstate[iflevel-1] = ifstate[iflevel-1] | 2;
  166. break;
  167. case 6: /* endinput */
  168. current = 0;
  169. break;
  170. default:
  171. luaI_auxsynterrbf("invalid pragma", buff);
  172. }
  173. skipspace();
  174. if (current == '\n') /* pragma must end with a '\n' */
  175. inclinenumber();
  176. else if (current != 0) /* or eof */
  177. luaI_auxsyntaxerror("invalid pragma format");
  178. ifskip(iflevel-1);
  179. }
  180. }
  181. static int read_long_string (char *yytext, int buffsize)
  182. {
  183. int cont = 0;
  184. int tokensize = 2; /* '[[' already stored */
  185. while (1)
  186. {
  187. if (buffsize-tokensize <= 2) /* may read more than 1 char in one cicle */
  188. yytext = luaI_buffer(buffsize *= 2);
  189. switch (current)
  190. {
  191. case 0:
  192. save(0);
  193. return WRONGTOKEN;
  194. case '[':
  195. save_and_next();
  196. if (current == '[')
  197. {
  198. cont++;
  199. save_and_next();
  200. }
  201. continue;
  202. case ']':
  203. save_and_next();
  204. if (current == ']')
  205. {
  206. if (cont == 0) goto endloop;
  207. cont--;
  208. save_and_next();
  209. }
  210. continue;
  211. case '\n':
  212. save('\n');
  213. inclinenumber();
  214. continue;
  215. default:
  216. save_and_next();
  217. }
  218. } endloop:
  219. save_and_next(); /* pass the second ']' */
  220. yytext[tokensize-2] = 0; /* erases ']]' */
  221. luaY_lval.vWord = luaI_findconstantbyname(yytext+2);
  222. yytext[tokensize-2] = ']'; /* restores ']]' */
  223. save(0);
  224. return STRING;
  225. }
  226. int luaY_lex (void)
  227. {
  228. static int linelasttoken = 0;
  229. double a;
  230. int buffsize = MINBUFF;
  231. char *yytext = luaI_buffer(buffsize);
  232. yytext[1] = yytext[2] = yytext[3] = 0;
  233. if (lua_debug)
  234. luaI_codedebugline(linelasttoken);
  235. linelasttoken = lua_linenumber;
  236. while (1)
  237. {
  238. int tokensize = 0;
  239. switch (current)
  240. {
  241. case '\n':
  242. inclinenumber();
  243. linelasttoken = lua_linenumber;
  244. continue;
  245. case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */
  246. next();
  247. continue;
  248. case '-':
  249. save_and_next();
  250. if (current != '-') return '-';
  251. do { next(); } while (current != '\n' && current != 0);
  252. continue;
  253. case '[':
  254. save_and_next();
  255. if (current != '[') return '[';
  256. else
  257. {
  258. save_and_next(); /* pass the second '[' */
  259. return read_long_string(yytext, buffsize);
  260. }
  261. case '=':
  262. save_and_next();
  263. if (current != '=') return '=';
  264. else { save_and_next(); return EQ; }
  265. case '<':
  266. save_and_next();
  267. if (current != '=') return '<';
  268. else { save_and_next(); return LE; }
  269. case '>':
  270. save_and_next();
  271. if (current != '=') return '>';
  272. else { save_and_next(); return GE; }
  273. case '~':
  274. save_and_next();
  275. if (current != '=') return '~';
  276. else { save_and_next(); return NE; }
  277. case '"':
  278. case '\'':
  279. {
  280. int del = current;
  281. save_and_next();
  282. while (current != del)
  283. {
  284. if (buffsize-tokensize <= 2) /* may read more than 1 char in one cicle */
  285. yytext = luaI_buffer(buffsize *= 2);
  286. switch (current)
  287. {
  288. case 0:
  289. case '\n':
  290. save(0);
  291. return WRONGTOKEN;
  292. case '\\':
  293. next(); /* do not save the '\' */
  294. switch (current)
  295. {
  296. case 'n': save('\n'); next(); break;
  297. case 't': save('\t'); next(); break;
  298. case 'r': save('\r'); next(); break;
  299. case '\n': save('\n'); inclinenumber(); break;
  300. default : save_and_next(); break;
  301. }
  302. break;
  303. default:
  304. save_and_next();
  305. }
  306. }
  307. next(); /* skip delimiter */
  308. save(0);
  309. luaY_lval.vWord = luaI_findconstantbyname(yytext+1);
  310. tokensize--;
  311. save(del); save(0); /* restore delimiter */
  312. return STRING;
  313. }
  314. case 'a': case 'b': case 'c': case 'd': case 'e':
  315. case 'f': case 'g': case 'h': case 'i': case 'j':
  316. case 'k': case 'l': case 'm': case 'n': case 'o':
  317. case 'p': case 'q': case 'r': case 's': case 't':
  318. case 'u': case 'v': case 'w': case 'x': case 'y':
  319. case 'z':
  320. case 'A': case 'B': case 'C': case 'D': case 'E':
  321. case 'F': case 'G': case 'H': case 'I': case 'J':
  322. case 'K': case 'L': case 'M': case 'N': case 'O':
  323. case 'P': case 'Q': case 'R': case 'S': case 'T':
  324. case 'U': case 'V': case 'W': case 'X': case 'Y':
  325. case 'Z':
  326. case '_':
  327. {
  328. TaggedString *ts;
  329. do {
  330. save_and_next();
  331. } while (isalnum((unsigned char)current) || current == '_');
  332. save(0);
  333. ts = lua_createstring(yytext);
  334. if (ts->marked > 2)
  335. return ts->marked; /* reserved word */
  336. luaY_lval.pTStr = ts;
  337. ts->marked = 2; /* avoid GC */
  338. return NAME;
  339. }
  340. case '.':
  341. save_and_next();
  342. if (current == '.')
  343. {
  344. save_and_next();
  345. if (current == '.')
  346. {
  347. save_and_next();
  348. return DOTS; /* ... */
  349. }
  350. else return CONC; /* .. */
  351. }
  352. else if (!isdigit((unsigned char)current)) return '.';
  353. /* current is a digit: goes through to number */
  354. a=0.0;
  355. goto fraction;
  356. case '0': case '1': case '2': case '3': case '4':
  357. case '5': case '6': case '7': case '8': case '9':
  358. a=0.0;
  359. do {
  360. a=10.0*a+(current-'0');
  361. save_and_next();
  362. } while (isdigit((unsigned char)current));
  363. if (current == '.') {
  364. save_and_next();
  365. if (current == '.')
  366. luaI_syntaxerror(
  367. "ambiguous syntax (decimal point x string concatenation)");
  368. }
  369. fraction:
  370. { double da=0.1;
  371. while (isdigit((unsigned char)current))
  372. {
  373. a+=(current-'0')*da;
  374. da/=10.0;
  375. save_and_next();
  376. }
  377. if (current == 'e' || current == 'E')
  378. {
  379. int e=0;
  380. int neg;
  381. double ea;
  382. save_and_next();
  383. neg=(current=='-');
  384. if (current == '+' || current == '-') save_and_next();
  385. if (!isdigit((unsigned char)current)) {
  386. save(0); return WRONGTOKEN; }
  387. do {
  388. e=10.0*e+(current-'0');
  389. save_and_next();
  390. } while (isdigit((unsigned char)current));
  391. for (ea=neg?0.1:10.0; e>0; e>>=1)
  392. {
  393. if (e & 1) a*=ea;
  394. ea*=ea;
  395. }
  396. }
  397. luaY_lval.vFloat = a;
  398. save(0);
  399. return NUMBER;
  400. }
  401. case 0:
  402. save(0);
  403. if (iflevel > 0)
  404. luaI_syntaxerror("missing $endif");
  405. return 0;
  406. default:
  407. save_and_next();
  408. return yytext[0];
  409. }
  410. }
  411. }