Browse Source

Added tests for error messages on incomplete inputs

master
Ludovic 'Archivist' Lagouardette 1 year ago
parent
commit
739db2f372
10 changed files with 112 additions and 14 deletions
  1. +1
    -0
      CMakeLists.txt
  2. +4
    -4
      include/molasses/parser_primitives.h
  3. +20
    -10
      src/molasses/parser_primitives.cpp
  4. +71
    -0
      tests/004.exp
  5. +1
    -0
      tests/004/incomplete-01.mol
  6. +1
    -0
      tests/004/incomplete-02.mol
  7. +2
    -0
      tests/004/incomplete-03.mol
  8. +3
    -0
      tests/004/incomplete-04.mol
  9. +4
    -0
      tests/004/incomplete-05.mol
  10. +5
    -0
      tests/004/incomplete-06.mol

+ 1
- 0
CMakeLists.txt View File

@ -30,3 +30,4 @@ endfunction()
add_expect_test(id001 ./tests/001.exp)
add_expect_test(id002 ./tests/002.exp)
add_expect_test(id003 ./tests/003.exp)
add_expect_test(id004 ./tests/004.exp)

+ 4
- 4
include/molasses/parser_primitives.h View File

@ -141,7 +141,7 @@ namespace molasses {
}
struct parser_error : public std::runtime_error {
explicit parser_error(const std::string& str) : std::runtime_error(str) {}
explicit parser_error(const std::string str) : std::runtime_error(str) {}
};
struct type_input_error : public parser_error {
@ -157,7 +157,7 @@ namespace molasses {
// TODO: Better error message
};
struct unexpected_token_error : public parser_error {
unexpected_token_error(const symbol& sym, const std::string& found, const std::string& expected)
unexpected_token_error(const symbol sym, const std::string found, const std::string expected)
: parser_error (
details::concatenate_builder(
"Unexpected token encountered\n",
@ -168,7 +168,7 @@ namespace molasses {
) {}
};
struct expecting_token_error : public parser_error {
expecting_token_error(const std::string& expected, const std::string& context)
expecting_token_error(const std::string expected, const std::string context)
: parser_error(
details::concatenate_builder(
"An expected token has not been encountered before the end of the input\n",
@ -180,7 +180,7 @@ namespace molasses {
// TODO: Better error message
};
struct unknown_token_error : public parser_error {
explicit unknown_token_error(const symbol& sym) : parser_error(details::concatenate_builder("An unknown token has been encountered\n", "\tAt ", sym.file_name,":",sym.line,":",sym.column,"\n")) {}
explicit unknown_token_error(const symbol sym) : parser_error(details::concatenate_builder("An unknown token has been encountered\n", "\tAt ", sym.file_name,":",sym.line,":",sym.column,"\n")) {}
// TODO: Better error message
};
struct type_expected_with_modifier_error : public parser_error {

+ 20
- 10
src/molasses/parser_primitives.cpp View File

@ -152,47 +152,57 @@ namespace molasses {
do{if(it == tokens.symbols.end()) { \
throw expecting_token_error(expected, context); \
}}while(false)
if(*it != PROC_KW) {
decltype(it) last_valid;
if(*it != PROC_KW) {
throw unexpected_token_error(*it, tokens.dictionary[*it],tokens.dictionary[PROC_KW]);
}
last_valid = it;
++it;
check_for_unexpected_stream_end(n">tokens.dictionary[PROC_KW], details::concatenate_builder("In top level, file ",it->file_name, ":", it->line, ":", it->column));
check_for_unexpected_stream_end(sa">"Procedure-Name", details::concatenate_builder("In top level, file ",last_valid->file_name, ":", last_valid->line, ":", last_valid->column));
std::string name = tokens.dictionary.at(*it);
auto& name_symbol = *it;
last_valid = it;
++it;
check_for_unexpected_stream_end(sa">"Procedure-Name", details::concatenate_builder("In top level, file ",it->file_name, ":", it->line, ":", it->column));
check_for_unexpected_stream_end(n">tokens.dictionary[SEPARATOR_KW], details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",last_valid->file_name, ":", last_valid->line, ":", last_valid->column));
// Process arguments list
std::vector<std::string> argument_types;
while(*it != SEPARATOR_KW) {
argument_types.emplace_back(tokens.dictionary.at(*it));
last_valid = it;
++it;
check_for_unexpected_stream_end(n">tokens.dictionary[SEPARATOR_KW], details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",it->file_name, ":", it->line, ":", it->column));
check_for_unexpected_stream_end(sa">"Procedure-Argument-List to end", details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",last_valid->file_name, ":", last_valid->line, ":", last_valid->column));
}
last_valid = it;
++it;
check_for_unexpected_stream_end("Procedure-Argument-List", details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",it->file_name, ":", it->line, ":", it->column));
check_for_unexpected_stream_end("Procedure-Argument-List to be followed by a return list or a __DO__", details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",last_valid->file_name, ":", last_valid->line, ":", last_valid->column));
argument_types = compact_type_modifiers(argument_types);
// Process return types list
std::vector<std::string> return_types;
while(*it != DO_KW) {
return_types.emplace_back(tokens.dictionary.at(*it));
last_valid = it;
++it;
check_for_unexpected_stream_end(n">tokens.dictionary[DO_KW], details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",it->file_name, ":", it->line, ":", it->column));
check_for_unexpected_stream_end(sa">"Procedure-Return-List to end", details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",last_valid->file_name, ":", last_valid->line, ":", last_valid->column));
}
last_valid = it;
++it;
check_for_unexpected_stream_end("Procedure-Return-List", details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",it->file_name, ":", it->line, ":", it->column));
check_for_unexpected_stream_end("__DO__ block needs a matching __END__", details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",last_valid->file_name, ":", last_valid->line, ":", last_valid->column));
return_types = compact_type_modifiers(return_types);
// Process return types list
// Process body
std::vector<symbol> body;
while(*it != END_KW) {
body.emplace_back(*it);
last_valid = it;
++it;
check_for_unexpected_stream_end(n">tokens.dictionary[END_KW], details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",it->file_name, ":", it->line, ":", it->column));
check_for_unexpected_stream_end(sa">"__DO__ block needs a matching __END__", details::concatenate_builder("Parsing procedure ",tokens.dictionary.at(name_symbol),", file ",last_valid->file_name, ":", last_valid->line, ":", last_valid->column));
}
last_valid = it;
++it;
return std::make_pair(it, std::make_shared<procedure_operation>(name, argument_types, return_types, body));

+ 71
- 0
tests/004.exp View File

@ -0,0 +1,71 @@
#!/usr/bin/expect
set SUGAR_EXECUTABLE $::env(SUGAR_EXECUTABLE)
proc abort {reason} {
puts "test failed $reason"
exit 1
}
spawn -noecho $SUGAR_EXECUTABLE tests/004/incomplete-01.mol lex parse
expect {
eof { abort "should display failure in incomplete-01" }
Procedure-Name
}
expect eof
spawn -noecho $SUGAR_EXECUTABLE tests/004/incomplete-02.mol lex parse
expect {
eof { abort "should display failure in incomplete-02" }
__--__
}
expect {
eof { abort "should display failure procedure" }
main
}
expect eof
spawn -noecho $SUGAR_EXECUTABLE tests/004/incomplete-03.mol lex parse
expect {
eof { abort "should display failure in incomplete-03" }
{Expected Procedure-Argument-List to end}
}
expect {
eof { abort "should display failure line" }
{incomplete-03.mol:2}
}
expect eof
spawn -noecho $SUGAR_EXECUTABLE tests/004/incomplete-04.mol lex parse
expect {
eof { abort "should display failure in incomplete-04" }
{Expected Procedure-Argument-List to be followed by a return list or a __DO__}
}
expect {
eof { abort "should display failure line" }
{incomplete-04.mol:3}
}
expect eof
spawn -noecho $SUGAR_EXECUTABLE tests/004/incomplete-05.mol lex parse
expect {
eof { abort "should display failure in incomplete-05" }
{Expected Procedure-Return-List to end}
}
expect {
eof { abort "should display failure line" }
{incomplete-05.mol:4}
}
expect eof
spawn -noecho $SUGAR_EXECUTABLE tests/004/incomplete-06.mol lex parse
expect {
eof { abort "should display failure in incomplete-06" }
{Expected __DO__ block needs a matching __END__}
}
expect {
eof { abort "should display failure line" }
{incomplete-06.mol:5}
}
expect eof

+ 1
- 0
tests/004/incomplete-01.mol View File

@ -0,0 +1 @@
__PROC__

+ 1
- 0
tests/004/incomplete-02.mol View File

@ -0,0 +1 @@
__PROC__ main

+ 2
- 0
tests/004/incomplete-03.mol View File

@ -0,0 +1,2 @@
__PROC__ main
i64

+ 3
- 0
tests/004/incomplete-04.mol View File

@ -0,0 +1,3 @@
__PROC__ main
i64
__--__

+ 4
- 0
tests/004/incomplete-05.mol View File

@ -0,0 +1,4 @@
__PROC__ main
i64
__--__
i64

+ 5
- 0
tests/004/incomplete-06.mol View File

@ -0,0 +1,5 @@
__PROC__ main
i64
__--__
i64
__DO__

Loading…
Cancel
Save