Warning, /libraries/kopeninghours/src/lib/openinghoursparser.y is written in an unsupported language. File is not indexed.
0001 %{ 0002 /* 0003 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org> 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "openinghours_p.h" 0008 #include "openinghoursparser_p.h" // generated 0009 #include "openinghoursscanner_p.h" // generated 0010 #include "logging.h" 0011 0012 using namespace KOpeningHours; 0013 0014 void yyerror(YYLTYPE *loc, OpeningHoursPrivate *parser, yyscan_t scanner, char const* msg) 0015 { 0016 Q_UNUSED(scanner); 0017 qCDebug(Log) << "PARSER ERROR:" << msg << "at position" << loc->first_column; 0018 parser->m_error = OpeningHours::SyntaxError; 0019 } 0020 0021 static void initSelectors(Selectors &sels) 0022 { 0023 sels.timeSelector = nullptr; 0024 sels.weekdaySelector = nullptr; 0025 sels.weekSelector = nullptr; 0026 sels.monthdaySelector = nullptr; 0027 sels.yearSelector = nullptr; 0028 sels.wideRangeSelectorComment.str = nullptr; 0029 sels.wideRangeSelectorComment.len = 0; 0030 sels.seen_24_7 = false; 0031 sels.colonAfterWideRangeSelector = false; 0032 } 0033 0034 static void applySelectors(const Selectors &sels, Rule *rule) 0035 { 0036 rule->m_timeSelector.reset(sels.timeSelector); 0037 rule->m_weekdaySelector.reset(sels.weekdaySelector); 0038 rule->m_weekSelector.reset(sels.weekSelector); 0039 rule->m_monthdaySelector.reset(sels.monthdaySelector); 0040 rule->m_yearSelector.reset(sels.yearSelector); 0041 rule->m_seen_24_7 = sels.seen_24_7; 0042 rule->m_colonAfterWideRangeSelector = sels.colonAfterWideRangeSelector; 0043 rule->m_wideRangeSelectorComment = QString::fromUtf8(sels.wideRangeSelectorComment.str, sels.wideRangeSelectorComment.len); 0044 } 0045 0046 static bool extendMonthdaySelector(MonthdayRange *monthdaySelector, int beginDay, int endDay) 0047 { 0048 const auto prevSelector = lastSelector(monthdaySelector); 0049 if (prevSelector->begin.year == prevSelector->end.year 0050 && prevSelector->begin.month == prevSelector->end.month) 0051 { 0052 auto sel = new MonthdayRange; 0053 sel->begin = sel->end = prevSelector->end; 0054 sel->begin.day = beginDay; 0055 sel->end.day = endDay; 0056 appendSelector(prevSelector, sel); 0057 return true; 0058 } 0059 return false; 0060 } 0061 0062 %} 0063 0064 %code requires { 0065 0066 #include "openinghours_p.h" 0067 #include "interval.h" 0068 0069 using namespace KOpeningHours; 0070 0071 struct StringRef { 0072 const char *str; 0073 int len; 0074 }; 0075 0076 struct Selectors { 0077 Timespan *timeSelector; 0078 WeekdayRange *weekdaySelector; 0079 Week *weekSelector; 0080 MonthdayRange *monthdaySelector; 0081 YearRange *yearSelector; 0082 StringRef wideRangeSelectorComment; 0083 bool seen_24_7; 0084 bool colonAfterWideRangeSelector; 0085 }; 0086 0087 #ifndef YY_TYPEDEF_YY_SCANNER_T 0088 #define YY_TYPEDEF_YY_SCANNER_T 0089 typedef void* yyscan_t; 0090 #endif 0091 0092 } 0093 0094 %define api.pure 0095 %define parse.error verbose 0096 0097 %locations 0098 %lex-param { yyscan_t scanner } 0099 %parse-param { KOpeningHours::OpeningHoursPrivate *parser } 0100 %parse-param { yyscan_t scanner } 0101 0102 %glr-parser 0103 %expect 18 0104 // (1) is for "T_YEAR T_COMMA T_YEAR T_MONTH", which is syntactically invalid anyway 0105 // (2) and (3) are for overlaps between weekday/holiday sequences and holiday-on-weekday selectors, which are also invalid 0106 %expect-rr 3 0107 0108 %union { 0109 int num; 0110 StringRef strRef; 0111 State state; 0112 Rule *rule; 0113 Time time; 0114 Selectors selectors; 0115 Timespan *timespan; 0116 NthEntry nthEntry; 0117 NthSequence *nthSequence; 0118 WeekdayRange *weekdayRange; 0119 Week *week; 0120 Date date; 0121 MonthdayRange *monthdayRange; 0122 DateOffset dateOffset; 0123 YearRange *yearRange; 0124 } 0125 0126 %token T_NORMAL_RULE_SEPARATOR 0127 %token T_ADDITIONAL_RULE_SEPARATOR 0128 %token T_FALLBACK_SEPARATOR 0129 0130 %token <state> T_STATE 0131 0132 %token T_24_7 0133 %token <num> T_YEAR 0134 0135 %token T_PLUS 0136 %token T_MINUS 0137 %token T_SLASH 0138 %token T_COLON 0139 %token T_COMMA 0140 0141 %token T_ALT_TIME_SEP 0142 %token T_ALT_TIME_SEP_OR_SUFFIX 0143 %token <num> T_ALT_TIME_AM 0144 %token <num> T_ALT_TIME_PM 0145 %token <num> T_4DIGIT_TIME 0146 0147 %token T_ALT_RANGE_SEP 0148 0149 %token <time> T_EVENT 0150 0151 %token T_LBRACKET 0152 %token T_RBRACKET 0153 %token T_LPAREN 0154 %token T_RPAREN 0155 0156 %token T_PH 0157 %token T_SH 0158 0159 %token T_KEYWORD_DAY 0160 %token T_KEYWORD_WEEK 0161 0162 %token T_EASTER 0163 %token T_WHITSUN 0164 0165 %token <num> T_WEEKDAY 0166 %token <num> T_MONTH 0167 %token <num> T_INTEGER 0168 0169 %token <strRef> T_COMMENT 0170 0171 %token T_INVALID 0172 0173 %type <rule> Rule 0174 %type <selectors> SelectorSequence 0175 %type <selectors> WideRangeSelector 0176 %type <selectors> SmallRangeSelector 0177 %type <selectors> TimeSelector 0178 %type <selectors> WeekdaySelector 0179 %type <selectors> WeekSelector 0180 %type <selectors> MonthdaySelector 0181 %type <selectors> YearSelector 0182 %type <selectors> YearSelectorCombined 0183 %type <timespan> Timespan 0184 %type <time> Time 0185 %type <time> VariableTime 0186 %type <time> ExtendedHourMinute 0187 %type <weekdayRange> HolidayAndWeekdaySequence 0188 %type <weekdayRange> HolidayAndWeekday 0189 %type <weekdayRange> HolidayOrWeekdaySequence 0190 %type <weekdayRange> WeekdaySequence 0191 %type <weekdayRange> WeekdayRange 0192 %type <weekdayRange> HolidaySequence 0193 %type <weekdayRange> Holiday 0194 %type <nthSequence> NthSequence 0195 %type <nthEntry> NthEntry 0196 %type <num> DayOffset 0197 %type <dateOffset> DateOffset 0198 %type <week> Week 0199 %type <date> DateFrom 0200 %type <date> DateTo 0201 %type <date> VariableDate 0202 %type <monthdayRange> MonthdayRange 0203 %type <monthdayRange> MonthdayRangeAdditional 0204 %type <dateOffset> AltMonthdayOffset 0205 %type <yearRange> YearRange 0206 %type <yearRange> YearRangeStandalone 0207 0208 %destructor { delete $$; } <rule> 0209 %destructor { 0210 delete $$.timeSelector; 0211 delete $$.weekdaySelector; 0212 delete $$.weekSelector; 0213 delete $$.monthdaySelector; 0214 delete $$.yearSelector; 0215 } <selectors> 0216 %destructor { delete $$; } <timespan> 0217 %destructor { delete $$; } <nthSequence> 0218 %destructor { delete $$; } <weekdayRange> 0219 %destructor { delete $$; } <week> 0220 %destructor { delete $$; } <monthdayRange> 0221 %destructor { delete $$; } <yearRange> 0222 0223 // resolve SR conflict between the YearSelector and MonthdaySelector on T_YEAR T_MONTH 0224 %nonassoc T_YEAR 0225 %nonassoc T_MONTH 0226 0227 %verbose 0228 0229 %% 0230 // see https://wiki.openstreetmap.org/wiki/Key:opening_hours/specification 0231 0232 Ruleset: 0233 Rule[R] { parser->addRule($R); } 0234 | Ruleset T_NORMAL_RULE_SEPARATOR Rule[R] { parser->addRule($R); } 0235 | Ruleset T_ADDITIONAL_RULE_SEPARATOR Rule[R] { 0236 $R->m_ruleType = Rule::AdditionalRule; 0237 parser->addRule($R); 0238 } 0239 | Ruleset T_FALLBACK_SEPARATOR Rule[R] { 0240 $R->m_ruleType = Rule::FallbackRule; 0241 parser->addRule($R); 0242 } 0243 | Ruleset T_SLASH error { 0244 if (!parser->isRecovering()) { 0245 parser->restartFrom(@3.first_column, Rule::NormalRule); 0246 parser->m_ruleSeparatorRecovery = true; 0247 yyerrok; 0248 } else { 0249 YYERROR; 0250 } 0251 } 0252 | Ruleset error { 0253 if (!parser->isRecovering()) { 0254 parser->restartFrom(@2.first_column, Rule::GuessRuleType); 0255 parser->m_ruleSeparatorRecovery = true; 0256 yyerrok; 0257 } else { 0258 YYERROR; 0259 } 0260 } 0261 ; 0262 0263 Rule: 0264 SelectorSequence[S] { 0265 $$ = new Rule; 0266 applySelectors($S, $$); 0267 } 0268 | SelectorSequence[S] T_COMMENT[C] { 0269 $$ = new Rule; 0270 $$->setComment($C.str, $C.len); 0271 applySelectors($S, $$); 0272 } 0273 | SelectorSequence[S] T_STATE[T] { 0274 $$ = new Rule; 0275 $$->setState($T); 0276 applySelectors($S, $$); 0277 } 0278 | SelectorSequence[S] T_STATE[T] T_COMMENT[C] { 0279 $$ = new Rule; 0280 $$->setComment($C.str, $C.len); 0281 $$->setState($T); 0282 applySelectors($S, $$); 0283 } 0284 | T_COMMENT[C] { 0285 $$ = new Rule; 0286 $$->setComment($C.str, $C.len); 0287 } 0288 | T_STATE[T] { 0289 $$ = new Rule; 0290 $$->setState($T); 0291 } 0292 | T_STATE[T] T_COMMENT[C] { 0293 $$ = new Rule; 0294 $$->setComment($C.str, $C.len); 0295 $$->setState($T); 0296 } 0297 ; 0298 0299 SelectorSequence: 0300 T_24_7 { initSelectors($$); $$.seen_24_7 = true; } 0301 | SmallRangeSelector[S] { $$ = $S; } 0302 | WideRangeSelector[W] { $$ = $W; } 0303 | WideRangeSelector[W] T_COLON { 0304 $$ = $W; 0305 $$.colonAfterWideRangeSelector = true; 0306 } 0307 | WideRangeSelector[W] SmallRangeSelector[S] { 0308 $$.timeSelector = $S.timeSelector; 0309 $$.weekdaySelector = $S.weekdaySelector; 0310 $$.weekSelector = $W.weekSelector; 0311 } 0312 | WideRangeSelector[W] T_COLON SmallRangeSelector[S] { 0313 $$.timeSelector = $S.timeSelector; 0314 $$.weekdaySelector = $S.weekdaySelector; 0315 $$.weekSelector = $W.weekSelector; 0316 $$.colonAfterWideRangeSelector = true; 0317 } 0318 ; 0319 0320 WideRangeSelector: 0321 YearSelector[Y] { $$ = $Y; } 0322 | MonthdaySelector[M] { $$ = $M; } 0323 | WeekSelector[W] { $$ = $W; } 0324 | YearSelector[Y] MonthdaySelector[M] { 0325 $$.yearSelector = $Y.yearSelector; 0326 $$.monthdaySelector = $M.monthdaySelector; 0327 } 0328 | YearSelector[Y] WeekSelector[W] { 0329 $$.yearSelector = $Y.yearSelector; 0330 $$.weekSelector = $W.weekSelector; 0331 } 0332 | MonthdaySelector[M] WeekSelector[W] { 0333 $$.monthdaySelector = $M.monthdaySelector; 0334 $$.weekSelector = $W.weekSelector; 0335 } 0336 | YearSelector[Y] MonthdaySelector[M] WeekSelector[W] { 0337 $$.yearSelector = $Y.yearSelector; 0338 $$.monthdaySelector = $M.monthdaySelector; 0339 $$.weekSelector = $W.weekSelector; 0340 } 0341 | T_COMMENT[C] T_COLON { 0342 initSelectors($$); 0343 $$.wideRangeSelectorComment = $C; 0344 $$.colonAfterWideRangeSelector = true; 0345 } 0346 ; 0347 0348 SmallRangeSelector: 0349 TimeSelector[T] { $$ = $T; } 0350 | WeekdaySelector[W] { $$ = $W; } 0351 | WeekdaySelector[W] T_COLON { $$ = $W; } 0352 | WeekdaySelector[W] TimeSelector[T] { 0353 $$.timeSelector = $T.timeSelector; 0354 $$.weekdaySelector = $W.weekdaySelector; 0355 } 0356 | WeekdaySelector[W] T_COLON TimeSelector[T] { 0357 $$.timeSelector = $T.timeSelector; 0358 $$.weekdaySelector = $W.weekdaySelector; 0359 } 0360 ; 0361 0362 // Time selector 0363 TimeSelector: 0364 Timespan[T] { 0365 initSelectors($$); 0366 $$.timeSelector = $T; 0367 } 0368 | TimeSelector[T1] T_COMMA Timespan[T2] { 0369 $$ = $T1; 0370 appendSelector($$.timeSelector, $T2); 0371 } 0372 | TimeSelector[T] T_COMMA error { 0373 $$ = $T; 0374 parser->restartFrom(@3.first_column, Rule::AdditionalRule); 0375 yyerrok; 0376 } 0377 | TimeSelector[T] T_SLASH Time[E] error { /* wrong use of slash as a timespan separator */ 0378 $$ = $T; 0379 parser->restartFrom(@E.first_column, Rule::AdditionalRule); 0380 yyerrok; 0381 } 0382 ; 0383 0384 Timespan: 0385 Time[T] { 0386 $$ = new Timespan; 0387 $$->begin = $$->end = $T; 0388 $$->pointInTime = true; 0389 } 0390 | Time[T] T_PLUS { 0391 $$ = new Timespan; 0392 $$->begin = $$->end = $T; 0393 $$->pointInTime = true; 0394 $$->openEnd = true; 0395 } 0396 | Time[T1] RangeSeparator Time[T2] { 0397 $$ = new Timespan; 0398 $$->begin = $T1; 0399 $$->end = $T2; 0400 } 0401 | Time[T1] RangeSeparator Time[T2] T_PLUS { 0402 $$ = new Timespan; 0403 $$->begin = $T1; 0404 $$->end = $T2; 0405 $$->openEnd = true; 0406 } 0407 | Time[T1] RangeSeparator Time[T2] T_SLASH T_INTEGER[I] { 0408 $$ = new Timespan; 0409 $$->begin = $T1; 0410 $$->end = $T2; 0411 $$->interval = $I; 0412 } 0413 | Time[T1] RangeSeparator Time[T2] T_SLASH ExtendedHourMinute[I] { 0414 $$ = new Timespan; 0415 $$->begin = $T1; 0416 $$->end = $T2; 0417 $$->interval = $I.hour * 60 + $I.minute; 0418 } 0419 ; 0420 0421 Time: 0422 ExtendedHourMinute[T] { $$ = $T; } 0423 | VariableTime[T] { $$ = $T; } 0424 ; 0425 0426 VariableTime: 0427 T_EVENT[E] { $$ = $E; } 0428 | T_LPAREN T_EVENT[E] T_PLUS ExtendedHourMinute[O] T_RPAREN { 0429 $$ = $E; 0430 $$.hour = $O.hour; 0431 $$.minute = $O.minute; 0432 } 0433 | T_LPAREN T_EVENT[E] T_MINUS ExtendedHourMinute[O] T_RPAREN { 0434 $$ = $E; 0435 $$.hour = -$O.hour; 0436 $$.minute = -$O.minute; 0437 } 0438 ; 0439 0440 // Weekday selector 0441 WeekdaySelector: 0442 HolidayOrWeekdaySequence[S] { 0443 initSelectors($$); 0444 $$.weekdaySelector = $S; 0445 } 0446 | HolidayAndWeekdaySequence[S] { 0447 initSelectors($$); 0448 $$.weekdaySelector = $S; 0449 } 0450 ; 0451 0452 HolidayAndWeekdaySequence: 0453 HolidayAndWeekday[HW] { $$ = $HW; } 0454 | HolidayAndWeekdaySequence[HW1] T_COMMA HolidayAndWeekday[HW2] { 0455 $$ = $HW1; 0456 appendSelector($$, $HW2); 0457 } 0458 ; 0459 0460 HolidayAndWeekday: 0461 HolidaySequence[H] WeekdaySequence[W] { 0462 $$ = new WeekdayRange; 0463 $$->lhsAndSelector.reset($H); 0464 $$->rhsAndSelector.reset($W); 0465 } 0466 | WeekdaySequence[W] HolidaySequence[H] { // wrong order according to the specification 0467 $$ = new WeekdayRange; 0468 $$->lhsAndSelector.reset($H); 0469 $$->rhsAndSelector.reset($W); 0470 } 0471 ; 0472 0473 HolidayOrWeekdaySequence: 0474 WeekdayRange[W] { $$ = $W; } 0475 | Holiday[H] { $$ = $H; } 0476 | HolidayOrWeekdaySequence[S] T_COMMA WeekdayRange[W] { 0477 $$ = $S; 0478 appendSelector($$, $W); 0479 } 0480 | HolidayOrWeekdaySequence[S] T_COMMA Holiday[H] { 0481 $$ = $S; 0482 appendSelector($$, $H); 0483 } 0484 ; 0485 0486 WeekdaySequence: 0487 WeekdayRange[W] { $$ = $W; } 0488 | WeekdaySequence[S] T_COMMA WeekdayRange[W] { 0489 $$ = $S; 0490 appendSelector($$, $W); 0491 } 0492 ; 0493 0494 WeekdayRange: 0495 T_WEEKDAY[D] { 0496 $$ = new WeekdayRange; 0497 $$->beginDay = $D; 0498 $$->endDay = $D; 0499 } 0500 | T_WEEKDAY[D1] RangeSeparator T_WEEKDAY[D2] { 0501 $$ = new WeekdayRange; 0502 $$->beginDay = $D1; 0503 $$->endDay = $D2; 0504 } 0505 | T_WEEKDAY[D] T_LBRACKET NthSequence[N] T_RBRACKET { 0506 $$ = new WeekdayRange; 0507 $$->beginDay = $$->endDay = $D; 0508 $$->nthSequence.reset($N); 0509 } 0510 | T_WEEKDAY[D] T_LBRACKET NthSequence[N] T_RBRACKET DayOffset[O] { 0511 $$ = new WeekdayRange; 0512 $$->beginDay = $$->endDay = $D; 0513 $$->nthSequence.reset($N); 0514 $$->offset = $O; 0515 } 0516 ; 0517 0518 HolidaySequence: 0519 Holiday[H] { $$ = $H; } 0520 | HolidaySequence[S] T_COMMA Holiday[H] { $$ = $S; appendSelector($$, $H); } 0521 ; 0522 0523 Holiday: 0524 T_PH { 0525 $$ = new WeekdayRange; 0526 $$->holiday = WeekdayRange::PublicHoliday; 0527 } 0528 | T_PH DayOffset[O] { 0529 $$ = new WeekdayRange; 0530 $$->holiday = WeekdayRange::PublicHoliday; 0531 $$->offset = $O; 0532 } 0533 | T_SH { 0534 $$ = new WeekdayRange; 0535 $$->holiday = WeekdayRange::SchoolHoliday; 0536 } 0537 ; 0538 0539 NthSequence: 0540 NthEntry[N] { 0541 $$ = new NthSequence; 0542 $$->add($N); 0543 } 0544 | NthSequence[N1] T_COMMA NthEntry[N2] { 0545 $N1->add($N2); 0546 $$ = $N1; 0547 } 0548 0549 NthEntry: 0550 T_INTEGER[N] { 0551 if ($N < 1 || $N > 5) { YYABORT; } 0552 $$ = {$N,$N}; 0553 } 0554 | T_INTEGER[N1] T_MINUS T_INTEGER[N2] { 0555 if ($N1 < 1 || $N1 > 5 || $N2 < 1 || $N2 > 5 || $N2 <= $N1) { YYABORT; } 0556 $$ = {$N1,$N2}; 0557 } 0558 | T_MINUS T_INTEGER[N] { 0559 if ($N < 1 || $N > 5) { YYABORT; } 0560 $$ = {-$N,-$N}; 0561 } 0562 ; 0563 0564 DayOffset: 0565 T_PLUS T_INTEGER[N] T_KEYWORD_DAY { $$ = $N; } 0566 | T_MINUS T_INTEGER[N] T_KEYWORD_DAY { $$ = -$N; } 0567 ; 0568 0569 // Week selector 0570 WeekSelector: 0571 T_KEYWORD_WEEK Week[W] { 0572 initSelectors($$); 0573 $$.weekSelector = $W; 0574 } 0575 | WeekSelector[W1] T_COMMA Week[W2] { 0576 $$ = $W1; 0577 appendSelector($$.weekSelector, $W2); 0578 } 0579 ; 0580 0581 Week: 0582 T_INTEGER[N] { 0583 $$ = new Week; 0584 $$->beginWeek = $$->endWeek = $N; 0585 } 0586 | T_INTEGER[N1] T_MINUS T_INTEGER[N2] { 0587 $$ = new Week; 0588 $$->beginWeek = $N1; 0589 $$->endWeek = $N2; 0590 } 0591 | T_INTEGER[N1] T_MINUS T_INTEGER[N2] T_SLASH T_INTEGER[I] { 0592 $$ = new Week; 0593 $$->beginWeek = $N1; 0594 $$->endWeek = $N2; 0595 $$->interval = $I; 0596 } 0597 ; 0598 0599 // Month selector 0600 // the split between MonthdayRange and MonthdayRangeAdditional is to avoid matching a list of years 0601 // to avoid an ambiguity with YearRange below 0602 MonthdaySelector: 0603 MonthdayRange[M] { 0604 initSelectors($$); 0605 $$.monthdaySelector = $M; 0606 } 0607 | MonthdaySelector[S] T_COMMA MonthdayRangeAdditional[M] { 0608 $$ = $S; 0609 appendSelector($$.monthdaySelector, $M); 0610 } 0611 | MonthdaySelector[S] T_COMMA T_INTEGER[D] { 0612 // month day sets, not covered the official grammar but in the 0613 // description in https://wiki.openstreetmap.org/wiki/Key:opening_hours#Summary_syntax 0614 $$ = $S; 0615 if (!extendMonthdaySelector($$.monthdaySelector, $D, $D)) { 0616 delete $$.monthdaySelector; 0617 YYABORT; 0618 } 0619 } 0620 | MonthdaySelector[S] T_ADDITIONAL_RULE_SEPARATOR T_INTEGER[D] { 0621 // same as the above, just with the wrong ", " separator 0622 $$ = $S; 0623 if (!extendMonthdaySelector($$.monthdaySelector, $D, $D)) { 0624 delete $$.monthdaySelector; 0625 YYABORT; 0626 } 0627 } 0628 | MonthdaySelector[S] T_COMMA T_INTEGER[D1] T_MINUS T_INTEGER[D2] { 0629 // same with a range of days 0630 $$ = $S; 0631 if (!extendMonthdaySelector($$.monthdaySelector, $D1, $D2)) { 0632 delete $$.monthdaySelector; 0633 YYABORT; 0634 } 0635 } 0636 | MonthdaySelector[S] T_ADDITIONAL_RULE_SEPARATOR T_INTEGER[D1] T_MINUS T_INTEGER[D2] { 0637 // same as the above, just with the wrong ", " separator 0638 $$ = $S; 0639 if (!extendMonthdaySelector($$.monthdaySelector, $D1, $D2)) { 0640 delete $$.monthdaySelector; 0641 YYABORT; 0642 } 0643 } 0644 ; 0645 0646 MonthdayRange: 0647 T_YEAR[Y] { 0648 $$ = new MonthdayRange; 0649 $$->begin = $$->end = { $Y, 0, 0, Date::FixedDate, { 0, 0, 0 } }; 0650 } 0651 | MonthdayRangeAdditional[M] { $$ = $M; } 0652 0653 MonthdayRangeAdditional: 0654 T_MONTH[M] { 0655 $$ = new MonthdayRange; 0656 $$->begin = $$->end = { 0, $M, 0, Date::FixedDate, { 0, 0, 0 } }; 0657 } 0658 | T_YEAR[Y] T_MONTH[M] { 0659 $$ = new MonthdayRange; 0660 $$->begin = $$->end = { $Y, $M, 0, Date::FixedDate, { 0, 0, 0 } }; 0661 } 0662 | T_MONTH[M1] RangeSeparator T_MONTH[M2] { 0663 $$ = new MonthdayRange; 0664 $$->begin = { 0, $M1, 0, Date::FixedDate, { 0, 0, 0 } }; 0665 $$->end = { 0, $M2, 0, Date::FixedDate, { 0, 0, 0 } }; 0666 } 0667 | T_YEAR[Y] T_MONTH[M1] RangeSeparator T_MONTH[M2] { 0668 $$ = new MonthdayRange; 0669 $$->begin = { $Y, $M1, 0, Date::FixedDate, { 0, 0, 0 } }; 0670 $$->end = { $Y, $M2, 0, Date::FixedDate, { 0, 0, 0 } }; 0671 } 0672 | T_YEAR[Y1] T_MONTH[M1] RangeSeparator T_YEAR[Y2] T_MONTH[M2] { 0673 $$ = new MonthdayRange; 0674 $$->begin = { $Y1, $M1, 0, Date::FixedDate, { 0, 0, 0 } }; 0675 $$->end = { $Y2, $M2, 0, Date::FixedDate, { 0, 0, 0 } }; 0676 } 0677 | T_MONTH[M1] AltMonthdayOffset[O1] RangeSeparator T_MONTH[M2] AltMonthdayOffset[O2] { 0678 $$ = new MonthdayRange; 0679 $$->begin = { 0, $M1, 0, Date::FixedDate, $O1 }; 0680 $$->end = { 0, $M2, 0, Date::FixedDate, $O2 }; 0681 } 0682 | DateFrom[D] { 0683 $$ = new MonthdayRange; 0684 $$->begin = $$->end = $D; 0685 } 0686 | DateFrom[D] DateOffset[O] { 0687 $$ = new MonthdayRange; 0688 $$->begin = $D; 0689 $$->begin.offset += $O; 0690 $$->end = $$->begin; 0691 } 0692 | DateFrom[F] RangeSeparator DateTo[T] { 0693 $$ = new MonthdayRange; 0694 $$->begin = $F; 0695 $$->end = $T; 0696 if ($$->end.year == 0) { $$->end.year = $$->begin.year; } 0697 if ($$->end.month == 0) { $$->end.month = $$->begin.month; } 0698 } 0699 | DateFrom[F] DateOffset[OF] RangeSeparator DateTo[T] { 0700 $$ = new MonthdayRange; 0701 $$->begin = $F; 0702 $$->begin.offset += $OF; 0703 $$->end = $T; 0704 if ($$->end.year == 0) { $$->end.year = $$->begin.year; } 0705 if ($$->end.month == 0) { $$->end.month = $$->begin.month; } 0706 } 0707 | DateFrom[F] RangeSeparator DateTo[T] DateOffset[OT] { 0708 $$ = new MonthdayRange; 0709 $$->begin = $F; 0710 $$->end = $T; 0711 if ($$->end.year == 0) { $$->end.year = $$->begin.year; } 0712 if ($$->end.month == 0) { $$->end.month = $$->begin.month; } 0713 $$->end.offset += $OT; 0714 } 0715 | DateFrom[F] RangeSeparator T_MONTH[M] AltMonthdayOffset[O] { 0716 $$ = new MonthdayRange; 0717 $$->begin = $F; 0718 $$->end = { $F.year, $M, 0, Date::FixedDate, $O }; 0719 } 0720 | T_MONTH[M] AltMonthdayOffset[O] RangeSeparator DateTo[T] { 0721 $$ = new MonthdayRange; 0722 $$->begin = { 0, $M, 0, Date::FixedDate, $O }; 0723 $$->end = $T; 0724 } 0725 | DateFrom[F] DateOffset[OF] RangeSeparator DateTo[T] DateOffset[OT] { 0726 $$ = new MonthdayRange; 0727 $$->begin = $F; 0728 $$->begin.offset += $OF; 0729 $$->end = $T; 0730 if ($$->end.year == 0) { $$->end.year = $$->begin.year; } 0731 if ($$->end.month == 0) { $$->end.month = $$->begin.month; } 0732 $$->end.offset += $OT; 0733 } 0734 ; 0735 0736 DateOffset: 0737 T_PLUS T_WEEKDAY[D] { $$ = { 0, (int8_t)$D, 1 }; } 0738 | T_MINUS T_WEEKDAY[D] { $$ = { 0, (int8_t)$D, -1 }; } 0739 | DayOffset[O] { $$ = { (int16_t)$O, 0, 0 }; } 0740 ; 0741 0742 DateFrom: 0743 T_MONTH[M] T_INTEGER[D] { $$ = { 0, $M, $D, Date::FixedDate, { 0, 0, 0 } }; } 0744 | T_YEAR[Y] T_MONTH[M] T_INTEGER[D] { $$ = { $Y, $M, $D, Date::FixedDate, { 0, 0, 0 } }; } 0745 | VariableDate[D] { $$ = $D; } 0746 | T_YEAR[Y] VariableDate[D] { 0747 $$ = $D; 0748 $$.year = $Y; 0749 } 0750 ; 0751 0752 DateTo: 0753 DateFrom[D] { $$ = $D; } 0754 | T_INTEGER[N] { $$ = { 0, 0, $N, Date::FixedDate, { 0, 0, 0 } }; } 0755 ; 0756 0757 VariableDate: 0758 T_EASTER { $$ = { 0, 0, 0, Date::Easter, { 0, 0, 0 } }; } 0759 | T_WHITSUN { $$ = { 0, 0, 0, Date::Easter, { 49, 0, 0 } }; } 0760 ; 0761 0762 AltMonthdayOffset: 0763 T_WEEKDAY[D] T_LBRACKET T_INTEGER[N] T_RBRACKET { $$ = { 0, (int8_t)$D, (int8_t)$N }; } 0764 | T_WEEKDAY[D] T_LBRACKET T_MINUS T_INTEGER[N] T_RBRACKET { $$ = { 0, (int8_t)$D, (int8_t)-$N }; } 0765 | T_WEEKDAY[D] T_LBRACKET T_INTEGER[N] T_RBRACKET DayOffset[O] { $$ = { (int16_t)$O, (int8_t)$D, (int8_t)$N }; } 0766 | T_WEEKDAY[D] T_LBRACKET T_MINUS T_INTEGER[N] T_RBRACKET DayOffset[O] { $$ = { (int16_t)$O, (int8_t)$D, (int8_t)-$N }; } 0767 0768 // Year selector 0769 // the split between the standalone and combined rules here is to avoid matching a single year 0770 // to avoid a practically relevant ambiguity with MonthdayRange 0771 YearSelector: 0772 YearRangeStandalone[Y] { 0773 initSelectors($$); 0774 $$.yearSelector = $Y; 0775 } 0776 | YearSelectorCombined[S] T_COMMA YearRange[Y] { 0777 $$ = $S; 0778 appendSelector($$.yearSelector, $Y); 0779 } 0780 ; 0781 YearSelectorCombined: 0782 YearRange[Y] { 0783 initSelectors($$); 0784 $$.yearSelector = $Y; 0785 } 0786 | YearSelectorCombined[S] T_COMMA YearRange[Y] { 0787 $$ = $S; 0788 appendSelector($$.yearSelector, $Y); 0789 } 0790 ; 0791 0792 YearRange: 0793 T_YEAR[Y] { 0794 $$ = new YearRange; 0795 $$->begin = $$->end = $Y; 0796 } 0797 | YearRangeStandalone[Y] { $$ = $Y; } 0798 ; 0799 0800 YearRangeStandalone: 0801 T_YEAR[Y1] RangeSeparator T_YEAR[Y2] { 0802 $$ = new YearRange; 0803 $$->begin = $Y1; 0804 $$->end = $Y2; 0805 if ($$->end < $$->begin) { 0806 delete $$; 0807 YYABORT; 0808 } 0809 } 0810 | T_YEAR[Y] T_SLASH T_INTEGER[I] { 0811 $$ = new YearRange; 0812 $$->begin = $Y; 0813 $$->interval = $I; 0814 } 0815 | T_YEAR[Y1] RangeSeparator T_YEAR[Y2] T_SLASH T_INTEGER[I] { 0816 $$ = new YearRange; 0817 $$->begin = $Y1; 0818 $$->end = $Y2; 0819 if ($$->end < $$->begin) { 0820 delete $$; 0821 YYABORT; 0822 } 0823 $$->interval = $I; 0824 } 0825 | T_YEAR[Y] T_PLUS { 0826 $$ = new YearRange; 0827 $$->begin = $Y; 0828 } 0829 0830 // basic building blocks 0831 ExtendedHourMinute: 0832 T_INTEGER[H] T_COLON T_INTEGER[M] { 0833 $$ = { Time::NoEvent, $H, $M }; 0834 if (!Time::isValid($$)) { YYABORT; } 0835 } 0836 | T_INTEGER[H] T_ALT_TIME_SEP T_INTEGER[M] { 0837 $$ = { Time::NoEvent, $H, $M }; 0838 if (!Time::isValid($$)) { YYABORT; } 0839 } 0840 | T_INTEGER[H] T_COLON T_INTEGER[M] T_ALT_TIME_SEP_OR_SUFFIX { 0841 $$ = { Time::NoEvent, $H, $M }; 0842 if (!Time::isValid($$)) { YYABORT; } 0843 } 0844 | T_INTEGER[H] T_ALT_TIME_SEP_OR_SUFFIX T_INTEGER[M] { 0845 $$ = { Time::NoEvent, $H, $M }; 0846 if (!Time::isValid($$)) { YYABORT; } 0847 } 0848 | T_INTEGER[H] T_ALT_TIME_SEP_OR_SUFFIX { 0849 $$ = { Time::NoEvent, $H, 0 }; 0850 if (!Time::isValid($$)) { YYABORT; } 0851 } 0852 | T_INTEGER[H] T_COLON T_ALT_TIME_AM[M] { 0853 $$ = { Time::NoEvent, $H, $M }; 0854 Time::convertFromAm($$); 0855 if (!Time::isValid($$)) { YYABORT; } 0856 } 0857 | T_INTEGER[H] T_ALT_TIME_SEP T_ALT_TIME_AM[M] { 0858 $$ = { Time::NoEvent, $H, $M }; 0859 Time::convertFromAm($$); 0860 if (!Time::isValid($$)) { YYABORT; } 0861 } 0862 | T_INTEGER[H] T_COLON T_ALT_TIME_PM[M] { 0863 $$ = { Time::NoEvent, $H, $M }; 0864 Time::convertFromPm($$); 0865 if (!Time::isValid($$)) { YYABORT; } 0866 } 0867 | T_INTEGER[H] T_ALT_TIME_SEP T_ALT_TIME_PM[M] { 0868 $$ = { Time::NoEvent, $H, $M }; 0869 Time::convertFromPm($$); 0870 if (!Time::isValid($$)) { YYABORT; } 0871 } 0872 | T_ALT_TIME_AM[H] { 0873 $$ = { Time::NoEvent, $H, 0 }; 0874 Time::convertFromAm($$); 0875 if (!Time::isValid($$)) { YYABORT; } 0876 } 0877 | T_ALT_TIME_PM[H] { 0878 $$ = { Time::NoEvent, $H, 0 }; 0879 Time::convertFromPm($$); 0880 if (!Time::isValid($$)) { YYABORT; } 0881 } 0882 | T_4DIGIT_TIME[T] { 0883 $$ = { Time::NoEvent, $T / 100, $T % 100 }; // lexer ensures this is always a valid time 0884 } 0885 ; 0886 0887 RangeSeparator: 0888 T_MINUS 0889 | T_ALT_RANGE_SEP 0890 %%