CommandManager: diagnose unterminated strings

This commit is contained in:
Maxime Coste 2012-11-21 13:56:52 +01:00
parent 6bbbd2543a
commit 9d04c773c1
2 changed files with 25 additions and 1 deletions

View File

@ -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

View File

@ -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>;