1
0

expr.y 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /* Yacc productions for "expr" command: */
  2. %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
  3. %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH
  4. /* operators listed below in increasing precedence: */
  5. %left OR
  6. %left AND
  7. %left EQ LT GT GEQ LEQ NEQ
  8. %left ADD SUBT
  9. %left MULT DIV REM
  10. %left MCH
  11. %left MATCH
  12. %left SUBSTR
  13. %left LENGTH INDEX
  14. %{
  15. #define YYSTYPE charp
  16. typedef char *charp;
  17. %}
  18. %%
  19. /* a single `expression' is evaluated and printed: */
  20. expression: expr NOARG = {
  21. prt(1, $1);
  22. exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
  23. }
  24. ;
  25. expr: '(' expr ')' = { $$ = $2; }
  26. | expr OR expr = { $$ = conj(OR, $1, $3); }
  27. | expr AND expr = { $$ = conj(AND, $1, $3); }
  28. | expr EQ expr = { $$ = rel(EQ, $1, $3); }
  29. | expr GT expr = { $$ = rel(GT, $1, $3); }
  30. | expr GEQ expr = { $$ = rel(GEQ, $1, $3); }
  31. | expr LT expr = { $$ = rel(LT, $1, $3); }
  32. | expr LEQ expr = { $$ = rel(LEQ, $1, $3); }
  33. | expr NEQ expr = { $$ = rel(NEQ, $1, $3); }
  34. | expr ADD expr = { $$ = arith(ADD, $1, $3); }
  35. | expr SUBT expr = { $$ = arith(SUBT, $1, $3); }
  36. | expr MULT expr = { $$ = arith(MULT, $1, $3); }
  37. | expr DIV expr = { $$ = arith(DIV, $1, $3); }
  38. | expr REM expr = { $$ = arith(REM, $1, $3); }
  39. | expr MCH expr = { $$ = match($1, $3); }
  40. | MATCH expr expr = { $$ = match($2, $3); }
  41. | SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
  42. | LENGTH expr = { $$ = length($2); }
  43. | INDEX expr expr = { $$ = index($2, $3); }
  44. | A_STRING
  45. ;
  46. %%
  47. /* expression command */
  48. #include <stdio.h>
  49. /* get rid of yacc debug printf's */
  50. #define printf
  51. #define ESIZE 512
  52. #define error(c) errxx(c)
  53. #define EQL(x,y) !strcmp(x,y)
  54. long atol();
  55. char *ltoa();
  56. char **Av;
  57. int Ac;
  58. int Argi;
  59. char Mstring[1][128];
  60. char *malloc();
  61. extern int nbra;
  62. int yyparse(void);
  63. main(argc, argv) char **argv; {
  64. Ac = argc;
  65. Argi = 1;
  66. Av = argv;
  67. yyparse();
  68. }
  69. char *operator[] = { "|", "&", "+", "-", "*", "/", "%", ":",
  70. "=", "==", "<", "<=", ">", ">=", "!=",
  71. "match", "substr", "length", "index", "\0" };
  72. int op[] = { OR, AND, ADD, SUBT, MULT, DIV, REM, MCH,
  73. EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
  74. MATCH, SUBSTR, LENGTH, INDEX };
  75. yylex() {
  76. register char *p;
  77. register i;
  78. if(Argi >= Ac) return NOARG;
  79. p = Av[Argi++];
  80. if(*p == '(' || *p == ')')
  81. return (int)*p;
  82. for(i = 0; *operator[i]; ++i)
  83. if(EQL(operator[i], p))
  84. return op[i];
  85. yylval = p;
  86. return A_STRING;
  87. }
  88. char *rel(op, r1, r2) register char *r1, *r2; {
  89. register i;
  90. if(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$"))
  91. i = atol(r1) - atol(r2);
  92. else
  93. i = strcmp(r1, r2);
  94. switch(op) {
  95. case EQ: i = i==0; break;
  96. case GT: i = i>0; break;
  97. case GEQ: i = i>=0; break;
  98. case LT: i = i<0; break;
  99. case LEQ: i = i<=0; break;
  100. case NEQ: i = i!=0; break;
  101. }
  102. return i? "1": "0";
  103. }
  104. char *arith(op, r1, r2) char *r1, *r2; {
  105. long i1, i2;
  106. register char *rv;
  107. if(!(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$")))
  108. yyerror("non-numeric argument");
  109. i1 = atol(r1);
  110. i2 = atol(r2);
  111. switch(op) {
  112. case ADD: i1 = i1 + i2; break;
  113. case SUBT: i1 = i1 - i2; break;
  114. case MULT: i1 = i1 * i2; break;
  115. case DIV: i1 = i1 / i2; break;
  116. case REM: i1 = i1 % i2; break;
  117. }
  118. rv = malloc(16);
  119. strcpy(rv, ltoa(i1));
  120. return rv;
  121. }
  122. char *conj(op, r1, r2) char *r1, *r2; {
  123. register char *rv;
  124. switch(op) {
  125. case OR:
  126. if(EQL(r1, "0")
  127. || EQL(r1, ""))
  128. if(EQL(r2, "0")
  129. || EQL(r2, ""))
  130. rv = "0";
  131. else
  132. rv = r2;
  133. else
  134. rv = r1;
  135. break;
  136. case AND:
  137. if(EQL(r1, "0")
  138. || EQL(r1, ""))
  139. rv = "0";
  140. else if(EQL(r2, "0")
  141. || EQL(r2, ""))
  142. rv = "0";
  143. else
  144. rv = r1;
  145. break;
  146. }
  147. return rv;
  148. }
  149. char *substr(v, s, w) char *v, *s, *w; {
  150. register si, wi;
  151. register char *res;
  152. si = atol(s);
  153. wi = atol(w);
  154. while(--si) if(*v) ++v;
  155. res = v;
  156. while(wi--) if(*v) ++v;
  157. *v = '\0';
  158. return res;
  159. }
  160. char *length(s) register char *s; {
  161. register i = 0;
  162. register char *rv;
  163. while(*s++) ++i;
  164. rv = malloc(8);
  165. strcpy(rv, ltoa((long)i));
  166. return rv;
  167. }
  168. char *index(s, t) char *s, *t; {
  169. register i, j;
  170. register char *rv;
  171. for(i = 0; s[i] ; ++i)
  172. for(j = 0; t[j] ; ++j)
  173. if(s[i]==t[j]) {
  174. strcpy(rv=malloc(8), ltoa((long)++i));
  175. return rv;
  176. }
  177. return "0";
  178. }
  179. char *match(s, p)
  180. {
  181. register char *rv;
  182. strcpy(rv=malloc(8), ltoa((long)ematch(s, p)));
  183. if(nbra) {
  184. rv = malloc(strlen(Mstring[0])+1);
  185. strcpy(rv, Mstring[0]);
  186. }
  187. return rv;
  188. }
  189. #define INIT register char *sp = instring;
  190. #define GETC() (*sp++)
  191. #define PEEKC() (*sp)
  192. #define UNGETC(c) (--sp)
  193. #define RETURN(c) return
  194. #define ERROR(c) errxx(c)
  195. ematch(s, p)
  196. char *s;
  197. register char *p;
  198. {
  199. static char expbuf[ESIZE];
  200. char *compile();
  201. register num;
  202. extern char *braslist[], *braelist[], *loc2;
  203. compile(p, expbuf, &expbuf[ESIZE], 0);
  204. if(nbra > 1)
  205. yyerror("Too many '\\('s");
  206. if(advance(s, expbuf)) {
  207. if(nbra == 1) {
  208. p = braslist[0];
  209. num = braelist[0] - p;
  210. strncpy(Mstring[0], p, num);
  211. Mstring[0][num] = '\0';
  212. }
  213. return(loc2-s);
  214. }
  215. return(0);
  216. }
  217. errxx(c)
  218. {
  219. yyerror("RE error");
  220. }
  221. #include "regexp.h"
  222. yyerror(s)
  223. {
  224. write(2, "expr: ", 6);
  225. prt(2, s);
  226. exit(2);
  227. }
  228. prt(fd, s)
  229. char *s;
  230. {
  231. write(fd, s, strlen(s));
  232. write(fd, "\n", 1);
  233. }
  234. char *ltoa(l)
  235. long l;
  236. {
  237. static char str[20];
  238. register char *sp = &str[18];
  239. register i;
  240. register neg = 0;
  241. if(l < 0)
  242. ++neg, l *= -1;
  243. str[19] = '\0';
  244. do {
  245. i = l % 10;
  246. *sp-- = '0' + i;
  247. l /= 10;
  248. } while(l);
  249. if(neg)
  250. *sp-- = '-';
  251. return ++sp;
  252. }