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