aboutsummaryrefslogtreecommitdiff
path: root/lib/Parser
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-21 14:03:31 +0000
committer_ov4 <ov4@ov4.org>2026-10-21 14:03:31 +0000
commitb4ffb2d9498560557821714e2d4651279dd6817c (patch)
tree995ad02bdb8cc461f48a53683c4fd7f2ddd8656b /lib/Parser
parentf1f5fa394a67a789914ccf2b24d534a0e466ae1b (diff)
feat(diagnostics): print source diagnostics in gcc file:line: layout
Lexer, parser, driver and codegen diagnostics now read "<path>:<line>: error: <message>" instead of "error: <message> at line N in <path>". The path is always printed as given on the command line. Call sites pass the bare message to cps::sourceError/sourceWarning, which carry printf format checking; reportError routes through the same helper. The suite iii harness parses the new layout and matches the reason against the message only. iii/template-class-pack-field passed only because its reason regex matched the case path, so it is now case-insensitive. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib/Parser')
-rw-r--r--lib/Parser/Parser.cc34
-rw-r--r--lib/Parser/ParserControlFlow.cc34
-rw-r--r--lib/Parser/ParserExpression.cc37
-rw-r--r--lib/Parser/ParserFile.cc15
-rw-r--r--lib/Parser/ParserFunction.cc97
-rw-r--r--lib/Parser/ParserType.cc97
6 files changed, 151 insertions, 163 deletions
diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc
index 3d45a97..b5c842f 100644
--- a/lib/Parser/Parser.cc
+++ b/lib/Parser/Parser.cc
@@ -100,7 +100,7 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
if (CurTok == tok_template) return ParseTemplateDecl();
if (CurTok == tok_extern) {
if (BlockDepth != 1) {
- sourceDiagnostic(Lex.getLine(), "error: EXTERN is only allowed at top level at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "EXTERN is only allowed at top level");
getNextToken();
return nullptr;
}
@@ -113,12 +113,12 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
int Line = Lex.getLine();
getNextToken();
if (BlockDepth != 1) {
- sourceDiagnostic(Line, "error: %s is only allowed at top level at line %d\n", Keyword, Line);
+ sourceError(Line, "%s is only allowed at top level", Keyword);
return nullptr;
}
if (Include) {
if (CurTok != tok_string_literal) {
- sourceDiagnostic(Line, "error: %s requires a string literal at line %d\n", Keyword, Line);
+ sourceError(Line, "%s requires a string literal", Keyword);
return nullptr;
}
std::unique_ptr<StmtAST> Stmt;
@@ -129,14 +129,14 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
}
auto Body = ParseBlock({tok_endglobal});
if (CurTok != tok_endglobal) {
- sourceDiagnostic(Line, "error: Expected ENDGLOBAL at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "Expected ENDGLOBAL");
return nullptr;
}
getNextToken();
return std::make_unique<GlobalBlockAST>(std::move(Body));
}
if (CurTok == tok_endglobal) {
- sourceDiagnostic(Lex.getLine(), "error: ENDGLOBAL without matching GLOBAL at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "ENDGLOBAL without matching GLOBAL");
getNextToken();
return nullptr;
}
@@ -144,7 +144,7 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
int Line = Lex.getLine();
getNextToken();
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: DELETE requires an object designator at line %d\n", Line);
+ cps::sourceError(Line, "DELETE requires an object designator");
return nullptr;
}
std::string Name = Lex.IdentifierStr;
@@ -156,7 +156,7 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
}
if (CurTok == tok_case) return ParseCaseStmt();
if (CurTok == tok_endcase || CurTok == tok_otherwise) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Unexpected CASE terminator at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Unexpected CASE terminator");
getNextToken();
return nullptr;
}
@@ -170,7 +170,7 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
else if (CurTok == tok_input) {
getNextToken();
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected variable name after INPUT at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected variable name after INPUT");
return nullptr;
}
std::string Name = Lex.IdentifierStr;
@@ -211,8 +211,8 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
return std::make_unique<ThrowStmtAST>();
}
else if (CurTok == tok_catch || CurTok == tok_endtry) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Unexpected %s without matching TRY at line %d\n",
- CurTok == tok_catch ? "CATCH" : "ENDTRY", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Unexpected %s without matching TRY",
+ CurTok == tok_catch ? "CATCH" : "ENDTRY");
getNextToken();
return nullptr;
}
@@ -230,7 +230,7 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
getNextToken();
if (CurTok == tok_function) return ParseFunction({}, true, true);
if (CurTok == tok_procedure) return ParseProcedure({}, true, true);
- cps::sourceDiagnostic(Line, "error: OVERLOAD must be followed by FUNCTION or PROCEDURE at line %d\n", Line);
+ cps::sourceError(Line, "OVERLOAD must be followed by FUNCTION or PROCEDURE");
return nullptr;
}
else if (CurTok == tok_function) {
@@ -261,22 +261,22 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() {
return ParseTypeDecl();
}
else if (CurTok == tok_define) {
- cps::sourceDiagnostic(Lex.getLine(), "error: DEFINE (SET literals) is not implemented at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "DEFINE (SET literals) is not implemented");
getNextToken();
return nullptr;
}
else if (CurTok == tok_endtype) {
- cps::sourceDiagnostic(Lex.getLine(), "error: ENDTYPE without matching TYPE at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "ENDTYPE without matching TYPE");
getNextToken();
return nullptr;
}
else if (CurTok == tok_endclass) {
- cps::sourceDiagnostic(Lex.getLine(), "error: ENDCLASS without matching CLASS at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "ENDCLASS without matching CLASS");
getNextToken();
return nullptr;
}
- cps::sourceDiagnostic(Lex.getLine(), "error: Unexpected token at line %d when expecting a statement\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Unexpected token when expecting a statement");
getNextToken(); // guarantee progress so error recovery cannot loop forever
return nullptr;
}
@@ -302,7 +302,7 @@ std::unique_ptr<StmtAST> Parser::ParseAssignStmt() {
if (!Parsed) return nullptr;
TemplateArgs = std::move(*Parsed);
if (CurTok != '(') {
- sourceDiagnostic(Line, "error: Expected '(' after explicit template arguments at line %d\n", Line);
+ sourceError(Line, "Expected '(' after explicit template arguments");
return nullptr;
}
}
@@ -329,7 +329,7 @@ std::unique_ptr<StmtAST> Parser::ParseAssignStmt() {
}
if (CurTok != tok_assign) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected '<-' after identifier '%s' at line %d\n", Name.c_str(), Line);
+ cps::sourceError(Line, "Expected '<-' after identifier '%s'", Name.c_str());
return nullptr;
}
getNextToken();
diff --git a/lib/Parser/ParserControlFlow.cc b/lib/Parser/ParserControlFlow.cc
index 8ca024d..8cb5c4e 100644
--- a/lib/Parser/ParserControlFlow.cc
+++ b/lib/Parser/ParserControlFlow.cc
@@ -9,13 +9,13 @@ std::unique_ptr<StmtAST> Parser::ParseTryStmt() {
getNextToken();
auto Body = ParseBlock({tok_catch, tok_endtry});
if (CurTok != tok_catch) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected CATCH in TRY at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected CATCH in TRY");
return nullptr;
}
getNextToken();
auto CatchBody = ParseBlock({tok_endtry, tok_catch});
if (CurTok != tok_endtry) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ENDTRY after CATCH at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ENDTRY after CATCH");
return nullptr;
}
getNextToken();
@@ -28,7 +28,7 @@ std::unique_ptr<StmtAST> Parser::ParseIfStmt() {
if (!Cond) return nullptr;
if (CurTok != tok_then) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected THEN at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "expected THEN");
return nullptr;
}
getNextToken();
@@ -42,7 +42,7 @@ std::unique_ptr<StmtAST> Parser::ParseIfStmt() {
}
if (CurTok != tok_endif) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected ENDIF at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "expected ENDIF");
return nullptr;
}
getNextToken();
@@ -60,7 +60,7 @@ std::unique_ptr<StmtAST> Parser::ParseWhileStmt() {
std::vector<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_endwhile});
if (CurTok != tok_endwhile) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected ENDWHILE\n");
+ cps::sourceError(Lex.getLine(), "expected ENDWHILE");
return nullptr;
}
getNextToken();
@@ -74,7 +74,7 @@ std::unique_ptr<StmtAST> Parser::ParseRepeatStmt() {
std::vector<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_until});
if (CurTok != tok_until) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected UNTIL\n");
+ cps::sourceError(Lex.getLine(), "expected UNTIL");
return nullptr;
}
getNextToken();
@@ -88,14 +88,14 @@ std::unique_ptr<StmtAST> Parser::ParseRepeatStmt() {
std::unique_ptr<StmtAST> Parser::ParseForStmt() {
getNextToken();
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected identifier after FOR\n");
+ cps::sourceError(Lex.getLine(), "expected identifier after FOR");
return nullptr;
}
std::string VarName = Lex.IdentifierStr;
getNextToken();
if (CurTok != tok_assign) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected '<-' in FOR loop\n");
+ cps::sourceError(Lex.getLine(), "expected '<-' in FOR loop");
return nullptr;
}
getNextToken();
@@ -104,7 +104,7 @@ std::unique_ptr<StmtAST> Parser::ParseForStmt() {
if (!Start) return nullptr;
if (CurTok != tok_to) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected TO in FOR loop\n");
+ cps::sourceError(Lex.getLine(), "expected TO in FOR loop");
return nullptr;
}
getNextToken();
@@ -122,18 +122,18 @@ std::unique_ptr<StmtAST> Parser::ParseForStmt() {
std::vector<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_next});
if (CurTok != tok_next) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected NEXT\n");
+ cps::sourceError(Lex.getLine(), "expected NEXT");
return nullptr;
}
getNextToken();
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected identifier after NEXT (e.g., NEXT %s)\n", VarName.c_str());
+ cps::sourceError(Lex.getLine(), "expected identifier after NEXT (e.g., NEXT %s)", VarName.c_str());
return nullptr;
}
if (!sameIdentifier(Lex.IdentifierStr, VarName)) {
- cps::sourceDiagnostic(Lex.getLine(), "error: NEXT identifier '%s' does not match FOR variable '%s'\n",
+ cps::sourceError(Lex.getLine(), "NEXT identifier '%s' does not match FOR variable '%s'",
Lex.IdentifierStr.c_str(), VarName.c_str());
return nullptr;
}
@@ -178,12 +178,12 @@ bool Parser::atCaseBoundary() {
std::unique_ptr<StmtAST> Parser::ParseCaseStmt() {
getNextToken();
if (CurTok != tok_of) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected OF after CASE at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected OF after CASE");
return nullptr;
}
getNextToken();
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected identifier after CASE OF at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected identifier after CASE OF");
return nullptr;
}
std::string Selector = Lex.IdentifierStr;
@@ -192,7 +192,7 @@ std::unique_ptr<StmtAST> Parser::ParseCaseStmt() {
bool SeenOtherwise = false;
while (CurTok != tok_endcase && CurTok != tok_eof) {
if (SeenOtherwise || !isCaseLabel()) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected CASE label on a new line (OTHERWISE must be last) at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected CASE label on a new line (OTHERWISE must be last)");
return nullptr;
}
CaseBranch Branch;
@@ -213,7 +213,7 @@ std::unique_ptr<StmtAST> Parser::ParseCaseStmt() {
if (!Branch.Lower) return nullptr;
}
if (CurTok != tok_colon) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ':' after CASE label at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ':' after CASE label");
return nullptr;
}
getNextToken();
@@ -221,7 +221,7 @@ std::unique_ptr<StmtAST> Parser::ParseCaseStmt() {
Branches.push_back(std::move(Branch));
}
if (CurTok != tok_endcase || Branches.empty()) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected nonempty CASE and ENDCASE at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected nonempty CASE and ENDCASE");
return nullptr;
}
getNextToken();
diff --git a/lib/Parser/ParserExpression.cc b/lib/Parser/ParserExpression.cc
index ef8e1d3..754d1f2 100644
--- a/lib/Parser/ParserExpression.cc
+++ b/lib/Parser/ParserExpression.cc
@@ -19,7 +19,7 @@ int Parser::GetTokPrecedence() {
bool Parser::ParseIntegerValue(bool Negative, int64_t &Out) {
const uint64_t Max = uint64_t(std::numeric_limits<int64_t>::max());
if (Lex.NumVal > Max + (Negative ? 1u : 0u)) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Integer literal is outside the i64 range at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Integer literal is outside the i64 range");
getNextToken();
return false;
}
@@ -88,14 +88,14 @@ std::unique_ptr<ExprAST> Parser::ParseIdentifierExpr() {
if (PackNames.count(IdName)) {
if (CurTok != tok_ellipsis) {
- sourceDiagnostic(Line, "error: A parameter pack must be expanded with '...' at line %d\n", Line);
+ sourceError(Line, "A parameter pack must be expanded with '...'");
return nullptr;
}
getNextToken();
return std::make_unique<PackExpansionExprAST>(IdName, Line);
}
if (CurTok == tok_ellipsis) {
- sourceDiagnostic(Line, "error: Only a parameter pack may be expanded at line %d\n", Line);
+ sourceError(Line, "Only a parameter pack may be expanded");
getNextToken();
return nullptr;
}
@@ -110,8 +110,7 @@ std::unique_ptr<ExprAST> Parser::ParseIdentifierExpr() {
auto Args = ParseExprList(')', true);
if (!Args) return nullptr;
if (CurTok == '[' || CurTok == '^') {
- cps::sourceDiagnostic(Lex.getLine(), "error: record/array/pointer access on a function result is not supported at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "record/array/pointer access on a function result is not supported");
return nullptr;
}
return ParseResultMethods(std::make_unique<CallExprAST>(IdName, std::move(*Args), Line, std::move(TemplateArgs)), Line);
@@ -135,7 +134,7 @@ std::unique_ptr<ExprAST> Parser::ParseIdentifierExpr() {
std::unique_ptr<MemberCallExprAST> Parser::ParseMemberCall(
const std::string &Name, std::vector<DesignatorAccess> Accesses, int Line) {
if (Accesses.empty() || Accesses.back().Kind != AccessKind::Field) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected a method name after '.' at line %d\n", Line);
+ cps::sourceError(Line, "Expected a method name after '.'");
return nullptr;
}
std::string Method = Accesses.back().FieldName;
@@ -149,8 +148,7 @@ std::unique_ptr<MemberCallExprAST> Parser::ParseMemberCall(
Args = std::move(*Parsed);
}
if (CurTok == '[' || CurTok == '^') {
- cps::sourceDiagnostic(Lex.getLine(), "error: record/array/pointer access on a function result is not supported at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "record/array/pointer access on a function result is not supported");
return nullptr;
}
auto Result = ParseResultMethods(std::make_unique<MemberCallExprAST>(std::move(Receiver), Method, std::move(Args), Line), Line);
@@ -172,7 +170,7 @@ bool Parser::ParseDesignatorSuffix(std::vector<DesignatorAccess> &Out) {
} else if (CurTok == '.') {
getNextToken();
if (CurTok != tok_identifier && CurTok != tok_new && CurTok != tok_delete && CurTok != tok_operator) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected field name after '.' at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected field name after '.'");
return false;
}
DesignatorAccess A;
@@ -209,7 +207,7 @@ std::unique_ptr<ExprAST> Parser::ParseParenExpr() {
std::string TypeName = ParseTypeName();
if (TypeName.empty()) return nullptr;
if (CurTok != ')') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ')' after cast type at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ')' after cast type");
return nullptr;
}
getNextToken();
@@ -220,7 +218,7 @@ std::unique_ptr<ExprAST> Parser::ParseParenExpr() {
auto V = ParseExpression();
if (!V) return nullptr;
if (CurTok != ')') {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected ')' at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "expected ')'");
return nullptr;
}
getNextToken();
@@ -239,11 +237,11 @@ std::unique_ptr<ExprAST> Parser::ParseResultMethods(std::unique_ptr<ExprAST> Exp
Name = CurTok == tok_delete ? "DELETE" : Lex.IdentifierStr;
getNextToken();
} else {
- sourceDiagnostic(Lex.getLine(), "error: Expected method name at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "Expected method name");
return nullptr;
}
if (CurTok != '(') {
- sourceDiagnostic(Lex.getLine(), "error: Expected '(' after method name at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "Expected '(' after method name");
return nullptr;
}
getNextToken();
@@ -264,7 +262,7 @@ std::unique_ptr<ExprAST> Parser::ParsePrimary() {
std::unique_ptr<ExprAST> Parser::ParsePrimaryImpl() {
switch (CurTok) {
case tok_new:
- cps::sourceDiagnostic(Lex.getLine(), "error: NEW is only allowed on the right of an assignment at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "NEW is only allowed on the right of an assignment");
return nullptr;
case tok_identifier: case tok_operator: return ParseIdentifierExpr();
case tok_number_int: return ParseNumberExpr();
@@ -289,8 +287,8 @@ std::unique_ptr<ExprAST> Parser::ParsePrimaryImpl() {
}
case '(': return ParseParenExpr();
default:
- cps::sourceDiagnostic(Lex.getLine(), "error: unknown token '%c' (%d) at line %d when expecting an expression\n",
- (char)CurTok, CurTok, Lex.getLine());
+ cps::sourceError(Lex.getLine(), "unknown token '%c' (%d) when expecting an expression",
+ (char)CurTok, CurTok);
return nullptr;
}
}
@@ -315,14 +313,13 @@ std::unique_ptr<ExprAST> Parser::ParseUnaryImpl() {
int Line = Lex.getLine();
getNextToken();
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: '^' (address-of) requires a variable, array element or record field at line %d\n",
- Line);
+ cps::sourceError(Line, "'^' (address-of) requires a variable, array element or record field");
return nullptr;
}
std::string BaseName = Lex.IdentifierStr;
getNextToken();
if (CurTok == '(') {
- cps::sourceDiagnostic(Lex.getLine(), "error: cannot take the address of a function result at line %d\n", Line);
+ cps::sourceError(Line, "cannot take the address of a function result");
return nullptr;
}
std::vector<DesignatorAccess> Accesses;
@@ -389,7 +386,7 @@ std::optional<std::vector<std::unique_ptr<ExprAST>>> Parser::ParseExprList(char
if (CurTok == CloseDelim) break;
if (CurTok != ',') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' or '%c' at line %d\n", CloseDelim, Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ',' or '%c'", CloseDelim);
return std::nullopt;
}
getNextToken();
diff --git a/lib/Parser/ParserFile.cc b/lib/Parser/ParserFile.cc
index 99a939f..c51c7e7 100644
--- a/lib/Parser/ParserFile.cc
+++ b/lib/Parser/ParserFile.cc
@@ -14,7 +14,7 @@ std::unique_ptr<StmtAST> Parser::ParseOpenFile() {
if (!FileName) return nullptr;
if (CurTok != tok_for) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected FOR after OPENFILE filename at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected FOR after OPENFILE filename");
return nullptr;
}
getNextToken(); // eat FOR
@@ -25,11 +25,10 @@ std::unique_ptr<StmtAST> Parser::ParseOpenFile() {
case tok_write: Mode = FileMode::Write; break;
case tok_append: Mode = FileMode::Append; break;
case tok_random:
- cps::sourceDiagnostic(Lex.getLine(), "error: File mode RANDOM is not implemented (text files only) at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "File mode RANDOM is not implemented (text files only)");
return nullptr;
default:
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected file mode READ, WRITE or APPEND at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected file mode READ, WRITE or APPEND");
return nullptr;
}
getNextToken(); // eat the mode keyword
@@ -46,13 +45,13 @@ std::unique_ptr<StmtAST> Parser::ParseReadFile() {
if (!FileName) return nullptr;
if (CurTok != ',') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' after READFILE filename at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ',' after READFILE filename");
return nullptr;
}
getNextToken(); // eat ','
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected variable name after ',' in READFILE at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected variable name after ',' in READFILE");
return nullptr;
}
std::string VarName = Lex.IdentifierStr;
@@ -62,7 +61,7 @@ std::unique_ptr<StmtAST> Parser::ParseReadFile() {
// Consume the whole designator so it cannot replay as statements.
std::vector<DesignatorAccess> Dummy;
ParseDesignatorSuffix(Dummy);
- cps::sourceDiagnostic(Lex.getLine(), "error: READFILE target must be a plain STRING variable at line %d\n", Line);
+ cps::sourceError(Line, "READFILE target must be a plain STRING variable");
return nullptr;
}
@@ -78,7 +77,7 @@ std::unique_ptr<StmtAST> Parser::ParseWriteFile() {
if (!FileName) return nullptr;
if (CurTok != ',') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' after WRITEFILE filename at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ',' after WRITEFILE filename");
return nullptr;
}
getNextToken(); // eat ','
diff --git a/lib/Parser/ParserFunction.cc b/lib/Parser/ParserFunction.cc
index a1f04c0..823e17f 100644
--- a/lib/Parser/ParserFunction.cc
+++ b/lib/Parser/ParserFunction.cc
@@ -15,8 +15,7 @@ bool Parser::ParseSignedIntBound(int64_t &Out) {
getNextToken();
}
if (CurTok != tok_number_int) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Array parameter bounds must be integer literals at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Array parameter bounds must be integer literals");
return false;
}
return ParseIntegerValue(Negative, Out);
@@ -37,8 +36,7 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef
while (CurTok != ')') {
if (CurTok == tok_byref) {
if (!AllowByRef) {
- cps::sourceDiagnostic(Lex.getLine(), "error: BYREF parameters are not allowed in a FUNCTION (procedures only) at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "BYREF parameters are not allowed in a FUNCTION (procedures only)");
return std::nullopt;
}
Current = PassMode::ByRef;
@@ -49,7 +47,7 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef
}
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected argument name at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected argument name");
return std::nullopt;
}
ParamDecl P;
@@ -59,7 +57,7 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef
getNextToken();
if (CurTok != tok_colon) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ':' after argument name at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ':' after argument name");
return std::nullopt;
}
getNextToken();
@@ -73,8 +71,7 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef
int64_t Lo = 0, Hi = 0;
if (!ParseSignedIntBound(Lo)) return std::nullopt;
if (CurTok != tok_colon) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ':' between array parameter bounds at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ':' between array parameter bounds");
return std::nullopt;
}
getNextToken();
@@ -82,8 +79,7 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef
P.DeclaredBounds.emplace_back(Lo, Hi);
if (CurTok == ']') break;
if (CurTok != ',') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' or ']' in array parameter bounds at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ',' or ']' in array parameter bounds");
return std::nullopt;
}
getNextToken();
@@ -94,8 +90,8 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef
P.Rank = 1; // ARRAY OF T: bounds travel with the argument
}
if (CurTok != tok_of) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected OF after ARRAY in parameter '%s' at line %d\n",
- P.Name.c_str(), Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected OF after ARRAY in parameter '%s'",
+ P.Name.c_str());
return std::nullopt;
}
getNextToken();
@@ -103,29 +99,29 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef
P.TypeName = ParseTypeName(false);
if (P.TypeName.empty()) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected argument type for '%s'\n", P.Name.c_str());
+ cps::sourceError(Lex.getLine(), "Expected argument type for '%s'", P.Name.c_str());
return std::nullopt;
}
if (CurTok == tok_ellipsis) {
if (P.IsArray || !isTemplatePack(P.TypeName)) {
- sourceDiagnostic(P.Line, "error: A pack parameter must use the current template pack and cannot be ARRAY at line %d\n", P.Line);
+ sourceError(P.Line, "A pack parameter must use the current template pack and cannot be ARRAY");
return std::nullopt;
}
P.IsPack = true;
getNextToken();
if (CurTok != ')') {
- sourceDiagnostic(P.Line, "error: A pack parameter must be last at line %d\n", P.Line);
+ sourceError(P.Line, "A pack parameter must be last");
return std::nullopt;
}
} else if (isTemplatePack(P.TypeName)) {
- sourceDiagnostic(P.Line, "error: A template parameter pack requires '...' at line %d\n", P.Line);
+ sourceError(P.Line, "A template parameter pack requires '...'");
return std::nullopt;
}
for (const ParamDecl &Prev : Params) {
if (sameIdentifier(Prev.Name, P.Name)) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Duplicate parameter name '%s' at line %d\n",
- P.Name.c_str(), Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Duplicate parameter name '%s'",
+ P.Name.c_str());
return std::nullopt;
}
}
@@ -133,12 +129,12 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef
if (CurTok == ')') break;
if (CurTok != ',') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' or ')'\n");
+ cps::sourceError(Lex.getLine(), "Expected ',' or ')'");
return std::nullopt;
}
getNextToken();
if (CurTok == ')') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected another parameter after ',' at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected another parameter after ','");
return std::nullopt;
}
}
@@ -150,13 +146,13 @@ std::string Parser::ParseOperatorName(int &Op) {
getNextToken(); // OPERATOR
Op = CurTok;
if (operatorSpelling(Op).empty()) {
- sourceDiagnostic(Lex.getLine(), "error: Expected a supported operator after OPERATOR at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "Expected a supported operator after OPERATOR");
getNextToken();
return {};
}
getNextToken();
if (CurTok != '(') {
- sourceDiagnostic(Lex.getLine(), "error: Expected '(' after operator name at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "Expected '(' after operator name");
return {};
}
return operatorName(Op);
@@ -166,15 +162,15 @@ std::unique_ptr<FunctionDefAST> Parser::ParseFunction(const std::string &OwnerCl
int Line = Lex.getLine();
getNextToken();
if (CurTok == tok_delete || (CurTok == tok_identifier && sameIdentifier(Lex.IdentifierStr, "DELETE"))) {
- cps::sourceDiagnostic(Lex.getLine(), "error: destructor DELETE must be a PROCEDURE at line %d\n", Line);
+ cps::sourceError(Line, "destructor DELETE must be a PROCEDURE");
return nullptr;
}
if (CurTok == tok_new || (CurTok == tok_identifier && sameIdentifier(Lex.IdentifierStr, "NEW"))) {
- cps::sourceDiagnostic(Lex.getLine(), "error: constructor NEW must be a PROCEDURE at line %d\n", Line);
+ cps::sourceError(Line, "constructor NEW must be a PROCEDURE");
return nullptr;
}
if (CurTok != tok_identifier && CurTok != tok_operator) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected function name\n");
+ cps::sourceError(Lex.getLine(), "Expected function name");
return nullptr;
}
@@ -184,7 +180,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseFunction(const std::string &OwnerCl
Name = ParseOperatorName(Operator);
if (Name.empty()) return nullptr;
if (!IsOverload) {
- sourceDiagnostic(Line, "error: An operator function must be declared OVERLOAD at line %d\n", Line);
+ sourceError(Line, "An operator function must be declared OVERLOAD");
return nullptr;
}
} else {
@@ -199,13 +195,12 @@ std::unique_ptr<FunctionDefAST> Parser::ParseFunction(const std::string &OwnerCl
if (CurTok == tok_returns) {
getNextToken();
if (CurTok == tok_array) {
- cps::sourceDiagnostic(Lex.getLine(), "error: A FUNCTION cannot RETURN an array; use a BYREF PROCEDURE parameter instead at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "A FUNCTION cannot RETURN an array; use a BYREF PROCEDURE parameter instead");
return nullptr;
}
RetType = ParseTypeName(true);
if (RetType.empty()) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected return type for function '%s'\n", Name.c_str());
+ cps::sourceError(Lex.getLine(), "Expected return type for function '%s'", Name.c_str());
return nullptr;
}
}
@@ -220,7 +215,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseFunction(const std::string &OwnerCl
PackNames = std::move(SavedPacks);
if (CurTok != tok_endfunction) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected ENDFUNCTION\n");
+ cps::sourceError(Lex.getLine(), "expected ENDFUNCTION");
return nullptr;
}
getNextToken();
@@ -234,7 +229,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerC
int Line = Lex.getLine();
getNextToken();
if (CurTok != tok_identifier && CurTok != tok_new && CurTok != tok_delete && CurTok != tok_operator) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected procedure name\n");
+ cps::sourceError(Lex.getLine(), "Expected procedure name");
return nullptr;
}
@@ -245,17 +240,17 @@ std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerC
OperatorName = ParseOperatorName(Operator);
if (OperatorName.empty()) return nullptr;
if (Operator != tok_assign || OwnerClass.empty() || !IsOverload) {
- sourceDiagnostic(Line, "error: Assignment operator must be an OVERLOAD member PROCEDURE at line %d\n", Line);
+ sourceError(Line, "Assignment operator must be an OVERLOAD member PROCEDURE");
return nullptr;
}
}
std::string Name = IsOperator ? OperatorName : CurTok == tok_new ? "NEW" : CurTok == tok_delete ? "DELETE" : Lex.IdentifierStr;
if (OwnerClass.empty() && sameIdentifier(Name, "DELETE")) {
- cps::sourceDiagnostic(Lex.getLine(), "error: destructor DELETE is only allowed in a CLASS at line %d\n", Line);
+ cps::sourceError(Line, "destructor DELETE is only allowed in a CLASS");
return nullptr;
}
if (OwnerClass.empty() && sameIdentifier(Name, "NEW")) {
- cps::sourceDiagnostic(Lex.getLine(), "error: constructor NEW is only allowed in a CLASS at line %d\n", Line);
+ cps::sourceError(Line, "constructor NEW is only allowed in a CLASS");
return nullptr;
}
if (!IsOperator) getNextToken();
@@ -263,7 +258,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerC
auto Args = ParsePrototypeArgs(/*AllowByRef=*/true);
if (!Args) return nullptr;
if (sameIdentifier(Name, "DELETE") && !Args->empty()) {
- cps::sourceDiagnostic(Lex.getLine(), "error: destructor DELETE must have no parameters at line %d\n", Line);
+ cps::sourceError(Line, "destructor DELETE must have no parameters");
return nullptr;
}
auto Proto = std::make_unique<PrototypeAST>(Name, std::move(*Args), "VOID", false, OwnerClass, IsPublic, IsOverload);
@@ -276,7 +271,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerC
PackNames = std::move(SavedPacks);
if (CurTok != tok_endprocedure) {
- cps::sourceDiagnostic(Lex.getLine(), "error: expected ENDPROCEDURE\n");
+ cps::sourceError(Lex.getLine(), "expected ENDPROCEDURE");
return nullptr;
}
getNextToken();
@@ -293,19 +288,18 @@ std::unique_ptr<StmtAST> Parser::ParseExternDecl() {
int Line = Lex.getLine();
getNextToken();
if (CurTok != tok_string_literal || Lex.StringVal != "C") {
- cps::sourceDiagnostic(Lex.getLine(), "error: EXTERN must be followed by \"C\" at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "EXTERN must be followed by \"C\"");
return nullptr;
}
getNextToken();
if (CurTok != tok_extern_function && CurTok != tok_extern_procedure) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected EXTERN_FUNCTION or EXTERN_PROCEDURE after EXTERN \"C\" at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected EXTERN_FUNCTION or EXTERN_PROCEDURE after EXTERN \"C\"");
return nullptr;
}
bool IsFunction = CurTok == tok_extern_function;
getNextToken();
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected C function name at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected C function name");
return nullptr;
}
std::string Name = Lex.IdentifierStr;
@@ -314,8 +308,8 @@ std::unique_ptr<StmtAST> Parser::ParseExternDecl() {
std::vector<ParamDecl> Params;
bool IsVariadic = false;
if (CurTok != '(') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected '(' after C function name '%s' at line %d\n",
- Name.c_str(), Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected '(' after C function name '%s'",
+ Name.c_str());
return nullptr;
}
getNextToken();
@@ -324,14 +318,13 @@ std::unique_ptr<StmtAST> Parser::ParseExternDecl() {
IsVariadic = true;
getNextToken();
if (CurTok != ')') {
- cps::sourceDiagnostic(Lex.getLine(), "error: '...' must be the last parameter at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "'...' must be the last parameter");
return nullptr;
}
break;
}
if (CurTok == tok_byref || CurTok == tok_byval) {
- cps::sourceDiagnostic(Lex.getLine(), "error: EXTERN parameters cannot be BYREF or BYVAL; use a C pointer type at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "EXTERN parameters cannot be BYREF or BYVAL; use a C pointer type");
return nullptr;
}
ParamDecl P;
@@ -342,12 +335,12 @@ std::unique_ptr<StmtAST> Parser::ParseExternDecl() {
Params.push_back(std::move(P));
if (CurTok == ')') break;
if (CurTok != ',') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' or ')' at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ',' or ')'");
return nullptr;
}
getNextToken();
if (CurTok == ')') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected another parameter after ',' at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected another parameter after ','");
return nullptr;
}
}
@@ -356,15 +349,15 @@ std::unique_ptr<StmtAST> Parser::ParseExternDecl() {
std::string RetType = "VOID";
if (CurTok == tok_returns) {
if (!IsFunction) {
- cps::sourceDiagnostic(Lex.getLine(), "error: EXTERN_PROCEDURE cannot have RETURNS at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "EXTERN_PROCEDURE cannot have RETURNS");
return nullptr;
}
getNextToken();
RetType = ParseTypeName(false);
if (RetType.empty()) return nullptr;
} else if (IsFunction) {
- cps::sourceDiagnostic(Lex.getLine(), "error: EXTERN_FUNCTION '%s' requires RETURNS at line %d\n",
- Name.c_str(), Line);
+ cps::sourceError(Line, "EXTERN_FUNCTION '%s' requires RETURNS",
+ Name.c_str());
return nullptr;
}
@@ -379,7 +372,7 @@ std::unique_ptr<StmtAST> Parser::ParseCallStmt() {
int Line = Lex.getLine();
getNextToken();
if (CurTok != tok_identifier && CurTok != tok_operator) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected callee name after CALL\n");
+ cps::sourceError(Lex.getLine(), "Expected callee name after CALL");
return nullptr;
}
@@ -399,7 +392,7 @@ std::unique_ptr<StmtAST> Parser::ParseCallStmt() {
if (!Parsed) return nullptr;
TemplateArgs = std::move(*Parsed);
if (CurTok != '(') {
- sourceDiagnostic(Line, "error: Expected '(' after explicit template arguments at line %d\n", Line);
+ sourceError(Line, "Expected '(' after explicit template arguments");
return nullptr;
}
}
diff --git a/lib/Parser/ParserType.cc b/lib/Parser/ParserType.cc
index 21696d0..22cffeb 100644
--- a/lib/Parser/ParserType.cc
+++ b/lib/Parser/ParserType.cc
@@ -18,7 +18,7 @@ std::unique_ptr<StmtAST> Parser::ParseTemplateDecl() {
bool AtTopLevel = BlockDepth == 1 && CurrentTemplate.empty();
getNextToken();
if (CurTok != '<') {
- sourceDiagnostic(Line, "error: Expected '<' after TEMPLATE at line %d\n", Line);
+ sourceError(Line, "Expected '<' after TEMPLATE");
return nullptr;
}
getNextToken();
@@ -28,19 +28,19 @@ std::unique_ptr<StmtAST> Parser::ParseTemplateDecl() {
bool SeenPack = false;
while (true) {
if (CurTok != tok_identifier) {
- sourceDiagnostic(Lex.getLine(), "error: Expected template parameter name at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "Expected template parameter name");
return nullptr;
}
TemplateParam P{Lex.IdentifierStr, false, Lex.getLine()};
if (!Names.insert(P.Name).second) {
- sourceDiagnostic(P.Line, "error: Duplicate template parameter '%s' at line %d\n", P.Name.c_str(), P.Line);
+ sourceError(P.Line, "Duplicate template parameter '%s'", P.Name.c_str());
Invalid = true;
}
getNextToken();
if (CurTok == tok_ellipsis) {
P.IsPack = true;
if (SeenPack) {
- sourceDiagnostic(P.Line, "error: A template may have only one parameter pack at line %d\n", P.Line);
+ sourceError(P.Line, "A template may have only one parameter pack");
Invalid = true;
}
SeenPack = true;
@@ -49,11 +49,11 @@ std::unique_ptr<StmtAST> Parser::ParseTemplateDecl() {
Params.push_back(std::move(P));
if (CurTok == '>') break;
if (CurTok != ',') {
- sourceDiagnostic(Lex.getLine(), "error: Expected ',' or '>' in TEMPLATE at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "Expected ',' or '>' in TEMPLATE");
return nullptr;
}
if (Params.back().IsPack) {
- sourceDiagnostic(Params.back().Line, "error: A template parameter pack must be last at line %d\n", Params.back().Line);
+ sourceError(Params.back().Line, "A template parameter pack must be last");
Invalid = true;
}
getNextToken();
@@ -70,7 +70,7 @@ std::unique_ptr<StmtAST> Parser::ParseTemplateDecl() {
if (CurTok == tok_function || CurTok == tok_procedure) {
bool Operator = Lex.peekToken() == tok_operator;
if (Operator) {
- sourceDiagnostic(Line, "error: Operator templates are not supported at line %d\n", Line);
+ sourceError(Line, "Operator templates are not supported");
Invalid = true;
int End = CurTok == tok_function ? tok_endfunction : tok_endprocedure;
do { getNextToken(); } while (CurTok != End && CurTok != tok_eof);
@@ -89,17 +89,17 @@ std::unique_ptr<StmtAST> Parser::ParseTemplateDecl() {
std::unique_ptr<ClassTypeDeclAST>(static_cast<ClassTypeDeclAST *>(Class.release())));
}
} else if (CurTok == tok_type) {
- sourceDiagnostic(Line, "error: TEMPLATE cannot prefix TYPE; use CLASS at line %d\n", Line);
+ sourceError(Line, "TEMPLATE cannot prefix TYPE; use CLASS");
ParseTypeDecl();
Invalid = true;
} else {
- sourceDiagnostic(Line, "error: TEMPLATE must be followed by FUNCTION, PROCEDURE or CLASS at line %d\n", Line);
+ sourceError(Line, "TEMPLATE must be followed by FUNCTION, PROCEDURE or CLASS");
Invalid = true;
}
CurrentTemplate = std::move(SavedTemplate);
TypeNames = std::move(SavedTypes);
if (!AtTopLevel) {
- sourceDiagnostic(Line, "error: TEMPLATE declarations are only allowed at top level at line %d\n", Line);
+ sourceError(Line, "TEMPLATE declarations are only allowed at top level");
Invalid = true;
}
if (Invalid || !Decl) return nullptr;
@@ -117,7 +117,7 @@ std::optional<std::vector<std::string>> Parser::ParseTemplateArgs() {
if (Type.empty()) return std::nullopt;
if (CurTok == tok_ellipsis) {
if (!isTemplatePack(Type)) {
- sourceDiagnostic(Line, "error: Only the current template parameter pack may use '...' in a type argument at line %d\n", Line);
+ sourceError(Line, "Only the current template parameter pack may use '...' in a type argument");
return std::nullopt;
}
Type += "...";
@@ -126,7 +126,7 @@ std::optional<std::vector<std::string>> Parser::ParseTemplateArgs() {
Args.push_back(std::move(Type));
if (CurTok == '>') break;
if (CurTok != ',') {
- sourceDiagnostic(Lex.getLine(), "error: Expected ',' or '>' in template arguments at line %d\n", Lex.getLine());
+ sourceError(Lex.getLine(), "Expected ',' or '>' in template arguments");
return std::nullopt;
}
getNextToken();
@@ -153,7 +153,7 @@ std::unique_ptr<StmtAST> Parser::ParseTypeDecl() {
getNextToken(); // eat TYPE or CLASS
if (CurTok != tok_identifier && !(IsClass && CurTok == tok_string_kw)) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected type name after %s at line %d\n", Keyword, Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected type name after %s", Keyword);
if (IsClass) ParseRecordBody("<unnamed>", Line, tok_endclass);
return nullptr;
}
@@ -169,18 +169,18 @@ std::unique_ptr<StmtAST> Parser::ParseTypeDecl() {
if (CurTok == tok_c_type) {
getNextToken();
if (CurTok != '(') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected '(' after C_TYPE at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected '(' after C_TYPE");
return nullptr;
}
getNextToken();
if (CurTok != tok_string_literal) {
- cps::sourceDiagnostic(Lex.getLine(), "error: C_TYPE requires a string literal at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "C_TYPE requires a string literal");
return nullptr;
}
std::string Expression = Lex.StringVal;
getNextToken();
if (CurTok != ')') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ')' after C_TYPE string at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ')' after C_TYPE string");
return nullptr;
}
getNextToken();
@@ -190,16 +190,16 @@ std::unique_ptr<StmtAST> Parser::ParseTypeDecl() {
std::vector<std::string> Values;
while (true) {
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected an enum value name in TYPE %s at line %d\n",
- Name.c_str(), Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected an enum value name in TYPE %s",
+ Name.c_str());
return nullptr;
}
Values.push_back(Lex.IdentifierStr);
getNextToken();
if (CurTok == ')') break;
if (CurTok != ',') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' or ')' in TYPE %s at line %d\n",
- Name.c_str(), Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ',' or ')' in TYPE %s",
+ Name.c_str());
return nullptr;
}
getNextToken();
@@ -212,12 +212,12 @@ std::unique_ptr<StmtAST> Parser::ParseTypeDecl() {
if (Pointee.empty()) return nullptr;
Decl = std::make_unique<PointerTypeDeclAST>(Name, Pointee);
} else if (CurTok == tok_set) {
- cps::sourceDiagnostic(Lex.getLine(), "error: SET OF types are not implemented at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "SET OF types are not implemented");
getNextToken();
return nullptr;
} else {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected '(', '^' or C_TYPE after '=' in TYPE %s at line %d\n",
- Name.c_str(), Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected '(', '^' or C_TYPE after '=' in TYPE %s",
+ Name.c_str());
return nullptr;
}
} else {
@@ -231,7 +231,7 @@ std::unique_ptr<StmtAST> Parser::ParseTypeDecl() {
}
if (!AtTopLevel) {
- cps::sourceDiagnostic(Lex.getLine(), "error: %s declarations are only allowed at top level at line %d\n", Keyword, Line);
+ cps::sourceError(Line, "%s declarations are only allowed at top level", Keyword);
return nullptr;
}
TypeNames.insert(Name);
@@ -272,7 +272,7 @@ std::optional<std::vector<RecordFieldDecl>> Parser::ParseRecordBody(
bool IsOverload = CurTok == tok_overload;
if (IsOverload) getNextToken();
if (CurTok != tok_function && CurTok != tok_procedure) {
- cps::sourceDiagnostic(Lex.getLine(), "error: OVERLOAD must be followed by FUNCTION or PROCEDURE at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "OVERLOAD must be followed by FUNCTION or PROCEDURE");
HadFieldError = true;
continue;
}
@@ -284,9 +284,9 @@ std::optional<std::vector<RecordFieldDecl>> Parser::ParseRecordBody(
}
} else if (ParseRecordField(Fields, IsPublic)) continue;
} else {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected %s or %s in %s %s at line %d\n",
+ cps::sourceError(Lex.getLine(), "Expected %s or %s in %s %s",
IsClass ? "field, method, PUBLIC or PRIVATE" : "DECLARE", EndKeyword,
- Keyword, Name.c_str(), Lex.getLine());
+ Keyword, Name.c_str());
}
HadFieldError = true;
// Consume invalid bodies rather than replaying their contents as
@@ -305,14 +305,14 @@ std::optional<std::vector<RecordFieldDecl>> Parser::ParseRecordBody(
}
}
if (CurTok != EndToken) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected %s in %s %s at line %d\n",
- EndKeyword, Keyword, Name.c_str(), Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected %s in %s %s",
+ EndKeyword, Keyword, Name.c_str());
return std::nullopt;
}
getNextToken(); // eat body terminator
if (Fields.empty() && (!Methods || Methods->empty()) && !HadFieldError) {
- cps::sourceDiagnostic(Lex.getLine(), "error: %s %s has no %s at line %d\n", Keyword, Name.c_str(),
- IsClass ? "members" : "fields", Line);
+ cps::sourceError(Line, "%s %s has no %s", Keyword, Name.c_str(),
+ IsClass ? "members" : "fields");
return std::nullopt;
}
if (HadFieldError) return std::nullopt;
@@ -326,29 +326,28 @@ bool Parser::ParseRecordField(std::vector<RecordFieldDecl> &Out, bool IsPublic)
: CurTok == tok_public ? "PUBLIC" : "PRIVATE";
if (CurTok != tok_identifier) getNextToken(); // optional class access keyword
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected field name after %s at line %d\n", Introducer, Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected field name after %s", Introducer);
return false;
}
std::string FieldName = Lex.IdentifierStr;
getNextToken();
if (CurTok != tok_colon) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ':' after field name %s at line %d\n",
- FieldName.c_str(), Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ':' after field name %s",
+ FieldName.c_str());
return false;
}
getNextToken();
if (CurTok == tok_array) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Array fields inside records are not implemented at line %d\n",
- Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Array fields inside records are not implemented");
return false;
}
std::string TypeName = ParseTypeName(false);
if (TypeName.empty()) return false;
if (CurTok == tok_ellipsis || isTemplatePack(TypeName)) {
- sourceDiagnostic(Line, "error: Pack fields are not supported at line %d\n", Line);
+ sourceError(Line, "Pack fields are not supported");
if (CurTok == tok_ellipsis) getNextToken();
return false;
}
@@ -388,7 +387,7 @@ std::string Parser::ParseTypeName(bool AllowVoid) {
if (CurTok == tok_identifier) {
std::string TypeName = Lex.IdentifierStr;
if (!AllowVoid && sameIdentifier(TypeName, "VOID")) {
- cps::sourceDiagnostic(Lex.getLine(), "error: VOID is not allowed here\n");
+ cps::sourceError(Lex.getLine(), "VOID is not allowed here");
return "";
}
getNextToken();
@@ -405,7 +404,7 @@ std::string Parser::ParseTypeName(bool AllowVoid) {
return TypeName;
}
- cps::sourceDiagnostic(Lex.getLine(), "error: Unknown type name\n");
+ cps::sourceError(Lex.getLine(), "Unknown type name");
return "";
}
@@ -413,14 +412,14 @@ std::string Parser::ParseTypeName(bool AllowVoid) {
std::unique_ptr<StmtAST> Parser::ParseDeclare() {
getNextToken();
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected identifier after DECLARE at line %d\n", Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected identifier after DECLARE");
return nullptr;
}
std::string Name = Lex.IdentifierStr;
getNextToken();
if (CurTok != tok_colon) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ':' after variable name '%s' at line %d\n", Name.c_str(), Lex.getLine());
+ cps::sourceError(Lex.getLine(), "Expected ':' after variable name '%s'", Name.c_str());
return nullptr;
}
getNextToken();
@@ -428,7 +427,7 @@ std::unique_ptr<StmtAST> Parser::ParseDeclare() {
if (CurTok == tok_array) {
getNextToken();
if (CurTok != '[') {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected '[' after ARRAY\n");
+ cps::sourceError(Lex.getLine(), "Expected '[' after ARRAY");
return nullptr;
}
getNextToken();
@@ -440,7 +439,7 @@ std::unique_ptr<StmtAST> Parser::ParseDeclare() {
if (!Lower) return nullptr;
if (CurTok != tok_colon) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ':' in array range (e.g. 1:10)\n");
+ cps::sourceError(Lex.getLine(), "Expected ':' in array range (e.g. 1:10)");
return nullptr;
}
getNextToken();
@@ -455,13 +454,13 @@ std::unique_ptr<StmtAST> Parser::ParseDeclare() {
getNextToken();
continue;
}
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' or ']' in array dims\n");
+ cps::sourceError(Lex.getLine(), "Expected ',' or ']' in array dims");
return nullptr;
}
getNextToken();
if (CurTok != tok_of) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected OF after array dims\n");
+ cps::sourceError(Lex.getLine(), "Expected OF after array dims");
return nullptr;
}
getNextToken();
@@ -494,13 +493,13 @@ std::unique_ptr<StmtAST> Parser::ParseConstant() {
int Line = Lex.getLine();
getNextToken();
if (CurTok != tok_identifier) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected identifier after CONSTANT at line %d\n", Line);
+ cps::sourceError(Line, "Expected identifier after CONSTANT");
return nullptr;
}
std::string Name = Lex.IdentifierStr;
getNextToken();
if (CurTok != tok_eq) {
- cps::sourceDiagnostic(Lex.getLine(), "error: Expected '=' in CONSTANT declaration at line %d\n", Line);
+ cps::sourceError(Line, "Expected '=' in CONSTANT declaration");
return nullptr;
}
getNextToken();
@@ -510,7 +509,7 @@ std::unique_ptr<StmtAST> Parser::ParseConstant() {
bool Literal = Numeric || CurTok == tok_true || CurTok == tok_false ||
CurTok == tok_string_literal || CurTok == tok_c_string_literal || CurTok == tok_char_literal;
if (!Literal || (Negative && !Numeric)) {
- cps::sourceDiagnostic(Lex.getLine(), "error: CONSTANT initializer must be a literal at line %d\n", Line);
+ cps::sourceError(Line, "CONSTANT initializer must be a literal");
return nullptr;
}
std::unique_ptr<ExprAST> Value;
@@ -526,7 +525,7 @@ std::unique_ptr<StmtAST> Parser::ParseConstant() {
if (Negative) Value = std::make_unique<UnaryExprAST>('-', std::move(Value));
}
if (GetTokPrecedence() >= 0) {
- cps::sourceDiagnostic(Lex.getLine(), "error: CONSTANT initializer must be a literal, not an expression, at line %d\n", Line);
+ cps::sourceError(Line, "CONSTANT initializer must be a literal, not an expression");
return nullptr;
}
return std::make_unique<ConstantStmtAST>(std::move(Name), std::move(Value));