aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libtmi8/include/tmi8/kv1_parser.hpp
blob: cbfe18ea0df8de04a3bbead271440ca8b5aa7f3c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// vim:set sw=2 ts=2 sts et:
//
// Copyright 2024 Rutger Broekhoff. Licensed under the EUPL.

#ifndef OEUF_LIBTMI8_KV1_PARSER_HPP
#define OEUF_LIBTMI8_KV1_PARSER_HPP

#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>

#include <tmi8/kv1_lexer.hpp>
#include <tmi8/kv1_types.hpp>

struct Kv1Parser {
  explicit Kv1Parser(std::vector<Kv1Token> tokens, Kv1Records &parse_into);
  
  void parse();

 private:
  // Method pointer to a method of Kv1Parser (i.e. a function that takes
  // 'this'; is not static) that takes no arguments and also does not return
  // anything.
  using ParseFunc = void (Kv1Parser::*)();
  static const std::unordered_map<std::string_view, ParseFunc> type_parsers;

  bool atEnd() const;
  void eatRowEnds();
  const Kv1Token *cur() const;
  const std::string *eatCell(std::string_view parsing_what);
  std::string parseHeader();
  void eatRestOfRow();

  void requireString(std::string_view field, bool mandatory, size_t max_length, std::string_view value);
  std::optional<bool> requireBoolean(std::string_view field, bool mandatory, std::string_view value);
  std::optional<double> requireNumber(std::string_view field, bool mandatory, size_t max_digits, std::string_view value);
  std::optional<RgbColor> requireRgbColor(std::string_view field, bool mandatory, std::string_view value);
  std::optional<double> requireRdCoord(std::string_view field, bool mandatory, size_t min_digits, std::string_view value);

  std::string eatString(std::string_view field, bool mandatory, size_t max_length);
  std::optional<bool> eatBoolean(std::string_view field, bool mandatory);
  std::optional<double> eatNumber(std::string_view field, bool mandatory, size_t max_digits);
  std::optional<RgbColor> eatRgbColor(std::string_view field, bool mandatory);
  std::optional<double> eatRdCoord(std::string_view field, bool mandatory, size_t min_digits);

  void parseOrganizationalUnit();
  void parseHigherOrganizationalUnit();
  void parseUserStopPoint();
  void parseUserStopArea();
  void parseTimingLink();
  void parseLink();
  void parseLine();
  void parseDestination();
  void parseJourneyPattern();
  void parseConcessionFinancerRelation();
  void parseConcessionArea();
  void parseFinancer();
  void parseJourneyPatternTimingLink();
  void parsePoint();
  void parsePointOnLink();
  void parseIcon();
  void parseNotice();
  void parseNoticeAssignment();
  void parseTimeDemandGroup();
  void parseTimeDemandGroupRunTime();
  void parsePeriodGroup();
  void parseSpecificDay();
  void parseTimetableVersion();
  void parsePublicJourney();
  void parsePeriodGroupValidity();
  void parseExceptionalOperatingDay();
  void parseScheduleVersion();
  void parsePublicJourneyPassingTimes();
  void parseOperatingDay();

  size_t pos = 0;
  std::vector<Kv1Token> tokens;
  const std::chrono::time_zone *amsterdam = std::chrono::locate_zone("Europe/Amsterdam");

 public:
  std::vector<std::string> warns;
  std::vector<std::string> global_errors;
  std::vector<std::string> record_errors;
  Kv1Records &records;
};

#endif // OEUF_LIBTMI8_KV1_PARSER_HPP