mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 23:37:35 +00:00
IDL: Produce better error messages when parsing IDL files.
This commit is contained in:
parent
78eff163ea
commit
82aac98bea
2 changed files with 51 additions and 10 deletions
|
@ -1,6 +1,7 @@
|
||||||
add_executable(Generate_CSS_PropertyID_h Generate_CSS_PropertyID_h.cpp)
|
add_executable(Generate_CSS_PropertyID_h Generate_CSS_PropertyID_h.cpp)
|
||||||
add_executable(Generate_CSS_PropertyID_cpp Generate_CSS_PropertyID_cpp.cpp)
|
add_executable(Generate_CSS_PropertyID_cpp Generate_CSS_PropertyID_cpp.cpp)
|
||||||
add_executable(WrapperGenerator WrapperGenerator.cpp)
|
add_executable(WrapperGenerator WrapperGenerator.cpp)
|
||||||
|
target_compile_options(WrapperGenerator PUBLIC -g)
|
||||||
target_link_libraries(Generate_CSS_PropertyID_h LagomCore)
|
target_link_libraries(Generate_CSS_PropertyID_h LagomCore)
|
||||||
target_link_libraries(Generate_CSS_PropertyID_cpp LagomCore)
|
target_link_libraries(Generate_CSS_PropertyID_cpp LagomCore)
|
||||||
target_link_libraries(WrapperGenerator LagomCore)
|
target_link_libraries(WrapperGenerator LagomCore)
|
||||||
|
|
|
@ -68,6 +68,41 @@ static String make_input_acceptable_cpp(const String& input)
|
||||||
return input_without_dashes;
|
return input_without_dashes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void report_parsing_error(StringView message, StringView filename, StringView input, size_t offset)
|
||||||
|
{
|
||||||
|
// FIXME: Spaghetti code ahead.
|
||||||
|
|
||||||
|
size_t lineno = 1;
|
||||||
|
size_t colno = 1;
|
||||||
|
size_t start_line = 0;
|
||||||
|
size_t line_length = 0;
|
||||||
|
for (size_t index = 0; index < input.length(); ++index) {
|
||||||
|
if (offset == index)
|
||||||
|
colno = index - start_line + 1;
|
||||||
|
|
||||||
|
if (input[index] == '\n') {
|
||||||
|
if (index >= offset)
|
||||||
|
break;
|
||||||
|
|
||||||
|
start_line = index + 1;
|
||||||
|
line_length = 0;
|
||||||
|
++lineno;
|
||||||
|
} else {
|
||||||
|
++line_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder error_message;
|
||||||
|
error_message.appendff("{}\n", input.substring_view(start_line, line_length));
|
||||||
|
for (size_t i = 0; i < colno - 1; ++i)
|
||||||
|
error_message.append(' ');
|
||||||
|
error_message.append("\033[1;31m^\n");
|
||||||
|
error_message.appendff("{}:{}: error: {}\033[0m\n", filename, lineno, message);
|
||||||
|
|
||||||
|
warnln("{}", error_message.string_view());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
namespace IDL {
|
namespace IDL {
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
|
@ -125,27 +160,32 @@ struct Interface {
|
||||||
String fully_qualified_name;
|
String fully_qualified_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static OwnPtr<Interface> parse_interface(const StringView& input)
|
static OwnPtr<Interface> parse_interface(StringView filename, const StringView& input)
|
||||||
{
|
{
|
||||||
auto interface = make<Interface>();
|
auto interface = make<Interface>();
|
||||||
|
|
||||||
GenericLexer lexer(input);
|
GenericLexer lexer(input);
|
||||||
|
|
||||||
auto assert_specific = [&](char ch) {
|
auto assert_specific = [&](char ch) {
|
||||||
auto consumed = lexer.consume();
|
if (!lexer.consume_specific(ch))
|
||||||
if (consumed != ch) {
|
report_parsing_error(String::formatted("expected '{}'", ch), filename, input, lexer.tell());
|
||||||
dbg() << "Expected '" << ch << "' at offset " << lexer.tell() << " but got '" << consumed << "'";
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto consume_whitespace = [&] {
|
auto consume_whitespace = [&] {
|
||||||
lexer.consume_while([](char ch) { return isspace(ch); });
|
bool consumed = true;
|
||||||
|
while (consumed) {
|
||||||
|
consumed = lexer.consume_while([](char ch) { return isspace(ch); }).length() > 0;
|
||||||
|
|
||||||
|
if (lexer.consume_specific("//")) {
|
||||||
|
lexer.consume_until('\n');
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto assert_string = [&](const StringView& expected) {
|
auto assert_string = [&](const StringView& expected) {
|
||||||
bool saw_expected = lexer.consume_specific(expected);
|
if (!lexer.consume_specific(expected))
|
||||||
ASSERT(saw_expected);
|
report_parsing_error(String::formatted("expected '{}'", expected), filename, input, lexer.tell());
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_string("interface");
|
assert_string("interface");
|
||||||
|
@ -295,7 +335,7 @@ int main(int argc, char** argv)
|
||||||
auto namespace_ = lexical_path.parts().at(lexical_path.parts().size() - 2);
|
auto namespace_ = lexical_path.parts().at(lexical_path.parts().size() - 2);
|
||||||
|
|
||||||
auto data = file_or_error.value()->read_all();
|
auto data = file_or_error.value()->read_all();
|
||||||
auto interface = IDL::parse_interface(data);
|
auto interface = IDL::parse_interface(path, data);
|
||||||
|
|
||||||
if (!interface) {
|
if (!interface) {
|
||||||
warnln("Cannot parse {}", path);
|
warnln("Cannot parse {}", path);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue