xref: /original-bsd/usr.bin/pascal/src/yylex.c (revision 1897046e)
1 /*-
2  * Copyright (c) 1980 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)yylex.c	5.2 (Berkeley) 04/16/91";
10 #endif /* not lint */
11 
12 #include "whoami.h"
13 #include "0.h"
14 #include "tree_ty.h"	/* must be included for yy.h */
15 #include "yy.h"
16 
17 /*
18  * Scanner
19  */
20 int	yylacnt;
21 
22 #define	YYLASIZ	10
23 
24 struct	yytok Yla[YYLASIZ];
25 
26 unyylex(y)
27 	struct yytok *y;
28 {
29 
30 	if (yylacnt == YYLASIZ)
31 		panic("unyylex");
32 	copy((char *) &Yla[yylacnt], (char *) y, sizeof Yla[0]);
33 	yylacnt++;
34 
35 }
36 
37 yylex()
38 {
39 	register c;
40 	register int **ip;
41 	register char *cp;
42 	int f;
43 	char delim;
44 
45 	if (yylacnt != 0) {
46 		yylacnt--;
47 		copy((char *) &Y, (char *) &Yla[yylacnt], sizeof Y);
48 		return (yychar);
49 	}
50 	if (c = yysavc)
51 		yysavc = 0;
52 	else
53 		c = readch();
54 #ifdef PXP
55 	yytokcnt++;
56 #endif
57 
58 next:
59 	/*
60 	 * skip white space
61 	 */
62 #ifdef PXP
63 	yywhcnt = 0;
64 #endif
65 	while (c == ' ' || c == '\t') {
66 #ifdef PXP
67 		if (c == '\t')
68 			yywhcnt++;
69 		yywhcnt++;
70 #endif
71 		c = readch();
72 	}
73 	yyecol = yycol;
74 	yyeline = yyline;
75 	yyefile = filename;
76 	yyeseqid = yyseqid;
77 	yyseekp = yylinpt;
78 	cp = token;
79 	yylval = yyline;
80 	switch (c) {
81 		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
82 		case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
83 		case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
84 		case 'v': case 'w': case 'x': case 'y': case 'z':
85 		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
86 		case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
87 		case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
88 		case 'V': case 'W': case 'X': case 'Y': case 'Z':
89 			do {
90 				*cp++ = c;
91 				c = readch();
92 			} while (alph(c) || digit(c));
93 			*cp = 0;
94 			if (opt('s'))
95 				for (cp = token; *cp; cp++)
96 					if (*cp >= 'A' && *cp <= 'Z') {
97 						*cp |= ' ';
98 					}
99 			yysavc = c;
100 			ip = (int **) hash((char *) 0, 1);
101 			if (*ip < (int *) yykey || *ip >= (int *) lastkey) {
102 				yylval = (int) *ip;
103 				return (YID);
104 			}
105 			yylval = yyline;
106 			/*
107 			 * For keywords
108 			 * the lexical token
109 			 * is magically retrieved
110 			 * from the keyword table.
111 			 */
112 			return ((*ip)[1]);
113 		case '0': case '1': case '2': case '3': case '4':
114 		case '5': case '6': case '7': case '8': case '9':
115 			f = 0;
116 			do {
117 				*cp++ = c;
118 				c = readch();
119 			} while (digit(c));
120 			if (c == 'b' || c == 'B') {
121 				/*
122 				 * nonstandard - octal constants
123 				 */
124 				if (opt('s')) {
125 					standard();
126 					yerror("Octal constants are non-standard");
127 				}
128 				*cp = 0;
129 				yylval = copystr(token);
130 				return (YBINT);
131 			}
132 			if (c == '.') {
133 				c = readch();
134 				if (c == '.') {
135 					*cp = 0;
136 					yysavc = YDOTDOT;
137 					yylval = copystr(token);
138 					return (YINT);
139 				}
140 infpnumb:
141 				f++;
142 				*cp++ = '.';
143 				if (!digit(c)) {
144 					yyset();
145 					recovered();
146 					yerror("Digits required after decimal point");
147 					*cp++ = '0';
148 				} else
149 					while (digit(c)) {
150 						*cp++ = c;
151 						c = readch();
152 					}
153 			}
154 			if (c == 'e' || c == 'E') {
155 				f++;
156 				*cp++ = c;
157 				if ((c = yysavc) == 0)
158 					c = readch();
159 				if (c == '+' || c == '-') {
160 					*cp++ = c;
161 					c = readch();
162 				}
163 				if (!digit(c)) {
164 					yyset();
165 					yerror("Digits required in exponent");
166 					*cp++ = '0';
167 				} else
168 					while (digit(c)) {
169 						*cp++ = c;
170 						c = readch();
171 					}
172 			}
173 			*cp = 0;
174 			yysavc = c;
175 			yylval = copystr(token);
176 			if (f)
177 				return (YNUMB);
178 			return (YINT);
179 		case '"':
180 		case '`':
181 		case '#':
182 			if (!any(bufp + 1, c))
183 				goto illch;
184 			if (!dquote) {
185 				recovered();
186 				dquote++;
187 				yerror("Character/string delimiter is '");
188 			}
189 		case '\'':
190 			delim = c;
191 			do {
192 				do {
193 					c = readch();
194 					if (c == '\n') {
195 						yerror("Unmatched %c for string", (char *) delim);
196 						if (cp == token)
197 							*cp++ = ' ', cp++;
198 						break;
199 					}
200 					*cp++ = c;
201 				} while (c != delim);
202 				c = readch();
203 			} while (c == delim);
204 			*--cp = 0;
205 			if (cp == token) {
206 				yerror("Null string not allowed");
207 				*cp++ = ' ';
208 				*cp++ = 0;
209 			}
210 			yysavc = c;
211 			yylval = copystr(token);
212 			return (YSTRING);
213 		case '.':
214 			c = readch();
215 			if (c == '.')
216 				return (YDOTDOT);
217 			if (digit(c)) {
218 				recovered();
219 				yerror("Digits required before decimal point");
220 				*cp++ = '0';
221 				goto infpnumb;
222 			}
223 			yysavc = c;
224 			return ('.');
225 		case '{':
226 			/*
227 			 * { ... } comment
228 			 */
229 #ifdef PXP
230 			getcm(c);
231 #endif
232 #ifdef PI
233 			c = options();
234 			while (c != '}') {
235 				if (c <= 0)
236 					goto nonterm;
237 				if (c == '{') {
238 					warning();
239 					yyset();
240 					yerror("{ in a { ... } comment");
241 				}
242 				c = readch();
243 			}
244 #endif
245 			c = readch();
246 			goto next;
247 		case '(':
248 			if ((c = readch()) == '*') {
249 				/*
250 				 * (* ... *) comment
251 				 */
252 #ifdef PXP
253 				getcm(c);
254 				c = readch();
255 				goto next;
256 #endif
257 #ifdef PI
258 				c = options();
259 				for (;;) {
260 					if (c < 0) {
261 nonterm:
262 						yerror("Comment does not terminate - QUIT");
263 						pexit(ERRS);
264 					}
265 					if (c == '(' && (c = readch()) == '*') {
266 						warning();
267 						yyset();
268 						yerror("(* in a (* ... *) comment");
269 					}
270 					if (c == '*') {
271 						if ((c = readch()) != ')')
272 							continue;
273 						c = readch();
274 						goto next;
275 					}
276 					c = readch();
277 				}
278 #endif
279 			}
280 			yysavc = c;
281 			c = '(';
282 		case ';':
283 		case ',':
284 		case ':':
285 		case '=':
286 		case '*':
287 		case '+':
288 		case '/':
289 		case '-':
290 		case ')':
291 		case '[':
292 		case ']':
293 		case '<':
294 		case '>':
295 		case '^':
296 			return (c);
297 		case '~':
298 		case '|':
299 		case '&':
300 			if ( opt('s') ) {
301 			    yyset();
302 			    standard();
303 			    yerror("%c is non-standard", (char *) c);
304 			}
305 			return c;
306 		default:
307 			switch (c) {
308 				case YDOTDOT:
309 					return (c);
310 				case '\n':
311 					c = readch();
312 #ifdef PXP
313 					yytokcnt++;
314 #endif
315 					goto next;
316 				case '\f':
317 					c = readch();
318 					goto next;
319 			}
320 			if (c <= 0)
321 				return (YEOF);
322 illch:
323 			do
324 				yysavc = readch();
325 			while (yysavc == c);
326 			yylval = c;
327 			return (YILLCH);
328 	}
329 }
330 
331 yyset()
332 {
333 
334 	yyecol = yycol;
335 	yyeline = yyline;
336 	yyefile = filename;
337 	yyseekp = yylinpt;
338 }
339 
340 /*
341  * Setuflg trims the current
342  * input line to at most 72 chars
343  * for the u option.
344  */
345 setuflg()
346 {
347 
348 	if (charbuf[71] != '\n') {
349 		charbuf[72] = '\n';
350 		charbuf[73] = 0;
351 	}
352 }
353