10 class ParseError:
public std::runtime_error {
12 inline ParseError(
const std::string& cause,
size_t pos, std::string input):
13 std::runtime_error(cause
15 + input.substr(pos)) {}
23 inline void error(
const std::string& cause) {
24 throw ParseError(cause, m_cursor, m_text);
26 inline void error_ident() {
27 error(
"Expected an identifier");
30 typedef bool (*acceptor)(
char c);
33 static inline bool accept_char(
char c) {
37 static inline bool accept_numeric(
char c) {
39 return (c ==
'-') || (c ==
'.') || (c >=
'0' && c <=
'9');
42 static inline bool accept_non_numeric(
char c) {
43 return !accept_numeric(c);
46 inline Parser(
View text): m_text(text), m_cursor(0) {}
48 inline bool has_next();
49 inline Value parse_value(
View already_parsed_ident =
View(
""));
50 inline Value parse_single_value(
View already_parsed_ident =
View(
""));
51 inline Arg parse_arg();
52 inline View parse_ident();
53 inline void parse_whitespace();
54 inline bool parse_char(acceptor accept);
55 inline bool peek_char(acceptor accept);
56 inline std::string parse_string(
57 acceptor delim,
const std::string& help,
bool enclose =
true);
58 inline bool parse_keyword(
View keyword);
59 inline View expect_ident();
62 inline bool Parser::has_next() {
63 return m_cursor < m_text.size();
66 inline Value Parser::parse_single_value(
View already_parsed_ident) {
69 if (already_parsed_ident.size() == 0) {
70 if (peek_char(accept_char<'"'>)) {
71 return Value(parse_string(accept_char<'"'>,
"\""));
73 if (peek_char(accept_char<'\''>)) {
74 return Value(parse_string(accept_char<'\''>,
"'"));
76 if (peek_char(accept_numeric)) {
77 return Value(parse_string(accept_non_numeric,
"non-numeric",
false));
83 if (already_parsed_ident.size() > 0) {
84 value_name = already_parsed_ident;
86 value_name = expect_ident();
89 if (value_name ==
"true" 90 || value_name ==
"false") {
91 return Value(value_name);
94 std::vector<Arg> args;
97 if (parse_char(accept_char<
'('>)) {
100 if (parse_char(accept_char<
')'>)) {
102 }
else if (first || parse_char(accept_char<','>)) {
103 if (parse_char(accept_char<
')'>)) {
108 args.push_back(parse_arg());
110 error(
"Expected ) or ,");
115 return Value(value_name, std::move(args));
119 inline Value Parser::parse_value(
View already_parsed_ident) {
120 Value val1 = parse_single_value(already_parsed_ident);
121 while (parse_char(accept_char<':'>)) {
122 Value val2 = parse_single_value();
123 val1 = Value(
"chain", {
124 Arg(std::move(val1)),
125 Arg(std::move(val2)),
131 inline Arg Parser::parse_arg() {
134 auto ident = parse_ident();
136 bool has_type =
false;
137 bool is_static =
false;
140 bool has_keyword =
false;
141 View keyword_ident(
"");
143 if (ident.size() > 0 && parse_char(accept_char<'='>)) {
144 keyword_ident = ident;
149 auto value = parse_value(ident);
151 if (has_keyword && has_type) {
152 return Arg(keyword_ident,
156 }
else if (!has_keyword && has_type) {
157 return Arg(is_static,
160 }
else if (has_keyword && !has_type) {
161 return Arg(keyword_ident,
164 return Arg(std::move(value));
167 inline View Parser::parse_ident() {
169 size_t ident_start = m_cursor;
170 if (m_cursor < m_text.size()) {
171 auto c = m_text[m_cursor];
173 || (c >=
'a' && c <=
'z')
174 || (c >=
'A' && c <=
'Z')
179 return m_text.slice(ident_start, m_cursor);
182 for (; m_cursor < m_text.size(); m_cursor++) {
183 auto c = m_text[m_cursor];
185 || (c >=
'a' && c <=
'z')
186 || (c >=
'A' && c <=
'Z')
187 || (c >=
'0' && c <=
'9')
194 return m_text.slice(ident_start, m_cursor);
196 inline void Parser::parse_whitespace() {
200 while (m_text[m_cursor] ==
' ' 201 || m_text[m_cursor] ==
'\n' 202 || m_text[m_cursor] ==
'\r' 203 || m_text[m_cursor] ==
'\t')
208 inline bool Parser::parse_char(acceptor accept) {
209 bool r = peek_char(accept);
215 inline bool Parser::peek_char(acceptor accept) {
220 return accept(m_text[m_cursor]);
222 inline std::string Parser::parse_string(
223 acceptor delim,
const std::string& help,
bool enclose) {
227 if (!enclose || parse_char(delim)) {
232 if (parse_char(delim)) {
237 if(peek_char(delim)) {
245 return m_text.slice(start, end);
248 error(std::string(
"Expected ") + help);
251 inline bool Parser::parse_keyword(
View keyword) {
253 if (m_text.slice(m_cursor).starts_with(keyword)) {
254 m_cursor += keyword.size();
259 inline View Parser::expect_ident() {
260 View ident = parse_ident();
261 if (ident.size() == 0) {
Contains the text compression and encoding framework.