CommandManager: diagnose unterminated strings
This commit is contained in:
parent
6bbbd2543a
commit
9d04c773c1
|
@ -31,6 +31,10 @@ void CommandManager::register_commands(const memoryview<String>& command_names,
|
||||||
register_command(command_name, command, completer);
|
register_command(command_name, command, completer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse_error::parse_error(const String& error)
|
||||||
|
: runtime_error{"parse error: " + error} {}
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -73,8 +77,16 @@ bool is_horizontal_blank(char c)
|
||||||
return c == ' ' or c == '\t';
|
return c == ' ' or c == '\t';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct unterminated_string : parse_error
|
||||||
|
{
|
||||||
|
unterminated_string(const String& open, const String& close, int nest = 0)
|
||||||
|
: parse_error{"unterminated string '" + open + "..." + close + "'" +
|
||||||
|
(nest > 0 ? "(nesting: " + int_to_str(nest) + ")" : "")}
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
TokenList parse(const String& line,
|
TokenList parse(const String& line,
|
||||||
TokenPosList* opt_token_pos_info = NULL)
|
TokenPosList* opt_token_pos_info = nullptr)
|
||||||
{
|
{
|
||||||
TokenList result;
|
TokenList result;
|
||||||
|
|
||||||
|
@ -109,6 +121,8 @@ TokenList parse(const String& line,
|
||||||
while ((line[pos] != delimiter or line[pos-1] == '\\') and
|
while ((line[pos] != delimiter or line[pos-1] == '\\') and
|
||||||
pos != length)
|
pos != length)
|
||||||
++pos;
|
++pos;
|
||||||
|
if (pos == length)
|
||||||
|
throw unterminated_string(String{delimiter}, String{delimiter});
|
||||||
}
|
}
|
||||||
else if (line[pos] == '%')
|
else if (line[pos] == '%')
|
||||||
{
|
{
|
||||||
|
@ -149,12 +163,18 @@ TokenList parse(const String& line,
|
||||||
}
|
}
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
|
if (pos == length)
|
||||||
|
throw unterminated_string("%" + type_name + opening_delimiter,
|
||||||
|
String{closing_delimiter}, level);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (pos != length and
|
while (pos != length and
|
||||||
(line[pos] != opening_delimiter or line[pos-1] == '\\'))
|
(line[pos] != opening_delimiter or line[pos-1] == '\\'))
|
||||||
++pos;
|
++pos;
|
||||||
|
if (pos == length)
|
||||||
|
throw unterminated_string("%" + type_name + opening_delimiter,
|
||||||
|
String{opening_delimiter});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -16,6 +16,10 @@ namespace Kakoune
|
||||||
|
|
||||||
struct Context;
|
struct Context;
|
||||||
|
|
||||||
|
struct parse_error : runtime_error
|
||||||
|
{
|
||||||
|
parse_error(const String& error);
|
||||||
|
};
|
||||||
|
|
||||||
using CommandParameters = memoryview<String>;
|
using CommandParameters = memoryview<String>;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user