plural.y 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. %{
  2. /* Expression parsing for plural form selection.
  3. Copyright (C) 2000-2026 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 Lesser General Public License as published by
  7. the Free Software Foundation; either version 2.1 of the License, or
  8. (at your option) 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 Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  15. /* For bison < 2.0, the bison generated parser uses alloca. AIX 3 forces us
  16. to put this declaration at the beginning of the file. The declaration in
  17. bison's skeleton file comes too late. This must come before <config.h>
  18. because <config.h> may include arbitrary system headers.
  19. This can go away once the AM_INTL_SUBDIR macro requires bison >= 2.0. */
  20. #if defined _AIX && !defined __GNUC__
  21. #pragma alloca
  22. #endif
  23. #ifdef HAVE_CONFIG_H
  24. # include <config.h>
  25. #endif
  26. #include <stddef.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include "plural-exp.h"
  30. /* The main function generated by the parser is called __gettextparse,
  31. but we want it to be called PLURAL_PARSE. */
  32. #ifndef _LIBC
  33. # define __gettextparse PLURAL_PARSE
  34. #endif
  35. /* Later we provide those prototypes. Without these macros, bison may
  36. generate its own prototypes with possible conflicts. */
  37. #define YYLEX_IS_DECLARED
  38. #define YYERROR_IS_DECLARED
  39. %}
  40. %parse-param {struct parse_args *arg}
  41. %lex-param {struct parse_args *arg}
  42. %define api.pure full
  43. %expect 7
  44. %union {
  45. unsigned long int num;
  46. enum expression_operator op;
  47. struct expression *exp;
  48. }
  49. %{
  50. /* Prototypes for local functions. */
  51. static int yylex (YYSTYPE *lval, struct parse_args *arg);
  52. static void yyerror (struct parse_args *arg, const char *str);
  53. /* Allocation of expressions. */
  54. static struct expression *
  55. new_exp (int nargs, enum expression_operator op,
  56. struct expression * const *args)
  57. {
  58. int i;
  59. struct expression *newp;
  60. /* If any of the argument could not be malloc'ed, just return NULL. */
  61. for (i = nargs - 1; i >= 0; i--)
  62. if (args[i] == NULL)
  63. goto fail;
  64. /* Allocate a new expression. */
  65. newp = (struct expression *) malloc (sizeof (*newp));
  66. if (newp != NULL)
  67. {
  68. newp->nargs = nargs;
  69. newp->operation = op;
  70. for (i = nargs - 1; i >= 0; i--)
  71. newp->val.args[i] = args[i];
  72. return newp;
  73. }
  74. fail:
  75. for (i = nargs - 1; i >= 0; i--)
  76. FREE_EXPRESSION (args[i]);
  77. return NULL;
  78. }
  79. static inline struct expression *
  80. new_exp_0 (enum expression_operator op)
  81. {
  82. return new_exp (0, op, NULL);
  83. }
  84. static inline struct expression *
  85. new_exp_1 (enum expression_operator op, struct expression *right)
  86. {
  87. struct expression *args[1];
  88. args[0] = right;
  89. return new_exp (1, op, args);
  90. }
  91. static struct expression *
  92. new_exp_2 (enum expression_operator op, struct expression *left,
  93. struct expression *right)
  94. {
  95. struct expression *args[2];
  96. args[0] = left;
  97. args[1] = right;
  98. return new_exp (2, op, args);
  99. }
  100. static inline struct expression *
  101. new_exp_3 (enum expression_operator op, struct expression *bexp,
  102. struct expression *tbranch, struct expression *fbranch)
  103. {
  104. struct expression *args[3];
  105. args[0] = bexp;
  106. args[1] = tbranch;
  107. args[2] = fbranch;
  108. return new_exp (3, op, args);
  109. }
  110. %}
  111. /* This declares that all operators have the same associativity and the
  112. precedence order as in C. See [Harbison, Steele: C, A Reference Manual].
  113. There is no unary minus and no bitwise operators.
  114. Operators with the same syntactic behaviour have been merged into a single
  115. token, to save space in the array generated by bison. */
  116. %right '?' /* ? */
  117. %left '|' /* || */
  118. %left '&' /* && */
  119. %left EQUOP2 /* == != */
  120. %left CMPOP2 /* < > <= >= */
  121. %left ADDOP2 /* + - */
  122. %left MULOP2 /* * / % */
  123. %right '!' /* ! */
  124. %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
  125. %token <num> NUMBER
  126. %type <exp> exp
  127. %%
  128. start: exp
  129. {
  130. if ($1 == NULL)
  131. YYABORT;
  132. arg->res = $1;
  133. }
  134. ;
  135. exp: exp '?' exp ':' exp
  136. {
  137. $$ = new_exp_3 (qmop, $1, $3, $5);
  138. }
  139. | exp '|' exp
  140. {
  141. $$ = new_exp_2 (lor, $1, $3);
  142. }
  143. | exp '&' exp
  144. {
  145. $$ = new_exp_2 (land, $1, $3);
  146. }
  147. | exp EQUOP2 exp
  148. {
  149. $$ = new_exp_2 ($2, $1, $3);
  150. }
  151. | exp CMPOP2 exp
  152. {
  153. $$ = new_exp_2 ($2, $1, $3);
  154. }
  155. | exp ADDOP2 exp
  156. {
  157. $$ = new_exp_2 ($2, $1, $3);
  158. }
  159. | exp MULOP2 exp
  160. {
  161. $$ = new_exp_2 ($2, $1, $3);
  162. }
  163. | '!' exp
  164. {
  165. $$ = new_exp_1 (lnot, $2);
  166. }
  167. | 'n'
  168. {
  169. $$ = new_exp_0 (var);
  170. }
  171. | NUMBER
  172. {
  173. if (($$ = new_exp_0 (num)) != NULL)
  174. $$->val.num = $1;
  175. }
  176. | '(' exp ')'
  177. {
  178. $$ = $2;
  179. }
  180. ;
  181. %%
  182. void
  183. FREE_EXPRESSION (struct expression *exp)
  184. {
  185. if (exp == NULL)
  186. return;
  187. /* Handle the recursive case. */
  188. switch (exp->nargs)
  189. {
  190. case 3:
  191. FREE_EXPRESSION (exp->val.args[2]);
  192. /* FALLTHROUGH */
  193. case 2:
  194. FREE_EXPRESSION (exp->val.args[1]);
  195. /* FALLTHROUGH */
  196. case 1:
  197. FREE_EXPRESSION (exp->val.args[0]);
  198. /* FALLTHROUGH */
  199. default:
  200. break;
  201. }
  202. free (exp);
  203. }
  204. static int
  205. yylex (YYSTYPE *lval, struct parse_args *arg)
  206. {
  207. const char *exp = arg->cp;
  208. int result;
  209. while (1)
  210. {
  211. if (exp[0] == '\0')
  212. {
  213. arg->cp = exp;
  214. return YYEOF;
  215. }
  216. if (exp[0] != ' ' && exp[0] != '\t')
  217. break;
  218. ++exp;
  219. }
  220. result = *exp++;
  221. switch (result)
  222. {
  223. case '0': case '1': case '2': case '3': case '4':
  224. case '5': case '6': case '7': case '8': case '9':
  225. {
  226. unsigned long int n = result - '0';
  227. while (exp[0] >= '0' && exp[0] <= '9')
  228. {
  229. n *= 10;
  230. n += exp[0] - '0';
  231. ++exp;
  232. }
  233. lval->num = n;
  234. result = NUMBER;
  235. }
  236. break;
  237. case '=':
  238. if (exp[0] == '=')
  239. {
  240. ++exp;
  241. lval->op = equal;
  242. result = EQUOP2;
  243. }
  244. else
  245. result = YYERRCODE;
  246. break;
  247. case '!':
  248. if (exp[0] == '=')
  249. {
  250. ++exp;
  251. lval->op = not_equal;
  252. result = EQUOP2;
  253. }
  254. break;
  255. case '&':
  256. case '|':
  257. if (exp[0] == result)
  258. ++exp;
  259. else
  260. result = YYERRCODE;
  261. break;
  262. case '<':
  263. if (exp[0] == '=')
  264. {
  265. ++exp;
  266. lval->op = less_or_equal;
  267. }
  268. else
  269. lval->op = less_than;
  270. result = CMPOP2;
  271. break;
  272. case '>':
  273. if (exp[0] == '=')
  274. {
  275. ++exp;
  276. lval->op = greater_or_equal;
  277. }
  278. else
  279. lval->op = greater_than;
  280. result = CMPOP2;
  281. break;
  282. case '*':
  283. lval->op = mult;
  284. result = MULOP2;
  285. break;
  286. case '/':
  287. lval->op = divide;
  288. result = MULOP2;
  289. break;
  290. case '%':
  291. lval->op = module;
  292. result = MULOP2;
  293. break;
  294. case '+':
  295. lval->op = plus;
  296. result = ADDOP2;
  297. break;
  298. case '-':
  299. lval->op = minus;
  300. result = ADDOP2;
  301. break;
  302. case 'n':
  303. case '?':
  304. case ':':
  305. case '(':
  306. case ')':
  307. /* Nothing, just return the character. */
  308. break;
  309. case ';':
  310. case '\n':
  311. case '\0':
  312. /* Be safe and let the user call this function again. */
  313. --exp;
  314. result = YYEOF;
  315. break;
  316. default:
  317. result = YYERRCODE;
  318. #if YYDEBUG != 0
  319. --exp;
  320. #endif
  321. break;
  322. }
  323. arg->cp = exp;
  324. return result;
  325. }
  326. static void
  327. yyerror (struct parse_args *arg, const char *str)
  328. {
  329. /* Do nothing. We don't print error messages here. */
  330. }