llex.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. ** $Id: llex.c,v 1.1 1997/09/16 19:25:59 roberto Exp roberto $
  3. ** Lexical Analizer
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <ctype.h>
  7. #include <string.h>
  8. #include "llex.h"
  9. #include "lmem.h"
  10. #include "lobject.h"
  11. #include "lparser.h"
  12. #include "lstring.h"
  13. #include "ltokens.h"
  14. #include "luadebug.h"
  15. #include "lzio.h"
  16. static int current; /* look ahead character */
  17. static ZIO *lex_z;
  18. int luaX_linenumber;
  19. int lua_debug=0;
  20. #define next() (current = zgetc(lex_z))
  21. static void addReserved (void)
  22. {
  23. static struct {
  24. char *name;
  25. int token;
  26. } reserved [] = {
  27. {"and", AND}, {"do", DO}, {"else", ELSE}, {"elseif", ELSEIF},
  28. {"end", END}, {"function", FUNCTION}, {"if", IF}, {"local", LOCAL},
  29. {"nil", NIL}, {"not", NOT}, {"or", OR}, {"repeat", REPEAT},
  30. {"return", RETURN}, {"then", THEN}, {"until", UNTIL}, {"while", WHILE}
  31. };
  32. static int firsttime = 1;
  33. if (firsttime) {
  34. int i;
  35. firsttime = 0;
  36. for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) {
  37. TaggedString *ts = luaS_new(reserved[i].name);
  38. ts->head.marked = reserved[i].token; /* reserved word (always > 255) */
  39. }
  40. }
  41. }
  42. #define MAX_IFS 5
  43. /* "ifstate" keeps the state of each nested $if the lexical is dealing with. */
  44. static struct {
  45. int elsepart; /* true if its in the $else part */
  46. int condition; /* true if $if condition is true */
  47. int skip; /* true if part must be skiped */
  48. } ifstate[MAX_IFS];
  49. static int iflevel; /* level of nested $if's */
  50. static struct textbuff {
  51. char *text;
  52. int tokensize;
  53. int buffsize;
  54. } textbuff;
  55. static void firstline (void)
  56. {
  57. int c = zgetc(lex_z);
  58. if (c == '#')
  59. while((c=zgetc(lex_z)) != '\n' && c != EOZ) /* skip first line */;
  60. zungetc(lex_z);
  61. }
  62. void luaX_setinput (ZIO *z)
  63. {
  64. addReserved();
  65. current = '\n';
  66. luaX_linenumber = 0;
  67. iflevel = 0;
  68. ifstate[0].skip = 0;
  69. ifstate[0].elsepart = 1; /* to avoid a free $else */
  70. lex_z = z;
  71. firstline();
  72. textbuff.buffsize = 20;
  73. textbuff.text = luaM_buffer(textbuff.buffsize);
  74. }
  75. /*
  76. ** =======================================================
  77. ** PRAGMAS
  78. ** =======================================================
  79. */
  80. #define PRAGMASIZE 20
  81. static void skipspace (void)
  82. {
  83. while (current == ' ' || current == '\t') next();
  84. }
  85. static int checkcond (char *buff)
  86. {
  87. static char *opts[] = {"nil", "1"};
  88. int i = luaO_findstring(buff, opts);
  89. if (i >= 0) return i;
  90. else if (isalpha((unsigned char)buff[0]) || buff[0] == '_')
  91. return luaS_globaldefined(buff);
  92. else {
  93. luaY_syntaxerror("invalid $if condition", buff);
  94. return 0; /* to avoid warnings */
  95. }
  96. }
  97. static void readname (char *buff)
  98. {
  99. int i = 0;
  100. skipspace();
  101. while (isalnum(current) || current == '_') {
  102. if (i >= PRAGMASIZE) {
  103. buff[PRAGMASIZE] = 0;
  104. luaY_syntaxerror("pragma too long", buff);
  105. }
  106. buff[i++] = current;
  107. next();
  108. }
  109. buff[i] = 0;
  110. }
  111. static void inclinenumber (void);
  112. static void ifskip (void)
  113. {
  114. while (ifstate[iflevel].skip) {
  115. if (current == '\n')
  116. inclinenumber();
  117. else if (current == EOZ)
  118. luaY_syntaxerror("input ends inside a $if", "");
  119. else next();
  120. }
  121. }
  122. static void inclinenumber (void)
  123. {
  124. static char *pragmas [] =
  125. {"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL};
  126. next(); /* skip '\n' */
  127. ++luaX_linenumber;
  128. if (current == '$') { /* is a pragma? */
  129. char buff[PRAGMASIZE+1];
  130. int ifnot = 0;
  131. int skip = ifstate[iflevel].skip;
  132. next(); /* skip $ */
  133. readname(buff);
  134. switch (luaO_findstring(buff, pragmas)) {
  135. case 0: /* debug */
  136. if (!skip) lua_debug = 1;
  137. break;
  138. case 1: /* nodebug */
  139. if (!skip) lua_debug = 0;
  140. break;
  141. case 2: /* endinput */
  142. if (!skip) {
  143. current = EOZ;
  144. iflevel = 0; /* to allow $endinput inside a $if */
  145. }
  146. break;
  147. case 3: /* end */
  148. if (iflevel-- == 0)
  149. luaY_syntaxerror("unmatched $end", "$end");
  150. break;
  151. case 4: /* ifnot */
  152. ifnot = 1;
  153. /* go through */
  154. case 5: /* if */
  155. if (iflevel == MAX_IFS-1)
  156. luaY_syntaxerror("too many nested `$ifs'", "$if");
  157. readname(buff);
  158. iflevel++;
  159. ifstate[iflevel].elsepart = 0;
  160. ifstate[iflevel].condition = checkcond(buff) ? !ifnot : ifnot;
  161. ifstate[iflevel].skip = skip || !ifstate[iflevel].condition;
  162. break;
  163. case 6: /* else */
  164. if (ifstate[iflevel].elsepart)
  165. luaY_syntaxerror("unmatched $else", "$else");
  166. ifstate[iflevel].elsepart = 1;
  167. ifstate[iflevel].skip =
  168. ifstate[iflevel-1].skip || ifstate[iflevel].condition;
  169. break;
  170. default:
  171. luaY_syntaxerror("invalid pragma", buff);
  172. }
  173. skipspace();
  174. if (current == '\n') /* pragma must end with a '\n' ... */
  175. inclinenumber();
  176. else if (current != EOZ) /* or eof */
  177. luaY_syntaxerror("invalid pragma format", buff);
  178. ifskip();
  179. }
  180. }
  181. /*
  182. ** =======================================================
  183. ** LEXICAL ANALIZER
  184. ** =======================================================
  185. */
  186. static void save (int c)
  187. {
  188. if (textbuff.tokensize >= textbuff.buffsize)
  189. textbuff.text = luaM_buffer(textbuff.buffsize *= 2);
  190. textbuff.text[textbuff.tokensize++] = c;
  191. }
  192. char *luaX_lasttoken (void)
  193. {
  194. save(0);
  195. return textbuff.text;
  196. }
  197. #define save_and_next() (save(current), next())
  198. static int read_long_string (void)
  199. {
  200. int cont = 0;
  201. while (1) {
  202. switch (current) {
  203. case EOZ:
  204. save(0);
  205. return WRONGTOKEN;
  206. case '[':
  207. save_and_next();
  208. if (current == '[') {
  209. cont++;
  210. save_and_next();
  211. }
  212. continue;
  213. case ']':
  214. save_and_next();
  215. if (current == ']') {
  216. if (cont == 0) goto endloop;
  217. cont--;
  218. save_and_next();
  219. }
  220. continue;
  221. case '\n':
  222. save('\n');
  223. inclinenumber();
  224. continue;
  225. default:
  226. save_and_next();
  227. }
  228. } endloop:
  229. save_and_next(); /* pass the second ']' */
  230. textbuff.text[textbuff.tokensize-2] = 0; /* erases ']]' */
  231. luaY_lval.pTStr = luaS_new(textbuff.text+2);
  232. textbuff.text[textbuff.tokensize-2] = ']'; /* restores ']]' */
  233. return STRING;
  234. }
  235. int luaY_lex (void)
  236. {
  237. static int linelasttoken = 0;
  238. double a;
  239. textbuff.tokensize = 0;
  240. if (lua_debug)
  241. luaY_codedebugline(linelasttoken);
  242. linelasttoken = luaX_linenumber;
  243. while (1) {
  244. switch (current) {
  245. case '\n':
  246. inclinenumber();
  247. linelasttoken = luaX_linenumber;
  248. continue;
  249. case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */
  250. next();
  251. continue;
  252. case '-':
  253. save_and_next();
  254. if (current != '-') return '-';
  255. do { next(); } while (current != '\n' && current != EOZ);
  256. textbuff.tokensize = 0;
  257. continue;
  258. case '[':
  259. save_and_next();
  260. if (current != '[') return '[';
  261. else {
  262. save_and_next(); /* pass the second '[' */
  263. return read_long_string();
  264. }
  265. case '=':
  266. save_and_next();
  267. if (current != '=') return '=';
  268. else { save_and_next(); return EQ; }
  269. case '<':
  270. save_and_next();
  271. if (current != '=') return '<';
  272. else { save_and_next(); return LE; }
  273. case '>':
  274. save_and_next();
  275. if (current != '=') return '>';
  276. else { save_and_next(); return GE; }
  277. case '~':
  278. save_and_next();
  279. if (current != '=') return '~';
  280. else { save_and_next(); return NE; }
  281. case '"':
  282. case '\'': {
  283. int del = current;
  284. save_and_next();
  285. while (current != del) {
  286. switch (current) {
  287. case EOZ:
  288. case '\n':
  289. save(0);
  290. return WRONGTOKEN;
  291. case '\\':
  292. next(); /* do not save the '\' */
  293. switch (current) {
  294. case 'n': save('\n'); next(); break;
  295. case 't': save('\t'); next(); break;
  296. case 'r': save('\r'); next(); break;
  297. case '\n': save('\n'); inclinenumber(); break;
  298. default : save_and_next(); break;
  299. }
  300. break;
  301. default:
  302. save_and_next();
  303. }
  304. }
  305. next(); /* skip delimiter */
  306. save(0);
  307. luaY_lval.pTStr = luaS_new(textbuff.text+1);
  308. textbuff.text[textbuff.tokensize-1] = del; /* restore delimiter */
  309. return STRING;
  310. }
  311. case '.':
  312. save_and_next();
  313. if (current == '.')
  314. {
  315. save_and_next();
  316. if (current == '.')
  317. {
  318. save_and_next();
  319. return DOTS; /* ... */
  320. }
  321. else return CONC; /* .. */
  322. }
  323. else if (!isdigit(current)) return '.';
  324. /* current is a digit: goes through to number */
  325. a=0.0;
  326. goto fraction;
  327. case '0': case '1': case '2': case '3': case '4':
  328. case '5': case '6': case '7': case '8': case '9':
  329. a=0.0;
  330. do {
  331. a=10.0*a+(current-'0');
  332. save_and_next();
  333. } while (isdigit(current));
  334. if (current == '.') {
  335. save_and_next();
  336. if (current == '.') {
  337. save(0);
  338. luaY_error(
  339. "ambiguous syntax (decimal point x string concatenation)");
  340. }
  341. }
  342. fraction:
  343. { double da=0.1;
  344. while (isdigit(current))
  345. {
  346. a+=(current-'0')*da;
  347. da/=10.0;
  348. save_and_next();
  349. }
  350. if (toupper(current) == 'E') {
  351. int e=0;
  352. int neg;
  353. double ea;
  354. save_and_next();
  355. neg=(current=='-');
  356. if (current == '+' || current == '-') save_and_next();
  357. if (!isdigit(current)) {
  358. save(0); return WRONGTOKEN; }
  359. do {
  360. e=10.0*e+(current-'0');
  361. save_and_next();
  362. } while (isdigit(current));
  363. for (ea=neg?0.1:10.0; e>0; e>>=1)
  364. {
  365. if (e & 1) a*=ea;
  366. ea*=ea;
  367. }
  368. }
  369. luaY_lval.vReal = a;
  370. return NUMBER;
  371. }
  372. case EOZ:
  373. save(0);
  374. if (iflevel > 0)
  375. luaY_error("missing $endif");
  376. return 0;
  377. default:
  378. if (current != '_' && !isalpha(current)) {
  379. save_and_next();
  380. return textbuff.text[0];
  381. }
  382. else { /* identifier or reserved word */
  383. TaggedString *ts;
  384. do {
  385. save_and_next();
  386. } while (isalnum(current) || current == '_');
  387. save(0);
  388. ts = luaS_new(textbuff.text);
  389. if (ts->head.marked > 255)
  390. return ts->head.marked; /* reserved word */
  391. luaY_lval.pTStr = ts;
  392. return NAME;
  393. }
  394. }
  395. }
  396. }