xref: /plan9/sys/src/cmd/spin/tl_lex.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
17dd7cddfSDavid du Colombier /***** tl_spin: tl_lex.c *****/
27dd7cddfSDavid du Colombier 
3312a1df1SDavid du Colombier /* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
47dd7cddfSDavid du Colombier /* All Rights Reserved.  This software is for educational purposes only.  */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code.  Permission is given to distribute this code provided that  */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged.  */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9312a1df1SDavid du Colombier /*             http://spinroot.com/                                       */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11312a1df1SDavid du Colombier 
127dd7cddfSDavid du Colombier /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
137dd7cddfSDavid du Colombier /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier #include <stdlib.h>
167dd7cddfSDavid du Colombier #include <ctype.h>
177dd7cddfSDavid du Colombier #include "tl.h"
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier static Symbol	*symtab[Nhash+1];
207dd7cddfSDavid du Colombier static int	tl_lex(void);
21*00d97012SDavid du Colombier extern int tl_peek(int);
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier extern YYSTYPE	tl_yylval;
247dd7cddfSDavid du Colombier extern char	yytext[];
257dd7cddfSDavid du Colombier 
267dd7cddfSDavid du Colombier #define Token(y)        tl_yylval = tl_nn(y,ZN,ZN); return y
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier static void
tl_getword(int first,int (* tst)(int))29312a1df1SDavid du Colombier tl_getword(int first, int (*tst)(int))
307dd7cddfSDavid du Colombier {	int i=0; char c;
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier 	yytext[i++] = (char ) first;
337dd7cddfSDavid du Colombier 	while (tst(c = tl_Getchar()))
347dd7cddfSDavid du Colombier 		yytext[i++] = c;
357dd7cddfSDavid du Colombier 	yytext[i] = '\0';
367dd7cddfSDavid du Colombier 	tl_UnGetchar();
377dd7cddfSDavid du Colombier }
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier static int
tl_follow(int tok,int ifyes,int ifno)40312a1df1SDavid du Colombier tl_follow(int tok, int ifyes, int ifno)
417dd7cddfSDavid du Colombier {	int c;
427dd7cddfSDavid du Colombier 	char buf[32];
437dd7cddfSDavid du Colombier 	extern int tl_yychar;
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier 	if ((c = tl_Getchar()) == tok)
467dd7cddfSDavid du Colombier 		return ifyes;
477dd7cddfSDavid du Colombier 	tl_UnGetchar();
487dd7cddfSDavid du Colombier 	tl_yychar = c;
497dd7cddfSDavid du Colombier 	sprintf(buf, "expected '%c'", tok);
507dd7cddfSDavid du Colombier 	tl_yyerror(buf);	/* no return from here */
517dd7cddfSDavid du Colombier 	return ifno;
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier int
tl_yylex(void)557dd7cddfSDavid du Colombier tl_yylex(void)
567dd7cddfSDavid du Colombier {	int c = tl_lex();
577dd7cddfSDavid du Colombier #if 0
58*00d97012SDavid du Colombier 	printf("c = %c (%d)\n", c, c);
597dd7cddfSDavid du Colombier #endif
607dd7cddfSDavid du Colombier 	return c;
617dd7cddfSDavid du Colombier }
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier static int
is_predicate(int z)64*00d97012SDavid du Colombier is_predicate(int z)
65*00d97012SDavid du Colombier {	char c, c_prev = z;
66*00d97012SDavid du Colombier 	char want = (z == '{') ? '}' : ')';
67*00d97012SDavid du Colombier 	int i = 0, j, nesting = 0;
68*00d97012SDavid du Colombier 	char peek_buf[512];
69*00d97012SDavid du Colombier 
70*00d97012SDavid du Colombier 	c = tl_peek(i++);	/* look ahead without changing position */
71*00d97012SDavid du Colombier 	while ((c != want || nesting > 0) && c != -1 && i < 2047)
72*00d97012SDavid du Colombier 	{	if (islower((int) c))
73*00d97012SDavid du Colombier 		{	peek_buf[0] = c;
74*00d97012SDavid du Colombier 			j = 1;
75*00d97012SDavid du Colombier 			while (j < (int) sizeof(peek_buf) && isalnum((int)(c = tl_peek(i))))
76*00d97012SDavid du Colombier 			{	peek_buf[j++] = c;
77*00d97012SDavid du Colombier 				i++;
78*00d97012SDavid du Colombier 			}
79*00d97012SDavid du Colombier 			c = 0;	/* make sure we don't match on z or want on the peekahead */
80*00d97012SDavid du Colombier 			if (j >= (int) sizeof(peek_buf))
81*00d97012SDavid du Colombier 			{	peek_buf[j-1] = '\0';
82*00d97012SDavid du Colombier 				fatal("name '%s' in ltl formula too long", peek_buf);
83*00d97012SDavid du Colombier 			}
84*00d97012SDavid du Colombier 			peek_buf[j] = '\0';
85*00d97012SDavid du Colombier 			if (strcmp(peek_buf, "always") == 0
86*00d97012SDavid du Colombier 			||  strcmp(peek_buf, "eventually") == 0
87*00d97012SDavid du Colombier 			||  strcmp(peek_buf, "until") == 0
88*00d97012SDavid du Colombier 			||  strcmp(peek_buf, "next") == 0)
89*00d97012SDavid du Colombier 			{	return 0;
90*00d97012SDavid du Colombier 			}
91*00d97012SDavid du Colombier 		} else
92*00d97012SDavid du Colombier 		{	char c_nxt = tl_peek(i);
93*00d97012SDavid du Colombier 			if (((c == 'U' || c == 'V' || c == 'X') && !isalnum_(c_prev) && !isalnum_(c_nxt))
94*00d97012SDavid du Colombier 			||  (c == '<' && c_nxt == '>')
95*00d97012SDavid du Colombier 			||  (c == '[' && c_nxt == ']'))
96*00d97012SDavid du Colombier 			{	return 0;
97*00d97012SDavid du Colombier 		}	}
98*00d97012SDavid du Colombier 
99*00d97012SDavid du Colombier 		if (c == z)
100*00d97012SDavid du Colombier 		{	nesting++;
101*00d97012SDavid du Colombier 		}
102*00d97012SDavid du Colombier 		if (c == want)
103*00d97012SDavid du Colombier 		{	nesting--;
104*00d97012SDavid du Colombier 		}
105*00d97012SDavid du Colombier 		c_prev = c;
106*00d97012SDavid du Colombier 		c = tl_peek(i++);
107*00d97012SDavid du Colombier 	}
108*00d97012SDavid du Colombier 	return 1;
109*00d97012SDavid du Colombier }
110*00d97012SDavid du Colombier 
111*00d97012SDavid du Colombier static void
read_upto_closing(int z)112*00d97012SDavid du Colombier read_upto_closing(int z)
113*00d97012SDavid du Colombier {	char c, want = (z == '{') ? '}' : ')';
114*00d97012SDavid du Colombier 	int i = 0, nesting = 0;
115*00d97012SDavid du Colombier 
116*00d97012SDavid du Colombier 	c = tl_Getchar();
117*00d97012SDavid du Colombier 	while ((c != want || nesting > 0) && c != -1 && i < 2047) /* yytext is 2048 */
118*00d97012SDavid du Colombier 	{	yytext[i++] = c;
119*00d97012SDavid du Colombier 		if (c == z)
120*00d97012SDavid du Colombier 		{	nesting++;
121*00d97012SDavid du Colombier 		}
122*00d97012SDavid du Colombier 		if (c == want)
123*00d97012SDavid du Colombier 		{	nesting--;
124*00d97012SDavid du Colombier 		}
125*00d97012SDavid du Colombier 		c = tl_Getchar();
126*00d97012SDavid du Colombier 	}
127*00d97012SDavid du Colombier 	yytext[i] = '\0';
128*00d97012SDavid du Colombier }
129*00d97012SDavid du Colombier 
130*00d97012SDavid du Colombier static int
tl_lex(void)1317dd7cddfSDavid du Colombier tl_lex(void)
1327dd7cddfSDavid du Colombier {	int c;
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier 	do {
1357dd7cddfSDavid du Colombier 		c = tl_Getchar();
1367dd7cddfSDavid du Colombier 		yytext[0] = (char ) c;
1377dd7cddfSDavid du Colombier 		yytext[1] = '\0';
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier 		if (c <= 0)
1407dd7cddfSDavid du Colombier 		{	Token(';');
1417dd7cddfSDavid du Colombier 		}
1427dd7cddfSDavid du Colombier 
1437dd7cddfSDavid du Colombier 	} while (c == ' ');	/* '\t' is removed in tl_main.c */
1447dd7cddfSDavid du Colombier 
145*00d97012SDavid du Colombier 	if (c == '{' || c == '(')	/* new 6.0.0 */
146*00d97012SDavid du Colombier 	{	if (is_predicate(c))
147*00d97012SDavid du Colombier 		{	read_upto_closing(c);
148*00d97012SDavid du Colombier 			tl_yylval = tl_nn(PREDICATE,ZN,ZN);
149*00d97012SDavid du Colombier 			tl_yylval->sym = tl_lookup(yytext);
150*00d97012SDavid du Colombier 			return PREDICATE;
151*00d97012SDavid du Colombier 	}	}
152*00d97012SDavid du Colombier 
153*00d97012SDavid du Colombier 	if (c == '}')
154*00d97012SDavid du Colombier 	{	tl_yyerror("unexpected '}'");
155*00d97012SDavid du Colombier 	}
1567dd7cddfSDavid du Colombier 	if (islower(c))
157312a1df1SDavid du Colombier 	{	tl_getword(c, isalnum_);
1587dd7cddfSDavid du Colombier 		if (strcmp("true", yytext) == 0)
1597dd7cddfSDavid du Colombier 		{	Token(TRUE);
1607dd7cddfSDavid du Colombier 		}
1617dd7cddfSDavid du Colombier 		if (strcmp("false", yytext) == 0)
1627dd7cddfSDavid du Colombier 		{	Token(FALSE);
1637dd7cddfSDavid du Colombier 		}
164*00d97012SDavid du Colombier 		if (strcmp("always", yytext) == 0)
165*00d97012SDavid du Colombier 		{	Token(ALWAYS);
166*00d97012SDavid du Colombier 		}
167*00d97012SDavid du Colombier 		if (strcmp("eventually", yytext) == 0)
168*00d97012SDavid du Colombier 		{	Token(EVENTUALLY);
169*00d97012SDavid du Colombier 		}
170*00d97012SDavid du Colombier 		if (strcmp("until", yytext) == 0)
171*00d97012SDavid du Colombier 		{	Token(U_OPER);
172*00d97012SDavid du Colombier 		}
173*00d97012SDavid du Colombier #ifdef NXT
174*00d97012SDavid du Colombier 		if (strcmp("next", yytext) == 0)
175*00d97012SDavid du Colombier 		{	Token(NEXT);
176*00d97012SDavid du Colombier 		}
177*00d97012SDavid du Colombier #endif
178*00d97012SDavid du Colombier 		if (strcmp("not", yytext) == 0)
179*00d97012SDavid du Colombier 		{	Token(NOT);
180*00d97012SDavid du Colombier 		}
1817dd7cddfSDavid du Colombier 		tl_yylval = tl_nn(PREDICATE,ZN,ZN);
1827dd7cddfSDavid du Colombier 		tl_yylval->sym = tl_lookup(yytext);
1837dd7cddfSDavid du Colombier 		return PREDICATE;
1847dd7cddfSDavid du Colombier 	}
185*00d97012SDavid du Colombier 
1867dd7cddfSDavid du Colombier 	if (c == '<')
1877dd7cddfSDavid du Colombier 	{	c = tl_Getchar();
1887dd7cddfSDavid du Colombier 		if (c == '>')
1897dd7cddfSDavid du Colombier 		{	Token(EVENTUALLY);
1907dd7cddfSDavid du Colombier 		}
1917dd7cddfSDavid du Colombier 		if (c != '-')
1927dd7cddfSDavid du Colombier 		{	tl_UnGetchar();
1937dd7cddfSDavid du Colombier 			tl_yyerror("expected '<>' or '<->'");
1947dd7cddfSDavid du Colombier 		}
1957dd7cddfSDavid du Colombier 		c = tl_Getchar();
1967dd7cddfSDavid du Colombier 		if (c == '>')
1977dd7cddfSDavid du Colombier 		{	Token(EQUIV);
1987dd7cddfSDavid du Colombier 		}
1997dd7cddfSDavid du Colombier 		tl_UnGetchar();
2007dd7cddfSDavid du Colombier 		tl_yyerror("expected '<->'");
2017dd7cddfSDavid du Colombier 	}
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier 	switch (c) {
204312a1df1SDavid du Colombier 	case '/' : c = tl_follow('\\', AND, '/'); break;
205312a1df1SDavid du Colombier 	case '\\': c = tl_follow('/', OR, '\\'); break;
206312a1df1SDavid du Colombier 	case '&' : c = tl_follow('&', AND, '&'); break;
207312a1df1SDavid du Colombier 	case '|' : c = tl_follow('|', OR, '|'); break;
208312a1df1SDavid du Colombier 	case '[' : c = tl_follow(']', ALWAYS, '['); break;
209312a1df1SDavid du Colombier 	case '-' : c = tl_follow('>', IMPLIES, '-'); break;
2107dd7cddfSDavid du Colombier 	case '!' : c = NOT; break;
2117dd7cddfSDavid du Colombier 	case 'U' : c = U_OPER; break;
2127dd7cddfSDavid du Colombier 	case 'V' : c = V_OPER; break;
2137dd7cddfSDavid du Colombier #ifdef NXT
2147dd7cddfSDavid du Colombier 	case 'X' : c = NEXT; break;
2157dd7cddfSDavid du Colombier #endif
2167dd7cddfSDavid du Colombier 	default  : break;
2177dd7cddfSDavid du Colombier 	}
2187dd7cddfSDavid du Colombier 	Token(c);
2197dd7cddfSDavid du Colombier }
2207dd7cddfSDavid du Colombier 
2217dd7cddfSDavid du Colombier Symbol *
tl_lookup(char * s)2227dd7cddfSDavid du Colombier tl_lookup(char *s)
2237dd7cddfSDavid du Colombier {	Symbol *sp;
2247dd7cddfSDavid du Colombier 	int h = hash(s);
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier 	for (sp = symtab[h]; sp; sp = sp->next)
2277dd7cddfSDavid du Colombier 		if (strcmp(sp->name, s) == 0)
2287dd7cddfSDavid du Colombier 			return sp;
2297dd7cddfSDavid du Colombier 
2307dd7cddfSDavid du Colombier 	sp = (Symbol *) tl_emalloc(sizeof(Symbol));
231312a1df1SDavid du Colombier 	sp->name = (char *) tl_emalloc((int) strlen(s) + 1);
2327dd7cddfSDavid du Colombier 	strcpy(sp->name, s);
2337dd7cddfSDavid du Colombier 	sp->next = symtab[h];
2347dd7cddfSDavid du Colombier 	symtab[h] = sp;
2357dd7cddfSDavid du Colombier 
2367dd7cddfSDavid du Colombier 	return sp;
2377dd7cddfSDavid du Colombier }
2387dd7cddfSDavid du Colombier 
2397dd7cddfSDavid du Colombier Symbol *
getsym(Symbol * s)2407dd7cddfSDavid du Colombier getsym(Symbol *s)
2417dd7cddfSDavid du Colombier {	Symbol *n = (Symbol *) tl_emalloc(sizeof(Symbol));
2427dd7cddfSDavid du Colombier 
2437dd7cddfSDavid du Colombier 	n->name = s->name;
2447dd7cddfSDavid du Colombier 	return n;
2457dd7cddfSDavid du Colombier }
246