82 const std::string &css_code;
84 RParser(
const std::string &_code) : css_code(_code)
86 len = css_code.length();
89 bool more_data()
const {
return pos < len; }
91 char current()
const {
return css_code[
pos]; }
93 void shift() { ++
pos; }
95 bool check_symbol(
bool isfirst =
false)
97 auto symbol = current();
98 if (((symbol >=
'a') && (symbol <=
'z')) ||
99 ((symbol >=
'A') && (symbol <=
'Z')) || (symbol ==
'_'))
return true;
100 return (!isfirst && (symbol>=
'0') && (symbol<=
'9'));
103 std::string error_position()
const
105 std::string res =
"\nLine "s + std::to_string(nline) +
": "s;
108 while ((p<len) && (p < linebeg+100) && (css_code[p] !=
'\n')) ++p;
110 return res + css_code.substr(linebeg, p-linebeg);
115 bool skip_until_newline =
false, skip_until_endblock =
false;
118 if (current() ==
'\n') {
119 skip_until_newline =
false;
125 if (skip_until_endblock && (current() ==
'*') && (
pos+1 < len) && (css_code[
pos+1] ==
'/')) {
127 skip_until_endblock =
false;
131 if (skip_until_newline || skip_until_endblock || (current() ==
' ') || (current() ==
'\t')) {
136 if ((current() ==
'/') && (
pos+1 < len)) {
137 if (css_code[
pos+1] ==
'/') {
139 skip_until_newline =
true;
141 }
else if (css_code[
pos+1] ==
'*') {
143 skip_until_endblock =
true;
154 std::string scan_identifier(
bool selector =
false)
156 if (
pos >= len)
return ""s;
161 if (selector && ((current() ==
'.') || (current() ==
'#'))) shift();
163 bool is_first =
true;
165 while ((
pos < len) && check_symbol(is_first)) { shift(); is_first =
false; }
167 std::string s = css_code.substr(pos0,
pos-pos0);
169 std::transform(s.begin(), s.end(), s.begin(),
170 [](
unsigned char c){ return std::tolower(c); });
174 std::string scan_value()
176 if (
pos >= len)
return ""s;
180 while ((
pos < len) && (current() !=
';') && current() !=
'\n') shift();
187 return css_code.substr(pos0,
pos - pos0 - 1);
192 RParser parser(css_code);
196 while (parser.more_data()) {
198 if (!parser.skip_empty())
201 auto sel = parser.scan_identifier(
true);
207 if (!parser.skip_empty())
210 if (parser.current() !=
'{') {
217 if (!parser.skip_empty())
222 while (parser.current() !=
'}') {
223 auto name = parser.scan_identifier();
229 if (!parser.skip_empty())
232 if (parser.current() !=
':') {
239 if (!parser.skip_empty())
242 if (parser.current() ==
';') {
246 auto value = parser.scan_value();
255 if (!parser.skip_empty())