This repository has been archived by the owner on Apr 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
config-parser.h
197 lines (159 loc) · 4.52 KB
/
config-parser.h
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// Copyright 2007 Daniel Erat <dan@erat.org>
// All rights reserved.
#ifndef __CONFIG_PARSER_H__
#define __CONFIG_PARSER_H__
#include <cstdio>
#include <string>
#include <vector>
#include "util.h"
using namespace std;
class ConfigParserTestSuite;
namespace wham {
// An individual node within a config, possibly containing tokens and
// references to sub-nodes.
struct ConfigNode {
ConfigNode() {}
string Dump() { return Dump(0); }
vector<string> tokens;
vector<ref_ptr<ConfigNode> > children;
int file_num; // not yet implemented
int line_num;
private:
string Dump(int level);
DISALLOW_EVIL_CONSTRUCTORS(ConfigNode);
};
// An error that occurred while loading a config file.
struct ConfigError {
ConfigError(const string& message, int line_num)
: file_num(0),
line_num(line_num),
message(message) {}
string ToString() const;
int file_num; // not yet implemented
int line_num;
string message;
};
// Parses configurations.
class ConfigParser {
public:
// Parse a config from 'filename' into 'config'.
// If 'errors' is non-NULL, errors will be logged there.
// Returns true on success and false otherwise.
static bool ParseFromFile(const string& filename,
ConfigNode* config,
vector<ConfigError>* errors);
private:
friend class ::ConfigParserTestSuite;
enum TokenType {
TOKEN_LITERAL,
TOKEN_LEFT_BRACE,
TOKEN_RIGHT_BRACE,
TOKEN_PERIOD,
TOKEN_NEWLINE,
NUM_TOKEN_TYPES
};
// Abstract base class for tokenizing input.
class Tokenizer {
public:
Tokenizer();
virtual ~Tokenizer() {}
// Get the next token from the stream.
// Returns true if a token was returned and false otherwise.
// The token is written to 'token', its type (relevant in the case of a
// bare token) is written to 'token_type', the 1-indexed number of the
// line where it began is written to 'line_num', and 'error' is set if
// an error was encountered. 'error' only needs to be checked when
// false is returned.
bool GetNextToken(
string* token,
TokenType* token_type,
int* line_num,
bool* error,
vector<ConfigError>* errors);
protected:
// Can the input source be read from? Returns false if there was an
// error in its initialization.
virtual bool Valid() = 0;
virtual int GetCharImpl() = 0;
private:
// Get the next character from the input source.
int GetChar() {
if (have_ungetted_char_) {
have_ungetted_char_ = false;
return ungetted_char_;
}
return GetCharImpl();
}
// Push a character that was already read into a temporary buffer such
// that it will be the next character returned by GetChar(). This
// buffer can only hold a single character.
void UngetChar(int ch) {
CHECK(!have_ungetted_char_);
ungetted_char_ = ch;
have_ungetted_char_ = true;
}
TokenType GetTokenType(const string& token) {
if (token == "\n") return TOKEN_NEWLINE;
if (token == "{") return TOKEN_LEFT_BRACE;
if (token == "}") return TOKEN_RIGHT_BRACE;
if (token == ".") return TOKEN_PERIOD;
return TOKEN_LITERAL;
}
bool done_;
int line_num_;
int ungetted_char_;
bool have_ungetted_char_;
DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
};
// Implementation of Tokenizer that reads from a file.
class FileTokenizer : public Tokenizer {
public:
FileTokenizer(const string& filename)
: Tokenizer(),
file_(fopen(filename.c_str(), "r")) {
}
~FileTokenizer() {
if (file_) {
fclose(file_);
file_ = NULL;
}
}
protected:
bool Valid() {
return (file_ != NULL);
}
int GetCharImpl() {
CHECK(file_);
return fgetc(file_);
}
private:
FILE* file_;
};
// Implementation of Tokenizer that reads from a string.
class StringTokenizer : public Tokenizer {
public:
StringTokenizer(const string& input)
: Tokenizer(),
input_(input),
pos_(0) {
}
protected:
bool Valid() {
return true;
}
int GetCharImpl() {
if (pos_ >= input_.size()) return EOF;
return input_[pos_++];
}
private:
string input_;
size_t pos_;
};
// Parse a config.
// Returns true on success and false otherwise.
static bool Parse(
Tokenizer* tokenizer, ConfigNode* config, vector<ConfigError>* errors);
DISALLOW_EVIL_CONSTRUCTORS(ConfigParser);
};
} // namespace wham
#endif