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.
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.
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.
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
28 int _get_day_num(const char* input);
29 int _get_year_num(Year_type ytype, const char* input1, const char* input2);
35 struct date_value date_val;
39 %token <string> ESC_DATE_GREG
40 %token <string> ESC_DATE_JULN
41 %token <string> ESC_DATE_HEBR
42 %token <string> ESC_DATE_FREN
43 %token <string> MOD_FROM
44 %token <string> MOD_TO
45 %token <string> MOD_BEF
46 %token <string> MOD_AFT
47 %token <string> MOD_BET
48 %token <string> MOD_AND
49 %token <string> MOD_ABT
50 %token <string> MOD_CAL
51 %token <string> MOD_EST
52 %token <string> MOD_INT
53 %token <string> MON_JAN
54 %token <string> MON_FEB
55 %token <string> MON_MAR
56 %token <string> MON_APR
57 %token <string> MON_MAY
58 %token <string> MON_JUN
59 %token <string> MON_JUL
60 %token <string> MON_AUG
61 %token <string> MON_SEP
62 %token <string> MON_OCT
63 %token <string> MON_NOV
64 %token <string> MON_DEC
65 %token <string> MON_TSH
66 %token <string> MON_CSH
67 %token <string> MON_KSL
68 %token <string> MON_TVT
69 %token <string> MON_SHV
70 %token <string> MON_ADR
71 %token <string> MON_ADS
72 %token <string> MON_NSN
73 %token <string> MON_IYR
74 %token <string> MON_SVN
75 %token <string> MON_TMZ
76 %token <string> MON_AAV
77 %token <string> MON_ELL
78 %token <string> MON_VEND
79 %token <string> MON_BRUM
80 %token <string> MON_FRIM
81 %token <string> MON_NIVO
82 %token <string> MON_PLUV
83 %token <string> MON_VENT
84 %token <string> MON_GERM
85 %token <string> MON_FLOR
86 %token <string> MON_PRAI
87 %token <string> MON_MESS
88 %token <string> MON_THER
89 %token <string> MON_FRUC
90 %token <string> MON_COMP
94 %token <string> NUMBER
96 %token <string> BADTOKEN
98 %type <date_val> date_value
99 %type <date_val> date_period
100 %type <date_val> date_range
101 %type <date_val> date_approx
102 %type <date_val> date_interpr
103 %type <string> date_phrase
108 date_value : date { make_date_value(DV_NO_MODIFIER,
114 | date_phrase { make_date_value(DV_PHRASE,
115 def_date, def_date, $1); }
118 /* If empty string: return empty string in 'phrase'
119 member as fallback */
120 /* Note: this can only happen in compatibility mode */
121 make_date_value(DV_PHRASE,
122 def_date, def_date, curr_line_value);
124 | error { /* On error: put entire string in 'phrase' member
126 make_date_value(DV_PHRASE,
127 def_date, def_date, curr_line_value);
131 date : ESC_DATE_GREG date_greg { copy_date(&$$, date_s);
132 $$.cal = CAL_GREGORIAN; }
133 | ESC_DATE_JULN date_juln { copy_date(&$$, date_s);
134 $$.cal = CAL_JULIAN; }
135 | ESC_DATE_HEBR date_hebr { copy_date(&$$, date_s);
136 $$.cal = CAL_HEBREW; }
137 | ESC_DATE_FREN date_fren { copy_date(&$$, date_s);
138 $$.cal = CAL_FRENCH_REV; }
139 | date_greg { copy_date(&$$, date_s);
140 $$.cal = CAL_GREGORIAN; }
143 date_period : MOD_FROM date { make_date_value(DV_FROM,
145 | MOD_TO date { make_date_value(DV_TO,
147 | MOD_FROM date { copy_date(&$<date>$, $2); }
149 { make_date_value(DV_FROM_TO, $<date>3, $5, ""); }
152 date_range : MOD_BEF date { make_date_value(DV_BEFORE,
154 | MOD_AFT date { make_date_value(DV_AFTER,
156 | MOD_BET date { copy_date(&$<date>$, $2); }
158 { make_date_value(DV_BETWEEN, $<date>3, $5, ""); }
161 date_approx : MOD_ABT date { make_date_value(DV_ABOUT,
163 | MOD_CAL date { make_date_value(DV_CALCULATED,
165 | MOD_EST date { make_date_value(DV_ESTIMATED,
169 date_interpr : MOD_INT date date_phrase
170 { make_date_value(DV_INTERPRETED, $2, def_date, $3); }
173 date_phrase : OPEN TEXT CLOSE { $$ = $2; }
176 date_greg : day month_greg year_greg
177 | month_greg year_greg
181 date_juln : day month_greg year
186 date_hebr : day month_hebr year
191 date_fren : day month_fren year
198 int d = _get_day_num($1);
200 strcpy(date_s.day_str, $1);
206 month_greg : MON_JAN { strcpy(date_s.month_str, $1);
208 | MON_FEB { strcpy(date_s.month_str, $1);
210 | MON_MAR { strcpy(date_s.month_str, $1);
212 | MON_APR { strcpy(date_s.month_str, $1);
214 | MON_MAY { strcpy(date_s.month_str, $1);
216 | MON_JUN { strcpy(date_s.month_str, $1);
218 | MON_JUL { strcpy(date_s.month_str, $1);
220 | MON_AUG { strcpy(date_s.month_str, $1);
222 | MON_SEP { strcpy(date_s.month_str, $1);
224 | MON_OCT { strcpy(date_s.month_str, $1);
226 | MON_NOV { strcpy(date_s.month_str, $1);
228 | MON_DEC { strcpy(date_s.month_str, $1);
232 month_hebr : MON_TSH { strcpy(date_s.month_str, $1);
234 | MON_CSH { strcpy(date_s.month_str, $1);
236 | MON_KSL { strcpy(date_s.month_str, $1);
238 | MON_TVT { strcpy(date_s.month_str, $1);
240 | MON_SHV { strcpy(date_s.month_str, $1);
242 | MON_ADR { strcpy(date_s.month_str, $1);
244 | MON_ADS { strcpy(date_s.month_str, $1);
246 | MON_NSN { strcpy(date_s.month_str, $1);
248 | MON_IYR { strcpy(date_s.month_str, $1);
250 | MON_SVN { strcpy(date_s.month_str, $1);
252 | MON_TMZ { strcpy(date_s.month_str, $1);
254 | MON_AAV { strcpy(date_s.month_str, $1);
256 | MON_ELL { strcpy(date_s.month_str, $1);
260 month_fren : MON_VEND { strcpy(date_s.month_str, $1);
262 | MON_BRUM { strcpy(date_s.month_str, $1);
264 | MON_FRIM { strcpy(date_s.month_str, $1);
266 | MON_NIVO { strcpy(date_s.month_str, $1);
268 | MON_PLUV { strcpy(date_s.month_str, $1);
270 | MON_VENT { strcpy(date_s.month_str, $1);
272 | MON_GERM { strcpy(date_s.month_str, $1);
274 | MON_FLOR { strcpy(date_s.month_str, $1);
276 | MON_PRAI { strcpy(date_s.month_str, $1);
278 | MON_MESS { strcpy(date_s.month_str, $1);
280 | MON_THER { strcpy(date_s.month_str, $1);
282 | MON_FRUC { strcpy(date_s.month_str, $1);
284 | MON_COMP { strcpy(date_s.month_str, $1);
289 { int y = _get_year_num(YEAR_SINGLE, $1, NULL);
291 strcpy(date_s.year_str, $1);
293 date_s.year_type = YEAR_SINGLE;
299 { int y = _get_year_num(YEAR_SINGLE, $1, NULL);
301 strcpy(date_s.year_str, $1);
303 date_s.year_type = YEAR_SINGLE;
306 | NUMBER SLASH NUMBER
307 { int y = _get_year_num(YEAR_DOUBLE, $1, $3);
309 sprintf(date_s.year_str, "%s/%s", $1, $3);
311 date_s.year_type = YEAR_DOUBLE;
318 int _get_day_num(const char* input)
320 if (strlen(input) <= MAX_DAY_LEN)
323 gedcom_date_error(_("Too many characters in day '%s'"), input);
328 int get_day_num(const char* input)
330 int token = get_date_token(input);
332 return _get_day_num(input);
334 gedcom_date_error(_("Not a valid day number: '%s'"), input);
340 { /* CAL_GREGORIAN */ MON_JAN,
341 /* CAL_JULIAN */ MON_JAN,
342 /* CAL_HEBREW */ MON_TSH,
343 /* CAL_FRENCH_REV */ MON_VEND
347 { /* CAL_GREGORIAN */ MON_DEC,
348 /* CAL_JULIAN */ MON_DEC,
349 /* CAL_HEBREW */ MON_ELL,
350 /* CAL_FRENCH_REV */ MON_COMP
353 int get_month_num(Calendar_type cal, const char* input)
355 int token = get_date_token(input);
356 if (token >= begin_month[cal] && token <= end_month[cal])
357 return token - begin_month[cal] + 1;
359 gedcom_date_error(_("Not a valid month for the given calendar: '%s'"),
365 int _get_year_num(Year_type ytype, const char* input1, const char* input2)
367 if (ytype == YEAR_SINGLE) {
368 if (strlen(input1) <= MAX_YEAR_LEN) {
372 gedcom_date_error(_("Too many characters in year '%s'"), input1);
377 if (strlen(input1) + strlen(input2) + 1 <= MAX_YEAR_LEN) {
378 return atoi(input1) + 1;
381 gedcom_date_error(_("Too many characters in year '%s/%s'"),
388 int get_year_num(const char* input, Year_type* ytype)
390 char *year1, *year2 = NULL;
391 int numtok = get_year_tokens(input, &year1, &year2);
393 *ytype = (numtok == 1 ? YEAR_SINGLE : YEAR_DOUBLE);
394 return _get_year_num (*ytype, year1, year2);
397 gedcom_date_error(_("Not a valid year: '%s'"), input);