tl_lex.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /***** tl_spin: tl_lex.c *****/
  2. /* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* No guarantee whatsoever is expressed or implied by the distribution of */
  5. /* this code. Permission is given to distribute this code provided that */
  6. /* this introductory message is not removed and no monies are exchanged. */
  7. /* Software written by Gerard J. Holzmann. For tool documentation see: */
  8. /* http://spinroot.com/ */
  9. /* Send all bug-reports and/or questions to: bugs@spinroot.com */
  10. /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
  11. /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
  12. #include <stdlib.h>
  13. #include <ctype.h>
  14. #include "tl.h"
  15. static Symbol *symtab[Nhash+1];
  16. static int tl_lex(void);
  17. extern int tl_peek(int);
  18. extern YYSTYPE tl_yylval;
  19. extern char yytext[];
  20. #define Token(y) tl_yylval = tl_nn(y,ZN,ZN); return y
  21. static void
  22. tl_getword(int first, int (*tst)(int))
  23. { int i=0; char c;
  24. yytext[i++] = (char ) first;
  25. while (tst(c = tl_Getchar()))
  26. yytext[i++] = c;
  27. yytext[i] = '\0';
  28. tl_UnGetchar();
  29. }
  30. static int
  31. tl_follow(int tok, int ifyes, int ifno)
  32. { int c;
  33. char buf[32];
  34. extern int tl_yychar;
  35. if ((c = tl_Getchar()) == tok)
  36. return ifyes;
  37. tl_UnGetchar();
  38. tl_yychar = c;
  39. sprintf(buf, "expected '%c'", tok);
  40. tl_yyerror(buf); /* no return from here */
  41. return ifno;
  42. }
  43. int
  44. tl_yylex(void)
  45. { int c = tl_lex();
  46. #if 0
  47. printf("c = %c (%d)\n", c, c);
  48. #endif
  49. return c;
  50. }
  51. static int
  52. is_predicate(int z)
  53. { char c, c_prev = z;
  54. char want = (z == '{') ? '}' : ')';
  55. int i = 0, j, nesting = 0;
  56. char peek_buf[512];
  57. c = tl_peek(i++); /* look ahead without changing position */
  58. while ((c != want || nesting > 0) && c != -1 && i < 2047)
  59. { if (islower((int) c))
  60. { peek_buf[0] = c;
  61. j = 1;
  62. while (j < (int) sizeof(peek_buf) && isalnum((int)(c = tl_peek(i))))
  63. { peek_buf[j++] = c;
  64. i++;
  65. }
  66. c = 0; /* make sure we don't match on z or want on the peekahead */
  67. if (j >= (int) sizeof(peek_buf))
  68. { peek_buf[j-1] = '\0';
  69. fatal("name '%s' in ltl formula too long", peek_buf);
  70. }
  71. peek_buf[j] = '\0';
  72. if (strcmp(peek_buf, "always") == 0
  73. || strcmp(peek_buf, "eventually") == 0
  74. || strcmp(peek_buf, "until") == 0
  75. || strcmp(peek_buf, "next") == 0)
  76. { return 0;
  77. }
  78. } else
  79. { char c_nxt = tl_peek(i);
  80. if (((c == 'U' || c == 'V' || c == 'X') && !isalnum_(c_prev) && !isalnum_(c_nxt))
  81. || (c == '<' && c_nxt == '>')
  82. || (c == '[' && c_nxt == ']'))
  83. { return 0;
  84. } }
  85. if (c == z)
  86. { nesting++;
  87. }
  88. if (c == want)
  89. { nesting--;
  90. }
  91. c_prev = c;
  92. c = tl_peek(i++);
  93. }
  94. return 1;
  95. }
  96. static void
  97. read_upto_closing(int z)
  98. { char c, want = (z == '{') ? '}' : ')';
  99. int i = 0, nesting = 0;
  100. c = tl_Getchar();
  101. while ((c != want || nesting > 0) && c != -1 && i < 2047) /* yytext is 2048 */
  102. { yytext[i++] = c;
  103. if (c == z)
  104. { nesting++;
  105. }
  106. if (c == want)
  107. { nesting--;
  108. }
  109. c = tl_Getchar();
  110. }
  111. yytext[i] = '\0';
  112. }
  113. static int
  114. tl_lex(void)
  115. { int c;
  116. do {
  117. c = tl_Getchar();
  118. yytext[0] = (char ) c;
  119. yytext[1] = '\0';
  120. if (c <= 0)
  121. { Token(';');
  122. }
  123. } while (c == ' '); /* '\t' is removed in tl_main.c */
  124. if (c == '{' || c == '(') /* new 6.0.0 */
  125. { if (is_predicate(c))
  126. { read_upto_closing(c);
  127. tl_yylval = tl_nn(PREDICATE,ZN,ZN);
  128. tl_yylval->sym = tl_lookup(yytext);
  129. return PREDICATE;
  130. } }
  131. if (c == '}')
  132. { tl_yyerror("unexpected '}'");
  133. }
  134. if (islower(c))
  135. { tl_getword(c, isalnum_);
  136. if (strcmp("true", yytext) == 0)
  137. { Token(TRUE);
  138. }
  139. if (strcmp("false", yytext) == 0)
  140. { Token(FALSE);
  141. }
  142. if (strcmp("always", yytext) == 0)
  143. { Token(ALWAYS);
  144. }
  145. if (strcmp("eventually", yytext) == 0)
  146. { Token(EVENTUALLY);
  147. }
  148. if (strcmp("until", yytext) == 0)
  149. { Token(U_OPER);
  150. }
  151. #ifdef NXT
  152. if (strcmp("next", yytext) == 0)
  153. { Token(NEXT);
  154. }
  155. #endif
  156. if (strcmp("not", yytext) == 0)
  157. { Token(NOT);
  158. }
  159. tl_yylval = tl_nn(PREDICATE,ZN,ZN);
  160. tl_yylval->sym = tl_lookup(yytext);
  161. return PREDICATE;
  162. }
  163. if (c == '<')
  164. { c = tl_Getchar();
  165. if (c == '>')
  166. { Token(EVENTUALLY);
  167. }
  168. if (c != '-')
  169. { tl_UnGetchar();
  170. tl_yyerror("expected '<>' or '<->'");
  171. }
  172. c = tl_Getchar();
  173. if (c == '>')
  174. { Token(EQUIV);
  175. }
  176. tl_UnGetchar();
  177. tl_yyerror("expected '<->'");
  178. }
  179. switch (c) {
  180. case '/' : c = tl_follow('\\', AND, '/'); break;
  181. case '\\': c = tl_follow('/', OR, '\\'); break;
  182. case '&' : c = tl_follow('&', AND, '&'); break;
  183. case '|' : c = tl_follow('|', OR, '|'); break;
  184. case '[' : c = tl_follow(']', ALWAYS, '['); break;
  185. case '-' : c = tl_follow('>', IMPLIES, '-'); break;
  186. case '!' : c = NOT; break;
  187. case 'U' : c = U_OPER; break;
  188. case 'V' : c = V_OPER; break;
  189. #ifdef NXT
  190. case 'X' : c = NEXT; break;
  191. #endif
  192. default : break;
  193. }
  194. Token(c);
  195. }
  196. Symbol *
  197. tl_lookup(char *s)
  198. { Symbol *sp;
  199. int h = hash(s);
  200. for (sp = symtab[h]; sp; sp = sp->next)
  201. if (strcmp(sp->name, s) == 0)
  202. return sp;
  203. sp = (Symbol *) tl_emalloc(sizeof(Symbol));
  204. sp->name = (char *) tl_emalloc((int) strlen(s) + 1);
  205. strcpy(sp->name, s);
  206. sp->next = symtab[h];
  207. symtab[h] = sp;
  208. return sp;
  209. }
  210. Symbol *
  211. getsym(Symbol *s)
  212. { Symbol *n = (Symbol *) tl_emalloc(sizeof(Symbol));
  213. n->name = s->name;
  214. return n;
  215. }