1 /***** tl_spin: tl_lex.c *****/
4 * This file is part of the public release of Spin. It is subject to the
5 * terms in the LICENSE file that is included in this source directory.
6 * Tool documentation is available at http://spinroot.com
8 * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
9 * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
16 static Symbol *symtab[Nhash+1];
17 static int tl_lex(void);
18 extern int tl_peek(int);
20 extern YYSTYPE tl_yylval;
23 #define Token(y) tl_yylval = tl_nn(y,ZN,ZN); return y
26 tl_getword(int first, int (*tst)(int))
29 yytext[i++] = (char ) first;
32 while (c != -1 && tst(c))
33 { yytext[i++] = (char) c;
37 /* while (tst(c = tl_Getchar()))
45 tl_follow(int tok, int ifyes, int ifno)
50 if ((c = tl_Getchar()) == tok)
54 sprintf(buf, "expected '%c'", tok);
55 tl_yyerror(buf); /* no return from here */
63 printf("c = %c (%d)\n", c, c);
71 char want = (z == '{') ? '}' : ')';
72 int i = 0, j, nesting = 0;
75 c = tl_peek(i++); /* look ahead without changing position */
76 while ((c != want || nesting > 0) && c != -1 && i < 2047)
77 { if (islower((int) c) || c == '_')
80 while (j < (int) sizeof(peek_buf)
81 && (isalnum((int)(c = tl_peek(i))) || c == '_'))
85 c = 0; /* make sure we don't match on z or want on the peekahead */
86 if (j >= (int) sizeof(peek_buf))
87 { peek_buf[j-1] = '\0';
88 fatal("name '%s' in ltl formula too long", peek_buf);
91 if (strcmp(peek_buf, "always") == 0
92 || strcmp(peek_buf, "equivalent") == 0
93 || strcmp(peek_buf, "eventually") == 0
94 || strcmp(peek_buf, "until") == 0
95 || strcmp(peek_buf, "next") == 0
96 || strcmp(peek_buf, "c_expr") == 0)
100 { int c_nxt = tl_peek(i);
101 if (((c == 'U' || c == 'V' || c == 'X')
103 && (c_nxt == -1 || !isalnum_(c_nxt)))
104 || (c == '<' && c_nxt == '>')
105 || (c == '<' && c_nxt == '-')
106 || (c == '-' && c_nxt == '>')
107 || (c == '[' && c_nxt == ']'))
124 read_upto_closing(int z)
125 { char c, want = (z == '{') ? '}' : ')';
126 int i = 0, nesting = 0;
129 while ((c != want || nesting > 0) && c != -1 && i < 2047) /* yytext is 2048 */
148 yytext[0] = (char ) c;
155 } while (c == ' '); /* '\t' is removed in tl_main.c */
157 if (c == '{' || c == '(') /* new 6.0.0 */
158 { if (is_predicate(c))
159 { read_upto_closing(c);
160 tl_yylval = tl_nn(PREDICATE,ZN,ZN);
162 { fatal("unexpected error 4", (char *) 0);
164 tl_yylval->sym = tl_lookup(yytext);
169 { tl_yyerror("unexpected '}'");
172 { tl_getword(c, isalnum_);
173 if (strcmp("true", yytext) == 0)
176 if (strcmp("false", yytext) == 0)
179 if (strcmp("always", yytext) == 0)
182 if (strcmp("eventually", yytext) == 0)
185 if (strcmp("until", yytext) == 0)
189 if (strcmp("next", yytext) == 0)
193 if (strcmp("c_expr", yytext) == 0)
196 if (strcmp("not", yytext) == 0)
199 tl_yylval = tl_nn(PREDICATE,ZN,ZN);
201 { fatal("unexpected error 5", (char *) 0);
203 tl_yylval->sym = tl_lookup(yytext);
214 tl_yyerror("expected '<>' or '<->'");
221 tl_yyerror("expected '<->'");
225 case '/' : c = tl_follow('\\', AND, '/'); break;
226 case '\\': c = tl_follow('/', OR, '\\'); break;
227 case '&' : c = tl_follow('&', AND, '&'); break;
228 case '|' : c = tl_follow('|', OR, '|'); break;
229 case '[' : c = tl_follow(']', ALWAYS, '['); break;
230 case '-' : c = tl_follow('>', IMPLIES, '-'); break;
231 case '!' : c = NOT; break;
232 case 'U' : c = U_OPER; break;
233 case 'V' : c = V_OPER; break;
235 case 'X' : c = NEXT; break;
245 unsigned int h = hash(s);
247 for (sp = symtab[h]; sp; sp = sp->next)
248 if (strcmp(sp->name, s) == 0)
251 sp = (Symbol *) tl_emalloc(sizeof(Symbol));
252 sp->name = (char *) tl_emalloc((int) strlen(s) + 1);
254 sp->next = symtab[h];
262 { Symbol *n = (Symbol *) tl_emalloc(sizeof(Symbol));