VirtualC64 v5.0 beta
Commodore 64 Emulator
Loading...
Searching...
No Matches
Parser.h
1// -----------------------------------------------------------------------------
2// This file is part of VirtualC64
3//
4// Copyright (C) Dirk W. Hoffmann. www.dirkwhoffmann.de
5// This FILE is dual-licensed. You are free to choose between:
6//
7// - The GNU General Public License v3 (or any later version)
8// - The Mozilla Public License v2
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR MPL-2.0
11// -----------------------------------------------------------------------------
12
13#pragma once
14
15#include "Types.h"
16#include "Exception.h"
17#include <functional>
18
19namespace vc64::util {
20
21struct ParseError : public std::exception {
22
23 string token;
24 string expected;
25
26 ParseError(const string &t) : token(t) { }
27 ParseError(const string &t, const string &e) : token(t), expected(e) { }
28
29 const char *what() const throw() override { return token.c_str(); }
30};
31
32struct ParseBoolError : public ParseError {
33 using ParseError::ParseError;
34};
35
36struct ParseOnOffError : public ParseError {
37 using ParseError::ParseError;
38};
39
40struct ParseNumError : public ParseError {
41 using ParseError::ParseError;
42};
43
44struct EnumParseError : public ParseError {
45 using ParseError::ParseError;
46};
47
48bool isBool(const string& token);
49bool isOnOff(const string& token);
50bool isNum(const string& token);
51
52bool parseBool(const string& token) throws;
53bool parseOnOff(const string& token) throws;
54long parseNum(const string& token) throws;
55string parseSeq(const string& token) throws;
56
57template <typename Enum> long parseEnum(const string& key)
58{
59 return parsePartialEnum <Enum> (key, [](long){ return true; });
60}
61
62template <typename R, typename Enum> R parseEnum(const string& key)
63{
64 return (R)parseEnum <Enum> (key);
65}
66
67template <typename Enum> long parsePartialEnum(const string& key, std::function<bool(long)> accept)
68{
69 string upper, prefix, suffix;
70
71 // Convert the search string to upper case
72 for (auto c : key) { upper += (char)std::toupper(c); }
73
74 // Search all keys
75 for (isize i = Enum::minVal; i <= Enum::maxVal; i++) {
76
77 if (!accept(i)) continue;
78
79 auto enumkey = string(Enum::key(i));
80
81 // Check if the full key matches
82 if (enumkey == upper) return i;
83
84 // If a section marker is present, check the plain key, too
85 if (auto pos = enumkey.find('.'); pos != std::string::npos) {
86 if (enumkey.substr(pos + 1, string::npos) == upper) return i;
87 }
88 }
89
90 throw EnumParseError(key, Enum::keyList());
91}
92
93template <typename R, typename Enum> R parsePartialEnum(const string& key, std::function<bool(long)> accept)
94{
95 return (R)parsePartialEnum<Enum>(key, accept);
96}
97
98}