plural.y 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. %{
  2. /* Expression parsing for plural form selection.
  3. Copyright (C) 2000, 2001 Free Software Foundation, Inc.
  4. Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software Foundation,
  15. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  16. /* The bison generated parser uses alloca. AIX 3 forces us to put this
  17. declaration at the beginning of the file. The declaration in bison's
  18. skeleton file comes too late. This must come before <config.h>
  19. because <config.h> may include arbitrary system headers. */
  20. #if defined _AIX && !defined __GNUC__
  21. #pragma alloca
  22. #endif
  23. #ifdef HAVE_CONFIG_H
  24. # include <config.h>
  25. #endif
  26. #include <stdlib.h>
  27. #include "gettextP.h"
  28. /* Names for the libintl functions are a problem. They must not clash
  29. with existing names and they should follow ANSI C. But this source
  30. code is also used in GNU C Library where the names have a __
  31. prefix. So we have to make a difference here. */
  32. #ifdef _LIBC
  33. # define FREE_EXPRESSION __gettext_free_exp
  34. #else
  35. # define FREE_EXPRESSION gettext_free_exp__
  36. # define __gettextparse gettextparse__
  37. #endif
  38. #define YYLEX_PARAM &((struct parse_args *) arg)->cp
  39. #define YYPARSE_PARAM arg
  40. %}
  41. %pure_parser
  42. %expect 10
  43. %union {
  44. unsigned long int num;
  45. enum operator op;
  46. struct expression *exp;
  47. }
  48. %{
  49. /* Prototypes for local functions. */
  50. static struct expression *new_exp PARAMS ((int nargs, enum operator op,
  51. struct expression * const *args));
  52. static inline struct expression *new_exp_0 PARAMS ((enum operator op));
  53. static inline struct expression *new_exp_1 PARAMS ((enum operator op,
  54. struct expression *right));
  55. static struct expression *new_exp_2 PARAMS ((enum operator op,
  56. struct expression *left,
  57. struct expression *right));
  58. static inline struct expression *new_exp_3 PARAMS ((enum operator op,
  59. struct expression *bexp,
  60. struct expression *tbranch,
  61. struct expression *fbranch));
  62. static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
  63. static void yyerror PARAMS ((const char *str));
  64. /* Allocation of expressions. */
  65. static struct expression *
  66. new_exp (nargs, op, args)
  67. int nargs;
  68. enum operator op;
  69. struct expression * const *args;
  70. {
  71. int i;
  72. struct expression *newp;
  73. /* If any of the argument could not be malloc'ed, just return NULL. */
  74. for (i = nargs - 1; i >= 0; i--)
  75. if (args[i] == NULL)
  76. goto fail;
  77. /* Allocate a new expression. */
  78. newp = (struct expression *) malloc (sizeof (*newp));
  79. if (newp != NULL)
  80. {
  81. newp->nargs = nargs;
  82. newp->operation = op;
  83. for (i = nargs - 1; i >= 0; i--)
  84. newp->val.args[i] = args[i];
  85. return newp;
  86. }
  87. fail:
  88. for (i = nargs - 1; i >= 0; i--)
  89. FREE_EXPRESSION (args[i]);
  90. return NULL;
  91. }
  92. static inline struct expression *
  93. new_exp_0 (op)
  94. enum operator op;
  95. {
  96. return new_exp (0, op, NULL);
  97. }
  98. static inline struct expression *
  99. new_exp_1 (op, right)
  100. enum operator op;
  101. struct expression *right;
  102. {
  103. struct expression *args[1];
  104. args[0] = right;
  105. return new_exp (1, op, args);
  106. }
  107. static struct expression *
  108. new_exp_2 (op, left, right)
  109. enum operator op;
  110. struct expression *left;
  111. struct expression *right;
  112. {
  113. struct expression *args[2];
  114. args[0] = left;
  115. args[1] = right;
  116. return new_exp (2, op, args);
  117. }
  118. static inline struct expression *
  119. new_exp_3 (op, bexp, tbranch, fbranch)
  120. enum operator op;
  121. struct expression *bexp;
  122. struct expression *tbranch;
  123. struct expression *fbranch;
  124. {
  125. struct expression *args[3];
  126. args[0] = bexp;
  127. args[1] = tbranch;
  128. args[2] = fbranch;
  129. return new_exp (3, op, args);
  130. }
  131. %}
  132. /* This declares that all operators have the same associativity and the
  133. precedence order as in C. See [Harbison, Steele: C, A Reference Manual].
  134. There is no unary minus and no bitwise operators.
  135. Operators with the same syntactic behaviour have been merged into a single
  136. token, to save space in the array generated by bison. */
  137. %right '?' /* ? */
  138. %left '|' /* || */
  139. %left '&' /* && */
  140. %left EQUOP2 /* == != */
  141. %left CMPOP2 /* < > <= >= */
  142. %left ADDOP2 /* + - */
  143. %left MULOP2 /* * / % */
  144. %right '!' /* ! */
  145. %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
  146. %token <num> NUMBER
  147. %type <exp> exp
  148. %%
  149. start: exp
  150. {
  151. if ($1 == NULL)
  152. YYABORT;
  153. ((struct parse_args *) arg)->res = $1;
  154. }
  155. ;
  156. exp: exp '?' exp ':' exp
  157. {
  158. $$ = new_exp_3 (qmop, $1, $3, $5);
  159. }
  160. | exp '|' exp
  161. {
  162. $$ = new_exp_2 (lor, $1, $3);
  163. }
  164. | exp '&' exp
  165. {
  166. $$ = new_exp_2 (land, $1, $3);
  167. }
  168. | exp EQUOP2 exp
  169. {
  170. $$ = new_exp_2 ($2, $1, $3);
  171. }
  172. | exp CMPOP2 exp
  173. {
  174. $$ = new_exp_2 ($2, $1, $3);
  175. }
  176. | exp ADDOP2 exp
  177. {
  178. $$ = new_exp_2 ($2, $1, $3);
  179. }
  180. | exp MULOP2 exp
  181. {
  182. $$ = new_exp_2 ($2, $1, $3);
  183. }
  184. | '!' exp
  185. {
  186. $$ = new_exp_1 (lnot, $2);
  187. }
  188. | 'n'
  189. {
  190. $$ = new_exp_0 (var);
  191. }
  192. | NUMBER
  193. {
  194. if (($$ = new_exp_0 (num)) != NULL)
  195. $$->val.num = $1;
  196. }
  197. | '(' exp ')'
  198. {
  199. $$ = $2;
  200. }
  201. ;
  202. %%
  203. void
  204. internal_function
  205. FREE_EXPRESSION (exp)
  206. struct expression *exp;
  207. {
  208. if (exp == NULL)
  209. return;
  210. /* Handle the recursive case. */
  211. switch (exp->nargs)
  212. {
  213. case 3:
  214. FREE_EXPRESSION (exp->val.args[2]);
  215. /* FALLTHROUGH */
  216. case 2:
  217. FREE_EXPRESSION (exp->val.args[1]);
  218. /* FALLTHROUGH */
  219. case 1:
  220. FREE_EXPRESSION (exp->val.args[0]);
  221. /* FALLTHROUGH */
  222. default:
  223. break;
  224. }
  225. free (exp);
  226. }
  227. static int
  228. yylex (lval, pexp)
  229. YYSTYPE *lval;
  230. const char **pexp;
  231. {
  232. const char *exp = *pexp;
  233. int result;
  234. while (1)
  235. {
  236. if (exp[0] == '\0')
  237. {
  238. *pexp = exp;
  239. return YYEOF;
  240. }
  241. if (exp[0] != ' ' && exp[0] != '\t')
  242. break;
  243. ++exp;
  244. }
  245. result = *exp++;
  246. switch (result)
  247. {
  248. case '0': case '1': case '2': case '3': case '4':
  249. case '5': case '6': case '7': case '8': case '9':
  250. {
  251. unsigned long int n = result - '0';
  252. while (exp[0] >= '0' && exp[0] <= '9')
  253. {
  254. n *= 10;
  255. n += exp[0] - '0';
  256. ++exp;
  257. }
  258. lval->num = n;
  259. result = NUMBER;
  260. }
  261. break;
  262. case '=':
  263. if (exp[0] == '=')
  264. {
  265. ++exp;
  266. lval->op = equal;
  267. result = EQUOP2;
  268. }
  269. else
  270. result = YYERRCODE;
  271. break;
  272. case '!':
  273. if (exp[0] == '=')
  274. {
  275. ++exp;
  276. lval->op = not_equal;
  277. result = EQUOP2;
  278. }
  279. break;
  280. case '&':
  281. case '|':
  282. if (exp[0] == result)
  283. ++exp;
  284. else
  285. result = YYERRCODE;
  286. break;
  287. case '<':
  288. if (exp[0] == '=')
  289. {
  290. ++exp;
  291. lval->op = less_or_equal;
  292. }
  293. else
  294. lval->op = less_than;
  295. result = CMPOP2;
  296. break;
  297. case '>':
  298. if (exp[0] == '=')
  299. {
  300. ++exp;
  301. lval->op = greater_or_equal;
  302. }
  303. else
  304. lval->op = greater_than;
  305. result = CMPOP2;
  306. break;
  307. case '*':
  308. lval->op = mult;
  309. result = MULOP2;
  310. break;
  311. case '/':
  312. lval->op = divide;
  313. result = MULOP2;
  314. break;
  315. case '%':
  316. lval->op = module;
  317. result = MULOP2;
  318. break;
  319. case '+':
  320. lval->op = plus;
  321. result = ADDOP2;
  322. break;
  323. case '-':
  324. lval->op = minus;
  325. result = ADDOP2;
  326. break;
  327. case 'n':
  328. case '?':
  329. case ':':
  330. case '(':
  331. case ')':
  332. /* Nothing, just return the character. */
  333. break;
  334. case ';':
  335. case '\n':
  336. case '\0':
  337. /* Be safe and let the user call this function again. */
  338. --exp;
  339. result = YYEOF;
  340. break;
  341. default:
  342. result = YYERRCODE;
  343. #if YYDEBUG != 0
  344. --exp;
  345. #endif
  346. break;
  347. }
  348. *pexp = exp;
  349. return result;
  350. }
  351. static void
  352. yyerror (str)
  353. const char *str;
  354. {
  355. /* Do nothing. We don't print error messages here. */
  356. }