A token that scans as an operator but is not one kills the process with
SIGABRT instead of reporting a compile error.
$ cat bad.arch
null main
methods
'START' : if 1 <> 2 then write "ne"
end
$ archetype --source=bad.arch
At bad.arch, line 3, column 17:
'START' : if 1 <> 2 then write "ne"
^
Unknown operator: <>
libc++abi: terminating
$ echo $?
134
<> is a plausible typo — it is the not-equal operator in Pascal, which is
what Archetype was originally written in, and the 1995 HOW-TO document uses it
in one of its examples. Whatever the input, the answer should be a diagnostic
and a clean exit.
Cause
TokenStream.cc:315-322 prints the position and message by hand and then calls
terminate():
else if (not Keywords::instance().Operators.has(s)) {
source_->showPosition(cout);
cout << "Unknown operator: " << s << endl;
terminate();
}
This is the only call to terminate() in src/.
What the neighbours do
Every other error in the same function reports and unwinds. Twelve lines
further down, an unterminated string literal does this:
source_->showPosition(cout);
throw std::runtime_error("Unterminated literal");
which is caught upstream and produces ERROR: Unterminated literal with exit
status 1. Ordinary parse errors go through errorMessage() and also exit 1.
Fix
errorMessage() already does the showPosition plus message that this site
open-codes, so the smallest correct change is to match the unterminated-literal
neighbour:
else if (not Keywords::instance().Operators.has(s)) {
source_->showPosition(cout);
throw std::runtime_error(format("Unknown operator: {}", s));
}
Returning false from fetch() instead would be tempting but wrong: false
means end of stream, so the caller would follow the real message with a
spurious "Expected Archetype statement, found end of file".
A test in TestTokenStream.cc asserting that scanning <> throws rather than
aborts would pin it. Worth checking at the same time whether any other input
reaches an abort — the exit status of a failed compile should be 1 for every
kind of bad input.
A token that scans as an operator but is not one kills the process with
SIGABRT instead of reporting a compile error.
<>is a plausible typo — it is the not-equal operator in Pascal, which iswhat Archetype was originally written in, and the 1995 HOW-TO document uses it
in one of its examples. Whatever the input, the answer should be a diagnostic
and a clean exit.
Cause
TokenStream.cc:315-322prints the position and message by hand and then callsterminate():This is the only call to
terminate()insrc/.What the neighbours do
Every other error in the same function reports and unwinds. Twelve lines
further down, an unterminated string literal does this:
which is caught upstream and produces
ERROR: Unterminated literalwith exitstatus 1. Ordinary parse errors go through
errorMessage()and also exit 1.Fix
errorMessage()already does theshowPositionplus message that this siteopen-codes, so the smallest correct change is to match the unterminated-literal
neighbour:
Returning
falsefromfetch()instead would be tempting but wrong:falsemeans end of stream, so the caller would follow the real message with a
spurious "Expected Archetype statement, found end of file".
A test in
TestTokenStream.ccasserting that scanning<>throws rather thanaborts would pin it. Worth checking at the same time whether any other input
reaches an abort — the exit status of a failed compile should be 1 for every
kind of bad input.