tl_lex.c 5.6 KB

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