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