Parsing of dates via a separate yacc parser.
[gedcom-parse.git] / gedcom / gedcom_date.y
1 /* Parser for Gedcom dates.
2    Copyright (C) 2001 The Genes Development Team
3    This file is part of the Gedcom parser library.
4    Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2001.
5
6    The Gedcom parser library is free software; you can redistribute it
7    and/or modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The Gedcom parser library is distributed in the hope that it will be
12    useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the Gedcom parser library; if not, write to the
18    Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 /* $Id$ */
22 /* $Name$ */
23
24 %{
25 #include <stdlib.h>
26 #include "date.h"
27 %}
28
29 %union {
30   char *string;
31   struct date_value date_val;
32   struct date date;
33 }
34
35 %token <string> ESC_DATE_GREG
36 %token <string> ESC_DATE_JULN
37 %token <string> ESC_DATE_HEBR
38 %token <string> ESC_DATE_FREN
39 %token <string> MOD_FROM
40 %token <string> MOD_TO
41 %token <string> MOD_BEF
42 %token <string> MOD_AFT
43 %token <string> MOD_BET
44 %token <string> MOD_AND
45 %token <string> MOD_ABT
46 %token <string> MOD_CAL
47 %token <string> MOD_EST
48 %token <string> MOD_INT
49 %token <string> MON_JAN
50 %token <string> MON_FEB
51 %token <string> MON_MAR
52 %token <string> MON_APR
53 %token <string> MON_MAY
54 %token <string> MON_JUN
55 %token <string> MON_JUL
56 %token <string> MON_AUG
57 %token <string> MON_SEP
58 %token <string> MON_OCT
59 %token <string> MON_NOV
60 %token <string> MON_DEC
61 %token <string> MON_TSH
62 %token <string> MON_CSH
63 %token <string> MON_KSL
64 %token <string> MON_TVT
65 %token <string> MON_SHV
66 %token <string> MON_ADR
67 %token <string> MON_ADS
68 %token <string> MON_NSN
69 %token <string> MON_IYR
70 %token <string> MON_SVN
71 %token <string> MON_TMZ
72 %token <string> MON_AAV
73 %token <string> MON_ELL
74 %token <string> MON_VEND
75 %token <string> MON_BRUM
76 %token <string> MON_FRIM
77 %token <string> MON_NIVO
78 %token <string> MON_PLUV
79 %token <string> MON_VENT
80 %token <string> MON_GERM
81 %token <string> MON_FLOR
82 %token <string> MON_PRAI
83 %token <string> MON_MESS
84 %token <string> MON_THER
85 %token <string> MON_FRUC
86 %token <string> MON_COMP
87 %token <string> OPEN
88 %token <string> CLOSE
89 %token <string> TEXT
90 %token <string> NUMBER
91 %token <string> SLASH
92 %token <string> BADTOKEN
93
94 %type <date_val> date_value
95 %type <date_val> date_period
96 %type <date_val> date_range
97 %type <date_val> date_approx
98 %type <date_val> date_interpr
99 %type <string> date_phrase
100 %type <date> date
101
102 %%
103
104 date_value   : date           { make_date_value(DV_NO_MODIFIER,
105                                                 $1, def_date, ""); }
106              | date_period    
107              | date_range
108              | date_approx
109              | date_interpr
110              | date_phrase    { make_date_value(DV_PHRASE,
111                                                 def_date, def_date, $1); }
112              ;
113
114 date         : ESC_DATE_GREG date_greg { copy_date(&$$, date_s);
115                                          $$.cal = CAL_GREGORIAN; }
116              | ESC_DATE_JULN date_juln { copy_date(&$$, date_s);
117                                          $$.cal = CAL_JULIAN;  }
118              | ESC_DATE_HEBR date_hebr { copy_date(&$$, date_s);
119                                          $$.cal = CAL_HEBREW;  }
120              | ESC_DATE_FREN date_fren { copy_date(&$$, date_s);
121                                          $$.cal = CAL_FRENCH_REV;  }
122              | date_greg               { copy_date(&$$, date_s);
123                                          $$.cal = CAL_GREGORIAN;  }
124              ;
125
126 date_period  : MOD_FROM date   { make_date_value(DV_FROM,
127                                                  $2, def_date, ""); }
128              | MOD_TO date     { make_date_value(DV_TO,
129                                                  $2, def_date, ""); }
130              | MOD_FROM date   { copy_date(&$<date>$, $2); }
131                MOD_TO date
132                       { make_date_value(DV_FROM_TO, $<date>3, $5, ""); }
133              ;
134
135 date_range   : MOD_BEF date    { make_date_value(DV_BEFORE,
136                                                  $2, def_date, ""); }
137              | MOD_AFT date    { make_date_value(DV_AFTER,
138                                                  $2, def_date, ""); }
139              | MOD_BET date    { copy_date(&$<date>$, $2); }
140                MOD_AND date
141                       { make_date_value(DV_BETWEEN, $<date>3, $5, ""); }
142              ;
143
144 date_approx  : MOD_ABT date    { make_date_value(DV_ABOUT,
145                                                  $2, def_date, ""); }
146              | MOD_CAL date    { make_date_value(DV_CALCULATED,
147                                                  $2, def_date, ""); }
148              | MOD_EST date    { make_date_value(DV_ESTIMATED,
149                                                  $2, def_date, ""); }
150              ;
151
152 date_interpr : MOD_INT date date_phrase
153                  { make_date_value(DV_INTERPRETED, $2, def_date, $3); }
154              ;
155
156 date_phrase  : OPEN TEXT CLOSE { $$ = $2; }
157              ;
158
159 date_greg    : day month_greg year_greg
160              | month_greg year_greg
161              | year_greg
162              ;
163
164 date_juln    : day month_greg year
165              | month_greg year
166              | year
167              ;
168
169 date_hebr    : day month_hebr year
170              | month_hebr year
171              | year
172              ;
173
174 date_fren    : day month_fren year
175              | month_fren year
176              | year
177              ;
178
179 day          : NUMBER
180                {
181                  if (strlen($1) <= MAX_DAY_LEN) {
182                    strcpy(date_s.day_str, $1);
183                    date_s.day = atoi($1);
184                  }
185                  else {
186                    gedcom_date_error(_("Too many characters in day '%s'"),
187                                      $1); 
188                  }
189                }
190              ;
191
192 month_greg   : MON_JAN { strcpy(date_s.month_str, $1);
193                          date_s.month = 1; }
194              | MON_FEB { strcpy(date_s.month_str, $1);
195                          date_s.month = 2; }
196              | MON_MAR { strcpy(date_s.month_str, $1);
197                          date_s.month = 3; }
198              | MON_APR { strcpy(date_s.month_str, $1);
199                          date_s.month = 4; }
200              | MON_MAY { strcpy(date_s.month_str, $1);
201                          date_s.month = 5; }
202              | MON_JUN { strcpy(date_s.month_str, $1);
203                          date_s.month = 6; }
204              | MON_JUL { strcpy(date_s.month_str, $1);
205                          date_s.month = 7; }
206              | MON_AUG { strcpy(date_s.month_str, $1);
207                          date_s.month = 8; }
208              | MON_SEP { strcpy(date_s.month_str, $1);
209                          date_s.month = 9; }
210              | MON_OCT { strcpy(date_s.month_str, $1);
211                          date_s.month = 10; }
212              | MON_NOV { strcpy(date_s.month_str, $1);
213                          date_s.month = 11; }
214              | MON_DEC { strcpy(date_s.month_str, $1);
215                          date_s.month = 12; }
216              ;
217
218 month_hebr   : MON_TSH { strcpy(date_s.month_str, $1);
219                          date_s.month = 1; }
220              | MON_CSH { strcpy(date_s.month_str, $1);
221                          date_s.month = 2; }
222              | MON_KSL { strcpy(date_s.month_str, $1);
223                          date_s.month = 3; }
224              | MON_TVT { strcpy(date_s.month_str, $1);
225                          date_s.month = 4; }
226              | MON_SHV { strcpy(date_s.month_str, $1);
227                          date_s.month = 5; }
228              | MON_ADR { strcpy(date_s.month_str, $1);
229                          date_s.month = 6; }
230              | MON_ADS { strcpy(date_s.month_str, $1);
231                          date_s.month = 7; }
232              | MON_NSN { strcpy(date_s.month_str, $1);
233                          date_s.month = 8; }
234              | MON_IYR { strcpy(date_s.month_str, $1);
235                          date_s.month = 9; }
236              | MON_SVN { strcpy(date_s.month_str, $1);
237                          date_s.month = 10; }
238              | MON_TMZ { strcpy(date_s.month_str, $1);
239                          date_s.month = 11; }
240              | MON_AAV { strcpy(date_s.month_str, $1);
241                          date_s.month = 12; }
242              | MON_ELL { strcpy(date_s.month_str, $1);
243                          date_s.month = 13; }
244              ;
245
246 month_fren   : MON_VEND { strcpy(date_s.month_str, $1);
247                          date_s.month = 1; }
248              | MON_BRUM { strcpy(date_s.month_str, $1);
249                          date_s.month = 2; }
250              | MON_FRIM { strcpy(date_s.month_str, $1);
251                          date_s.month = 3; }
252              | MON_NIVO { strcpy(date_s.month_str, $1);
253                          date_s.month = 4; }
254              | MON_PLUV { strcpy(date_s.month_str, $1);
255                          date_s.month = 5; }
256              | MON_VENT { strcpy(date_s.month_str, $1);
257                          date_s.month = 6; }
258              | MON_GERM { strcpy(date_s.month_str, $1);
259                          date_s.month = 7; }
260              | MON_FLOR { strcpy(date_s.month_str, $1);
261                          date_s.month = 8; }
262              | MON_PRAI { strcpy(date_s.month_str, $1);
263                          date_s.month = 9; }
264              | MON_MESS { strcpy(date_s.month_str, $1);
265                          date_s.month = 10; }
266              | MON_THER { strcpy(date_s.month_str, $1);
267                          date_s.month = 11; }
268              | MON_FRUC { strcpy(date_s.month_str, $1);
269                          date_s.month = 12; }
270              | MON_COMP { strcpy(date_s.month_str, $1);
271                          date_s.month = 13; }
272              ;
273
274 year         : NUMBER
275                  { if (strlen($1) <= MAX_YEAR_LEN) {
276                      strcpy(date_s.year_str, $1);
277                      date_s.year = atoi($1);
278                      date_s.year_type = YEAR_SINGLE;
279                    }
280                    else {
281                      gedcom_date_error(_("Too many characters in year '%s'"),
282                                      $1); 
283                    }
284                  }
285              ;
286
287 year_greg    : NUMBER
288                  { if (strlen($1) <= MAX_YEAR_LEN) {
289                      strcpy(date_s.year_str, $1);
290                      date_s.year = atoi($1);
291                      date_s.year_type = YEAR_SINGLE;
292                    }
293                    else {
294                      gedcom_date_error(_("Too many characters in year '%s'"),
295                                      $1); 
296                    }
297                  }
298              | NUMBER SLASH NUMBER
299                  { if (strlen($1) + strlen($3) + 1 <= MAX_YEAR_LEN) {
300                      sprintf(date_s.year_str, "%s/%s", $1, $3);
301                      date_s.year = atoi($1) + 1;
302                      date_s.year_type = YEAR_DOUBLE;
303                    }
304                    else {
305                      gedcom_date_error(_("Too many characters in year '%s/%s'"),
306                                      $1, $3); 
307                    }
308                  
309                  }
310              ;
311
312 %%