2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
5 * Author: Ceriel J.H. Jacobs
8 /* L E X I C A L A N A L Y S E R F O R M O D U L A - 2 */
10 /* $Id: LLlex.c,v 1.7 1994/06/24 12:44:30 ceriel Exp $ */
23 int idfsize = IDFSIZE;
26 extern char *getwdir();
31 /* Skip Modula-2 comments (* ... *).
32 Note that comments may be nested (par. 3.5).
35 register int CommentLevel = 0;
42 /* Foreign; This definition module has an
43 implementation in another language.
44 In this case, check that the object file is present
45 and don't generate a rule for it.
55 if (class(ch) == STNL) {
60 if (ch == '*') CommentLevel++;
67 if (CommentLevel < 0) break;
72 lexerror("unterminated comment");
82 /* Read a Modula-2 string, delimited by the character "upto".
86 while (LoadChar(ch), ch != upto) {
87 if (class(ch) == STNL) {
88 lexerror("newline in string");
93 lexerror("end-of-file in string");
99 static char *s_error = "illegal line directive";
108 if ((ch & 0200) && ch != EOI) {
109 error("non-ascii '\\%03o' read", ch & 0377);
117 CheckForLineDirective()
119 register int ch = getch();
121 char buf[IDFSIZE + 2];
122 register char *c = buf;
131 * Do not skip newlines
134 if (class(ch) == STNL || class(ch) == STEOI) {
139 } while (class(ch) != STNUM);
140 while (class(ch) == STNUM) {
141 i = i*10 + (ch - '0');
144 while (ch != '"' && class(ch) != STNL && class(ch) != STEOI)
150 if (class(ch) == STNL || class(ch) == STEOI) {
159 } while (class(ch) != STNL && class(ch) != STEOI);
161 * Remember the file name
163 if (class(ch) == STNL && strcmp(FileName,buf)) {
164 FileName = Salloc(buf,(unsigned) strlen(buf) + 1);
165 WorkingDir = getwdir(FileName);
168 if (class(ch) == STEOI) {
175 char idfbuf[IDFSIZE + 2];
180 /* LLlex() is the Lexical Analyzer.
181 The putting aside of tokens is taken into account.
183 register struct token *tk = ˙
184 register int ch, nch;
186 if (ASIDE) { /* a token is put aside */
194 tk->tk_lineno = LineNumber;
200 CheckForLineDirective();
207 if ((unsigned) ch - 040 < 0137) {
208 lexerror("garbage char %c", ch);
210 else lexerror("garbage char \\%03o", ch);
222 if (ch == '&') return tk->tk_symb = AND;
223 if (ch == '~') return tk->tk_symb = NOT;
224 return tk->tk_symb = ch;
232 return tk->tk_symb = UPTO;
238 return tk->tk_symb = BECOMES;
244 return tk->tk_symb = LESSEQUAL;
247 return tk->tk_symb = '#';
253 return tk->tk_symb = GREATEREQUAL;
258 crash("(LLlex, STCOMP)");
261 return tk->tk_symb = ch;
265 register char *tag = &idfbuf[0];
266 register struct idf *id;
269 if (tag - idfbuf < idfsize) *tag++ = ch;
276 tk->TOK_IDF = id = findidf(idfbuf);
277 return tk->tk_symb = id && id->id_reserved ? id->id_reserved : IDENT;
282 return tk->tk_symb = STRING;
286 /* The problem arising with the "parsing" of a number
287 is that we don't know the base in advance so we
288 have to read the number with the help of a rather
289 complex finite automaton.
291 enum statetp {Oct,OptHex,Hex,Dec,OctEndOrHex,End,OptReal,Real};
292 register enum statetp state;
293 state = is_oct(ch) ? Oct : Dec;
301 if (ch == 'B' || ch == 'C') {
310 if (ch == 'D') state = OptHex;
311 else if (is_hex(ch)) state = Hex;
312 else if (ch == '.') state = OptReal;
315 if (ch != 'H') PushBack();
337 lexerror("H expected after hex number");
356 return tk->tk_symb = INTEGER;
359 /* The '.' could be the first of the '..'
360 token. At this point, we need a
361 look-ahead of two characters.
365 /* Indeed the '..' token
375 if (state == Real) break;
384 if (ch == 'E' || ch == 'D') {
389 if (!(ch == '+' || ch == '-' || is_dig(ch)))
393 if (ch == '+' || ch == '-') {
394 /* Signed scalefactor
401 } while (is_dig(ch));
404 lexerror("bad scale factor");
411 return tk->tk_symb = REAL;
417 return tk->tk_symb = -1;
421 crash("(LLlex) Impossible character class");