1 /*
2     This file is part of the kholidays library.
3 
4     SPDX-FileCopyrightText: 2010 John Layt <john@layt.net>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #ifndef KHOLIDAYS_HOLIDAYPARSERDRIVERPLAN_P_H
10 #define KHOLIDAYS_HOLIDAYPARSERDRIVERPLAN_P_H
11 
12 #include "../holidayparserdriver_p.h"
13 
14 #include <QByteArray>
15 #include <QStringList>
16 
17 #include <string>
18 
19 namespace KHolidays
20 {
21 class HolidayScannerPlan;
22 class HolidayParserPlan;
23 class location;
24 
25 /**
26  * HolidayParserDriverPlan implementation class
27  *
28  * Implements the standard driver interface for parsing Plan holiday files as
29  * implemented in KDE SC 4.5 onwards.  This includes extensions to the file
30  * format to support non-Gregorian calendar systems, metadata, and other new
31  * features.
32  *
33  * Implemented using Bison/Flex and the Bison C++ skeleton v2.1a, see README.
34  * While almost all code is new, the structure of the parser is based on the
35  * original Plan parser.
36  *
37  * @internal Private, for internal use only
38  */
39 class HolidayParserDriverPlan : public HolidayParserDriver
40 {
41 public:
42     /**
43      * Constructor of Plan file parser driver
44      *
45      * @param filePath full path to holiday file
46      */
47     explicit HolidayParserDriverPlan(const QString &planFilename);
48 
49     /**
50      * Destructor.
51      */
52     ~HolidayParserDriverPlan() override;
53 
54     /**
55      * Bison C++ skeleton error message handling
56      *
57      * @param errorMessage error message to log
58      */
59     void error(const KHolidays::location &errorLocation, const QString &errorMessage);
60 
61     /**
62      * Standard error message handling
63      *
64      * @param errorMessage error message to log
65      */
66     void error(const QString &errorMessage) override;
67 
68 protected:
69     /**
70      * Actually parse the file, new plan format implementation
71      */
72     void parse() override;
73 
74     /**
75      * Parse the file for metadata only and populate the metadata variables
76      */
77     void parseMetadata() override;
78 
79     /**
80      * Set the calendar system to use
81      *
82      * @param calendar The QCalendarSystem calendar system to use
83      */
84     void setParseCalendar(QCalendarSystem::CalendarSystem calendar) override;
85 
86     // Bison C++ skeleton required friend for Bison parser class implementation
87     friend class HolidayParserPlan;
88 
89     // Accessor methods for parser to talk to driver
90     QString filePath();
91     std::string *fileToParse() const;
92 
93     // Calendar and date calculation utilities
94     int adjustedMonthNumber(int month);
95     bool isLeapYear(int year);
96     int parseYear();
97 
98     // Utilities for parser to calculate interim Julian Day Number during parsing
99     int julianDayFromEventName(const QString &eventName);
100     int julianDayFromEaster();
101     int julianDayFromPascha();
102     int julianDayFromMonthDay(int month, int day);
103     int julianDayFromRelativeWeekday(int occurrence, int weekday, int jd);
104     int julianDayFromWeekdayInMonth(int occurrence, int weekday, int month);
105 
106     // Utilities for parser to set variables during parsing
107     void setParseCalendar(const QString &calendarType);
108     void setFileCountryCode(const QString &countryCode);
109     void setFileLanguageCode(const QString &languageCode);
110     void setFileName(const QString &ame);
111     void setFileDescription(const QString &description);
112     void setEventName(const QString &eventName);
113     void setEventCategory(const QString &category);
114     void setEventCalendarType(const QString &calendarType = QStringLiteral("gregorian"));
115     void setEventDate(int eventYear, int eventMonth, int eventDay);
116     void setEventDate(int jd);
117 
118     // Terminal functions for parser to create holidays from parsed variables
119     void setFromEaster(int offset, int duration);
120     void setFromPascha(int offset, int duration);
121     void setFromDate(int offset, int condition, int duration);
122     void setFromWeekdayInMonth(int occurrence, int weekday, int month, int offset, int duration);
123     void setFromRelativeWeekday(int occurrence, int weekday, int offset, int duration);
124     void setEvent(int event_jd, int observe_offset, int duration);
125 
126 private:
127     // Calendar and date calculation utilities
128     int julianDay(int year, int month, int day);
129     void julianDayToDate(int jd, int *year, int *month, int *day);
130     QDate easter(int year);
131     QDate pascha(int year);
132     QCalendarSystem::CalendarSystem typeToSystem(const QString &calendarType);
133     QString systemToType(QCalendarSystem::CalendarSystem calendar);
134 
135     int conditionalOffset(int year, int month, int day, int condition);
136 
137     void addHoliday(const QDate &date, int duration);
138 
139     QByteArray m_scanData; // Holiday file stored as a string
140 
141     QStringList m_fileCalendarTypes; // List of all Calendar Types used in file
142     QString m_parseCalendarType; // Calendar Type being parsed
143 
144     bool m_traceParsing; // Bison C++ skeleton enable tracing in Bison parser class
145     HolidayParserPlan *m_parser; // Bison C++ skeleton Bison parser class implementation
146 
147     bool m_traceScanning; // Flex C++ enable tracing in Flex scanner class
148     HolidayScannerPlan *m_scanner; // Flex C++ scanner class implementation
149 
150     bool m_parseMetadataOnly; // Only parse file for metadata
151     QDate m_parseYearStart; // First day of year being parsed
152     QDate m_parseYearEaster; // Easter in the parse year, Gregorian only
153     QDate m_parseYearPascha; // Orthodox Easter in the parse year, Gregorian only
154 
155     QStringList m_eventCategories; // Event categories
156     QString m_eventCalendarType; // Calendar Type for event rule
157     QString m_eventName; // Event name text
158     int m_eventYear; // Event date fields
159     int m_eventMonth; // Event date fields
160     int m_eventDay; // Event date fields
161 
162     std::string *m_fileToParse = nullptr;
163 };
164 
165 }
166 
167 #endif // KHOLIDAYS_HOLIDAYPARSERDRIVERPLAN_P_H
168