Reduce redundant escape code parsing #211
This commit is contained in:
@@ -949,6 +949,57 @@ namespace chaiscript
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Char_Parser
|
||||||
|
{
|
||||||
|
bool is_escaped;
|
||||||
|
bool is_interpolated;
|
||||||
|
bool saw_interpolation_marker;
|
||||||
|
const bool interpolation_allowed;
|
||||||
|
|
||||||
|
Char_Parser(const bool t_interpolation_allowed)
|
||||||
|
: is_escaped(false),
|
||||||
|
is_interpolated(false),
|
||||||
|
saw_interpolation_marker(false),
|
||||||
|
interpolation_allowed(t_interpolation_allowed)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse(std::string &t_match, const char t_char, const int line, const int col, const std::string &filename) {
|
||||||
|
if (t_char == '\\') {
|
||||||
|
if (is_escaped) {
|
||||||
|
t_match.push_back('\\');
|
||||||
|
is_escaped = false;
|
||||||
|
} else {
|
||||||
|
is_escaped = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (is_escaped) {
|
||||||
|
switch (t_char) {
|
||||||
|
case ('\'') : t_match.push_back('\''); break;
|
||||||
|
case ('\"') : t_match.push_back('\"'); break;
|
||||||
|
case ('?') : t_match.push_back('?'); break;
|
||||||
|
case ('a') : t_match.push_back('\a'); break;
|
||||||
|
case ('b') : t_match.push_back('\b'); break;
|
||||||
|
case ('f') : t_match.push_back('\f'); break;
|
||||||
|
case ('n') : t_match.push_back('\n'); break;
|
||||||
|
case ('r') : t_match.push_back('\r'); break;
|
||||||
|
case ('t') : t_match.push_back('\t'); break;
|
||||||
|
case ('v') : t_match.push_back('\v'); break;
|
||||||
|
case ('$') : t_match.push_back('$'); break;
|
||||||
|
default: throw exception::eval_error("Unknown escaped sequence in string", File_Position(line, col), filename);
|
||||||
|
}
|
||||||
|
} else if (interpolation_allowed && t_char == '$') {
|
||||||
|
saw_interpolation_marker = true;
|
||||||
|
} else {
|
||||||
|
t_match.push_back(t_char);
|
||||||
|
}
|
||||||
|
is_escaped = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Reads (and potentially captures) a quoted string from input. Translates escaped sequences.
|
/// Reads (and potentially captures) a quoted string from input. Translates escaped sequences.
|
||||||
bool Quoted_String(const bool t_capture = false) {
|
bool Quoted_String(const bool t_capture = false) {
|
||||||
SkipWS();
|
SkipWS();
|
||||||
@@ -960,19 +1011,19 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (Quoted_String_()) {
|
if (Quoted_String_()) {
|
||||||
std::string match;
|
std::string match;
|
||||||
bool is_escaped = false;
|
|
||||||
bool is_interpolated = false;
|
Char_Parser cparser(true);
|
||||||
bool saw_interpolation_marker = false;
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
auto s = start + 1, end = m_position - 1;
|
auto s = start + 1, end = m_position - 1;
|
||||||
|
|
||||||
while (s != end) {
|
while (s != end) {
|
||||||
if (saw_interpolation_marker) {
|
if (cparser.saw_interpolation_marker) {
|
||||||
if (*s == '{') {
|
if (*s == '{') {
|
||||||
//We've found an interpolation point
|
//We've found an interpolation point
|
||||||
|
|
||||||
if (is_interpolated) {
|
if (cparser.is_interpolated) {
|
||||||
//If we've seen previous interpolation, add on instead of making a new one
|
//If we've seen previous interpolation, add on instead of making a new one
|
||||||
m_match_stack.push_back(make_node<eval::Quoted_String_AST_Node>(match, start.line, start.col));
|
m_match_stack.push_back(make_node<eval::Quoted_String_AST_Node>(match, start.line, start.col));
|
||||||
|
|
||||||
@@ -993,7 +1044,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*s == '}') {
|
if (*s == '}') {
|
||||||
is_interpolated = true;
|
cparser.is_interpolated = true;
|
||||||
++s;
|
++s;
|
||||||
|
|
||||||
const auto tostr_stack_top = m_match_stack.size();
|
const auto tostr_stack_top = m_match_stack.size();
|
||||||
@@ -1019,40 +1070,14 @@ namespace chaiscript
|
|||||||
} else {
|
} else {
|
||||||
match.push_back('$');
|
match.push_back('$');
|
||||||
}
|
}
|
||||||
saw_interpolation_marker = false;
|
cparser.saw_interpolation_marker = false;
|
||||||
} else {
|
} else {
|
||||||
if (*s == '\\') {
|
cparser.parse(match, *s, start.line, start.col, *m_filename);
|
||||||
if (is_escaped) {
|
|
||||||
match.push_back('\\');
|
|
||||||
is_escaped = false;
|
|
||||||
} else {
|
|
||||||
is_escaped = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (is_escaped) {
|
|
||||||
switch (*s) {
|
|
||||||
case ('b') : match.push_back('\b'); break;
|
|
||||||
case ('f') : match.push_back('\f'); break;
|
|
||||||
case ('n') : match.push_back('\n'); break;
|
|
||||||
case ('r') : match.push_back('\r'); break;
|
|
||||||
case ('t') : match.push_back('\t'); break;
|
|
||||||
case ('\'') : match.push_back('\''); break;
|
|
||||||
case ('\"') : match.push_back('\"'); break;
|
|
||||||
case ('$') : match.push_back('$'); break;
|
|
||||||
default: throw exception::eval_error("Unknown escaped sequence in string", File_Position(start.line, start.col), *m_filename);
|
|
||||||
}
|
|
||||||
} else if (*s == '$') {
|
|
||||||
saw_interpolation_marker = true;
|
|
||||||
} else {
|
|
||||||
match.push_back(*s);
|
|
||||||
}
|
|
||||||
is_escaped = false;
|
|
||||||
}
|
|
||||||
++s;
|
++s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_interpolated) {
|
if (cparser.is_interpolated) {
|
||||||
m_match_stack.push_back(make_node<eval::Quoted_String_AST_Node>(match, start.line, start.col));
|
m_match_stack.push_back(make_node<eval::Quoted_String_AST_Node>(match, start.line, start.col));
|
||||||
|
|
||||||
build_match<eval::Binary_Operator_AST_Node>(prev_stack_top, "+");
|
build_match<eval::Binary_Operator_AST_Node>(prev_stack_top, "+");
|
||||||
@@ -1104,33 +1129,12 @@ namespace chaiscript
|
|||||||
const auto start = m_position;
|
const auto start = m_position;
|
||||||
if (Single_Quoted_String_()) {
|
if (Single_Quoted_String_()) {
|
||||||
std::string match;
|
std::string match;
|
||||||
bool is_escaped = false;
|
Char_Parser cparser(false);
|
||||||
|
|
||||||
for (auto s = start + 1, end = m_position - 1; s != end; ++s) {
|
for (auto s = start + 1, end = m_position - 1; s != end; ++s) {
|
||||||
if (*s == '\\') {
|
cparser.parse(match, *s, start.line, start.col, *m_filename);
|
||||||
if (is_escaped) {
|
|
||||||
match.push_back('\\');
|
|
||||||
is_escaped = false;
|
|
||||||
} else {
|
|
||||||
is_escaped = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (is_escaped) {
|
|
||||||
switch (*s) {
|
|
||||||
case ('b') : match.push_back('\b'); break;
|
|
||||||
case ('f') : match.push_back('\f'); break;
|
|
||||||
case ('n') : match.push_back('\n'); break;
|
|
||||||
case ('r') : match.push_back('\r'); break;
|
|
||||||
case ('t') : match.push_back('\t'); break;
|
|
||||||
case ('\'') : match.push_back('\''); break;
|
|
||||||
case ('\"') : match.push_back('\"'); break;
|
|
||||||
default: throw exception::eval_error("Unknown escaped sequence in string", File_Position(start.line, start.col), *m_filename);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match.push_back(*s);
|
|
||||||
}
|
|
||||||
is_escaped = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_match_stack.push_back(make_node<eval::Single_Quoted_String_AST_Node>(match, start.line, start.col));
|
m_match_stack.push_back(make_node<eval::Single_Quoted_String_AST_Node>(match, start.line, start.col));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user