LLlex.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /* L E X I C A L A N A L Y S E R F O R I S O - P A S C A L */
  2. #include "debug.h"
  3. #include "idfsize.h"
  4. #include "numsize.h"
  5. #include "strsize.h"
  6. #include <alloc.h>
  7. #include <em_arith.h>
  8. #include <em_label.h>
  9. #include "LLlex.h"
  10. #include "Lpars.h"
  11. #include "class.h"
  12. #include "const.h"
  13. #include "f_info.h"
  14. #include "idf.h"
  15. #include "input.h"
  16. #include "main.h"
  17. #include "type.h"
  18. extern long str2long();
  19. extern char *Malloc();
  20. #define TO_LOWER(ch) (ch |= ( ch>='A' && ch<='Z' ) ? 0x0020 : 0)
  21. #ifdef DEBUG
  22. extern int cntlines;
  23. #endif
  24. int idfsize = IDFSIZE;
  25. struct token dot,
  26. aside;
  27. struct type *toktype,
  28. *asidetype;
  29. static int eofseen;
  30. STATIC
  31. SkipComment()
  32. {
  33. /* Skip ISO-Pascal comments (* ... *) or { ... }.
  34. Note :
  35. comments may not be nested (ISO 6.1.8).
  36. (* and { are interchangeable, so are *) and }.
  37. */
  38. register int ch;
  39. LoadChar(ch);
  40. for (;;) {
  41. if( class(ch) == STNL ) {
  42. LineNumber++;
  43. #ifdef DEBUG
  44. cntlines++;
  45. #endif
  46. }
  47. else if( ch == '*' ) {
  48. LoadChar(ch);
  49. if( ch == ')' ) return; /* *) */
  50. else continue;
  51. }
  52. else if( ch == '}' ) return;
  53. else if( ch == EOI ) {
  54. lexerror("unterminated comment");
  55. break;
  56. }
  57. LoadChar(ch);
  58. }
  59. }
  60. STATIC struct string *
  61. GetString()
  62. {
  63. /* Read a Pascal string, delimited by the character "'".
  64. */
  65. register int ch;
  66. register struct string *str = (struct string *)
  67. Malloc((unsigned) sizeof(struct string));
  68. register char *p;
  69. register int len = ISTRSIZE;
  70. str->s_str = p = Malloc((unsigned int) ISTRSIZE);
  71. for( ; ; ) {
  72. LoadChar(ch);
  73. if( ch & 0200 )
  74. fatal("non-ascii '\\%03o' read", ch & 0377);
  75. /*NOTREACHED*/
  76. if( class(ch) == STNL ) {
  77. lexerror("newline in string");
  78. LineNumber++;
  79. #ifdef DEBUG
  80. cntlines++;
  81. #endif
  82. break;
  83. }
  84. if( ch == EOI ) {
  85. lexerror("end-of-file in string");
  86. break;
  87. }
  88. if( ch == '\'' ) {
  89. LoadChar(ch);
  90. if( ch != '\'' )
  91. break;
  92. }
  93. *p++ = ch;
  94. if( p - str->s_str == len ) {
  95. extern char *Srealloc();
  96. str->s_str = Srealloc(str->s_str,
  97. (unsigned int) len + RSTRSIZE);
  98. p = str->s_str + len;
  99. len += RSTRSIZE;
  100. }
  101. }
  102. if( ch == EOI ) eofseen = 1;
  103. else PushBack();
  104. str->s_length = p - str->s_str;
  105. *p++ = '\0';
  106. /* ISO 6.1.7: string length at least 1 */
  107. if( str->s_length == 0 ) {
  108. lexerror("character-string: at least one character expected");
  109. str->s_length = 1;
  110. }
  111. return str;
  112. }
  113. int
  114. LLlex()
  115. {
  116. /* LLlex() is the Lexical Analyzer.
  117. The putting aside of tokens is taken into account.
  118. */
  119. register struct token *tk = &dot;
  120. register int ch, nch;
  121. toktype = error_type;
  122. if( ASIDE ) { /* a token is put aside */
  123. *tk = aside;
  124. toktype = asidetype;
  125. ASIDE = 0;
  126. return tk->tk_symb;
  127. }
  128. tk->tk_lineno = LineNumber;
  129. if( eofseen ) {
  130. eofseen = 0;
  131. ch = EOI;
  132. }
  133. else {
  134. again:
  135. LoadChar(ch);
  136. if( !options['C'] ) /* -C : cases are different */
  137. TO_LOWER(ch);
  138. if( (ch & 0200) && ch != EOI )
  139. fatal("non-ascii '\\%03o' read", ch & 0377);
  140. /*NOTREACHED*/
  141. }
  142. switch( class(ch) ) {
  143. case STNL:
  144. LineNumber++;
  145. tk->tk_lineno++;
  146. #ifdef DEBUG
  147. cntlines++;
  148. #endif
  149. goto again;
  150. case STSKIP:
  151. goto again;
  152. case STGARB:
  153. if( (unsigned) ch < 0177 )
  154. lexerror("garbage char %c", ch);
  155. else
  156. crash("(LLlex) garbage char \\%03o", ch);
  157. goto again;
  158. case STSIMP:
  159. if( ch == '(' ) {
  160. LoadChar(nch);
  161. if( nch == '*' ) { /* (* */
  162. SkipComment();
  163. tk->tk_lineno = LineNumber;
  164. goto again;
  165. }
  166. if( nch == '.' ) /* (. is [ */
  167. return tk->tk_symb = '[';
  168. if( nch == EOI ) eofseen = 1;
  169. else PushBack();
  170. }
  171. else if( ch == '{' ) {
  172. SkipComment();
  173. tk->tk_lineno = LineNumber;
  174. goto again;
  175. }
  176. else if( ch == '@' ) ch = '^'; /* @ is ^ */
  177. return tk->tk_symb = ch;
  178. case STCOMP:
  179. LoadChar(nch);
  180. switch( ch ) {
  181. case '.':
  182. if( nch == '.' ) /* .. */
  183. return tk->tk_symb = UPTO;
  184. if( nch == ')' ) /* .) is ] */
  185. return tk->tk_symb = ']';
  186. break;
  187. case ':':
  188. if( nch == '=' ) /* := */
  189. return tk->tk_symb = BECOMES;
  190. break;
  191. case '<':
  192. if( nch == '=' ) /* <= */
  193. return tk->tk_symb = LESSEQUAL;
  194. if( nch == '>' ) /* <> */
  195. return tk->tk_symb = NOTEQUAL;
  196. break;
  197. case '>':
  198. if( nch == '=' ) /* >= */
  199. return tk->tk_symb = GREATEREQUAL;
  200. break;
  201. default :
  202. crash("(LLlex, STCOMP)");
  203. /*NOTREACHED*/
  204. }
  205. if( nch == EOI ) eofseen = 1;
  206. else PushBack();
  207. return tk->tk_symb = ch;
  208. case STIDF: {
  209. char buf[IDFSIZE + 1];
  210. register char *tag = &buf[0];
  211. register struct idf *id;
  212. extern struct idf *str2idf();
  213. do {
  214. if( !options['C'] ) /* -C : cases are different */
  215. TO_LOWER(ch);
  216. if( tag - buf < idfsize )
  217. *tag++ = ch;
  218. LoadChar(ch);
  219. } while( in_idf(ch) );
  220. *tag = '\0';
  221. if( ch == EOI ) eofseen = 1;
  222. else PushBack();
  223. tk->TOK_IDF = id = str2idf(buf, 1);
  224. return tk->tk_symb = id->id_reserved ? id->id_reserved : IDENT;
  225. }
  226. case STSTR: {
  227. register struct string *str = GetString();
  228. if( str->s_length == 1 ) {
  229. #ifdef DEBUG
  230. if( options['l'] ) {
  231. /* to prevent LexScan from crashing */
  232. tk->tk_data.tk_str = str;
  233. return tk->tk_symb = STRING;
  234. }
  235. #endif
  236. tk->TOK_INT = *(str->s_str) & 0377;
  237. toktype = char_type;
  238. free(str->s_str);
  239. free((char *) str);
  240. }
  241. else {
  242. tk->tk_data.tk_str = str;
  243. toktype = standard_type(T_STRING, 1, str->s_length);
  244. }
  245. return tk->tk_symb = STRING;
  246. }
  247. case STNUM: {
  248. #define INT_MODE 0
  249. #define REAL_MODE 1
  250. char buf[NUMSIZE+2];
  251. register char *np = buf;
  252. register int state = INT_MODE;
  253. extern char *Salloc();
  254. do {
  255. if( np <= &buf[NUMSIZE] )
  256. *np++ = ch;
  257. LoadChar(ch);
  258. } while( is_dig(ch) );
  259. if( ch == '.' ) {
  260. LoadChar(ch);
  261. if( is_dig(ch) ) {
  262. if( np <= &buf[NUMSIZE] )
  263. *np++ = '.';
  264. do {
  265. /* fractional part */
  266. if( np <= &buf[NUMSIZE] )
  267. *np++ = ch;
  268. LoadChar(ch);
  269. } while( is_dig(ch) );
  270. state = REAL_MODE;
  271. }
  272. else {
  273. PushBack();
  274. PushBack();
  275. goto end;
  276. }
  277. }
  278. if( ch == 'e' || ch == 'E' ) {
  279. char *tp = np; /* save position in string */
  280. /* scale factor */
  281. if( np <= &buf[NUMSIZE] )
  282. *np++ = ch;
  283. LoadChar(ch);
  284. if( ch == '+' || ch == '-' ) {
  285. /* signed scale factor */
  286. if( np <= &buf[NUMSIZE] )
  287. *np++ = ch;
  288. LoadChar(ch);
  289. }
  290. if( is_dig(ch) ) {
  291. do {
  292. if( np <= &buf[NUMSIZE] )
  293. *np++ = ch;
  294. LoadChar(ch);
  295. } while( is_dig(ch) );
  296. state = REAL_MODE;
  297. }
  298. else {
  299. PushBack();
  300. PushBack();
  301. if( np - tp == 2 ) /* sign */
  302. PushBack();
  303. np = tp; /* restore position */
  304. goto end;
  305. }
  306. }
  307. /* syntax of number is correct */
  308. if( ch == EOI ) eofseen = 1;
  309. else PushBack();
  310. end:
  311. *np++ = '\0';
  312. if( state == INT_MODE ) {
  313. if( np > &buf[NUMSIZE+1] ) {
  314. tk->TOK_INT = 1;
  315. lexerror("constant too long");
  316. }
  317. else {
  318. np = buf;
  319. while (*np == '0') /* skip leading zeros */
  320. np++;
  321. tk->TOK_INT = str2long(np, 10);
  322. if( tk->TOK_INT < 0 ||
  323. strlen(np) > strlen(maxint_str) ||
  324. strlen(np) == strlen(maxint_str) &&
  325. strcmp(np, maxint_str) > 0 )
  326. lexwarning("overflow in constant");
  327. }
  328. toktype = int_type;
  329. return tk->tk_symb = INTEGER;
  330. }
  331. /* REAL_MODE */
  332. tk->tk_data.tk_real = (struct real *)
  333. Malloc(sizeof(struct real));
  334. /* allocate struct for inverse */
  335. tk->TOK_RIV = (struct real *) Malloc(sizeof(struct real));
  336. tk->TOK_RIV->r_inverse = tk->tk_data.tk_real;
  337. /* sign */
  338. tk->TOK_RSI = 0;
  339. tk->TOK_RIV->r_sign = 1;
  340. if( np > &buf[NUMSIZE+1] ) {
  341. tk->TOK_REL = Salloc("0.0", 4);
  342. lexerror("floating constant too long");
  343. }
  344. else tk->TOK_REL = Salloc(buf, np - buf);
  345. toktype = real_type;
  346. return tk->tk_symb = REAL;
  347. /*NOTREACHED*/
  348. }
  349. case STEOI:
  350. return tk->tk_symb = -1;
  351. case STCHAR:
  352. default:
  353. crash("(LLlex) Impossible character class");
  354. /*NOTREACHED*/
  355. }
  356. /*NOTREACHED*/
  357. }