diff --git a/include/molasses/errors.h b/include/molasses/errors.h index 79ce2dd..071b279 100644 --- a/include/molasses/errors.h +++ b/include/molasses/errors.h @@ -61,6 +61,13 @@ namespace molasses { "\tExpected ", expected, "\n", "\tFound ", found, "\n" )) {} }; + struct duplicate_label_error : public parser_error { + duplicate_label_error(const symbol& sym, const std::string& found) + : parser_error(details::concatenate_builder( + "Unexpected label duplication\n", "\tAt ", sym.file_name, ":", sym.line, ":", sym.column, "\n", + "\tFound ", found, " duplicated label\n" + )) {} + }; struct expecting_token_error : public parser_error { expecting_token_error(const std::string& expected, const std::string& context) : parser_error(details::concatenate_builder( diff --git a/src/molasses/lexer.cpp b/src/molasses/lexer.cpp index 7cbff64..ddc3c27 100644 --- a/src/molasses/lexer.cpp +++ b/src/molasses/lexer.cpp @@ -44,10 +44,6 @@ namespace molasses { }; for(auto& character : source) { - if(character == '\n') { - line++; - column = 0; - } column++; if(state == state_machine_t::string_escape) { switch(character) { @@ -79,6 +75,10 @@ namespace molasses { } else { builder << character; } + if(character == '\n') { + line++; + column = 0; + } } else { if(state == state_machine_t::string_end) { std::stringstream quoted; diff --git a/src/molasses/parser_primitives.cpp b/src/molasses/parser_primitives.cpp index 57480eb..6189dc2 100644 --- a/src/molasses/parser_primitives.cpp +++ b/src/molasses/parser_primitives.cpp @@ -176,12 +176,11 @@ namespace molasses { throw expecting_token_error(expected, context); \ }}while(false) - decltype(it) last_valid; + decltype(it) last_valid = it; 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("Procedure-Name", details::concatenate_builder("In top level, file ",last_valid->file_name, ":", last_valid->line, ":", last_valid->column)); @@ -227,8 +226,11 @@ namespace molasses { if(*ahead == GOTO_KW) { found_gotos[tokens.dictionary[*it]] = body.size(); } else if(*ahead == LABEL_KW) { - found_labels[tokens.dictionary[*it]] = body.size(); - // TODO: Handle duplicate labels + auto label_value = tokens.dictionary[*it]; + if(found_labels.contains(label_value)) { + throw duplicate_label_error(*it, label_value); + } + found_labels[label_value] = body.size(); } body.emplace_back(*it); body.emplace_back(*ahead);