gram.y 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. %{
  2. #include <stdio.h>
  3. #include "lburg.h"
  4. static char rcsid[] = "$Id: gram.y 145 2001-10-17 21:53:10Z timo $";
  5. /*lint -e616 -e527 -e652 -esym(552,yynerrs) -esym(563,yynewstate,yyerrlab) */
  6. static int yylineno = 0;
  7. %}
  8. %union {
  9. int n;
  10. char *string;
  11. Tree tree;
  12. }
  13. %term TERMINAL
  14. %term START
  15. %term PPERCENT
  16. %token <string> ID TEMPLATE CODE
  17. %token <n> INT
  18. %type <string> nonterm cost
  19. %type <tree> tree
  20. %%
  21. spec : decls PPERCENT rules { yylineno = 0; }
  22. | decls { yylineno = 0; }
  23. ;
  24. decls : /* lambda */
  25. | decls decl
  26. ;
  27. decl : TERMINAL blist '\n'
  28. | START nonterm '\n' {
  29. if (nonterm($2)->number != 1)
  30. yyerror("redeclaration of the start symbol\n");
  31. }
  32. | '\n'
  33. | error '\n' { yyerrok; }
  34. ;
  35. blist : /* lambda */
  36. | blist ID '=' INT { term($2, $4); }
  37. ;
  38. rules : /* lambda */
  39. | rules nonterm ':' tree TEMPLATE cost '\n' { rule($2, $4, $5, $6); }
  40. | rules '\n'
  41. | rules error '\n' { yyerrok; }
  42. ;
  43. nonterm : ID { nonterm($$ = $1); }
  44. ;
  45. tree : ID { $$ = tree($1, 0, 0); }
  46. | ID '(' tree ')' { $$ = tree($1, $3, 0); }
  47. | ID '(' tree ',' tree ')' { $$ = tree($1, $3, $5); }
  48. ;
  49. cost : CODE { if (*$1 == 0) $$ = "0"; }
  50. ;
  51. %%
  52. #include <assert.h>
  53. #include <stdarg.h>
  54. #include <ctype.h>
  55. #include <string.h>
  56. #include <limits.h>
  57. int errcnt = 0;
  58. FILE *infp = NULL;
  59. FILE *outfp = NULL;
  60. static char buf[BUFSIZ], *bp = buf;
  61. static int ppercent = 0;
  62. static int code = 0;
  63. static int get(void) {
  64. if (*bp == 0) {
  65. bp = buf;
  66. *bp = 0;
  67. if (fgets(buf, sizeof buf, infp) == NULL)
  68. return EOF;
  69. yylineno++;
  70. while (buf[0] == '%' && buf[1] == '{' && buf[2] == '\n') {
  71. for (;;) {
  72. if (fgets(buf, sizeof buf, infp) == NULL) {
  73. yywarn("unterminated %{...%}\n");
  74. return EOF;
  75. }
  76. yylineno++;
  77. if (strcmp(buf, "%}\n") == 0)
  78. break;
  79. fputs(buf, outfp);
  80. }
  81. if (fgets(buf, sizeof buf, infp) == NULL)
  82. return EOF;
  83. yylineno++;
  84. }
  85. }
  86. return *bp++;
  87. }
  88. void yyerror(char *fmt, ...) {
  89. va_list ap;
  90. va_start(ap, fmt);
  91. if (yylineno > 0)
  92. fprintf(stderr, "line %d: ", yylineno);
  93. vfprintf(stderr, fmt, ap);
  94. if (fmt[strlen(fmt)-1] != '\n')
  95. fprintf(stderr, "\n");
  96. errcnt++;
  97. va_end(ap);
  98. }
  99. int yylex(void) {
  100. int c;
  101. if (code) {
  102. char *p;
  103. bp += strspn(bp, " \t\f");
  104. p = strchr(bp, '\n');
  105. if (p == NULL)
  106. p = strchr(bp, '\n');
  107. while (p > bp && isspace(p[-1]))
  108. p--;
  109. yylval.string = alloc(p - bp + 1);
  110. strncpy(yylval.string, bp, p - bp);
  111. yylval.string[p - bp] = 0;
  112. bp = p;
  113. code--;
  114. return CODE;
  115. }
  116. while ((c = get()) != EOF) {
  117. switch (c) {
  118. case ' ': case '\f': case '\t':
  119. continue;
  120. case '\n':
  121. case '(': case ')': case ',':
  122. case ':': case '=':
  123. return c;
  124. }
  125. if (c == '%' && *bp == '%') {
  126. bp++;
  127. return ppercent++ ? 0 : PPERCENT;
  128. } else if (c == '%' && strncmp(bp, "term", 4) == 0
  129. && isspace(bp[4])) {
  130. bp += 4;
  131. return TERMINAL;
  132. } else if (c == '%' && strncmp(bp, "start", 5) == 0
  133. && isspace(bp[5])) {
  134. bp += 5;
  135. return START;
  136. } else if (c == '"') {
  137. char *p = strchr(bp, '"');
  138. if (p == NULL) {
  139. yyerror("missing \" in assembler template\n");
  140. p = strchr(bp, '\n');
  141. if (p == NULL)
  142. p = strchr(bp, '\0');
  143. }
  144. assert(p);
  145. yylval.string = alloc(p - bp + 1);
  146. strncpy(yylval.string, bp, p - bp);
  147. yylval.string[p - bp] = 0;
  148. bp = *p == '"' ? p + 1 : p;
  149. code++;
  150. return TEMPLATE;
  151. } else if (isdigit(c)) {
  152. int n = 0;
  153. do {
  154. int d = c - '0';
  155. if (n > (INT_MAX - d)/10)
  156. yyerror("integer greater than %d\n", INT_MAX);
  157. else
  158. n = 10*n + d;
  159. c = get();
  160. } while (c != EOF && isdigit(c));
  161. bp--;
  162. yylval.n = n;
  163. return INT;
  164. } else if (isalpha(c)) {
  165. char *p = bp - 1;
  166. while (isalpha(*bp) || isdigit(*bp) || *bp == '_')
  167. bp++;
  168. yylval.string = alloc(bp - p + 1);
  169. strncpy(yylval.string, p, bp - p);
  170. yylval.string[bp - p] = 0;
  171. return ID;
  172. } else if (isprint(c))
  173. yyerror("invalid character `%c'\n", c);
  174. else
  175. yyerror("invalid character `\\%03o'\n", (unsigned char)c);
  176. }
  177. return 0;
  178. }
  179. void yywarn(char *fmt, ...) {
  180. va_list ap;
  181. va_start(ap, fmt);
  182. if (yylineno > 0)
  183. fprintf(stderr, "line %d: ", yylineno);
  184. fprintf(stderr, "warning: ");
  185. vfprintf(stderr, fmt, ap);
  186. }