diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-17 10:30:02 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-17 10:30:02 +0000 |
| commit | f5246db6d045ffb86d6717e1b1c37f03bcb2b75b (patch) | |
| tree | 468f4fba2e7ef75f29f90fd64af7d4e1fe05f50f | |
| parent | 066a378ca09ccc5d8074a942cf4bf1b9d4f40729 (diff) | |
feat(parser): parse OVERLOAD prefix on FUNCTION and PROCEDURE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | include/cps/FunctionAST.h | 6 | ||||
| -rw-r--r-- | include/cps/Lexer.h | 1 | ||||
| -rw-r--r-- | include/cps/Parser.h | 4 | ||||
| -rw-r--r-- | lib/Lexer/Lexer.cc | 1 | ||||
| -rw-r--r-- | lib/Parser/Parser.cc | 10 | ||||
| -rw-r--r-- | lib/Parser/ParserFunction.cc | 8 | ||||
| -rw-r--r-- | lib/Parser/ParserType.cc | 17 | ||||
| -rw-r--r-- | tests/iii/overload-syntax-error/case.json | 1 | ||||
| -rw-r--r-- | tests/iii/overload-syntax-error/program.cps | 1 |
9 files changed, 35 insertions, 14 deletions
diff --git a/include/cps/FunctionAST.h b/include/cps/FunctionAST.h index 4dfe908..9995a4c 100644 --- a/include/cps/FunctionAST.h +++ b/include/cps/FunctionAST.h @@ -30,6 +30,7 @@ class PrototypeAST { std::vector<ParamDecl> Params; std::string ReturnType; bool IsExternal; + bool IsOverload; std::string OwnerClass; bool IsPublic; @@ -37,13 +38,14 @@ public: PrototypeAST(const std::string &Name, std::vector<ParamDecl> Params, const std::string &ReturnType, - bool IsExternal = false, std::string OwnerClass = {}, bool IsPublic = true) - : Name(Name), Params(std::move(Params)), ReturnType(ReturnType), IsExternal(IsExternal), + bool IsExternal = false, std::string OwnerClass = {}, bool IsPublic = true, bool IsOverload = false) + : Name(Name), Params(std::move(Params)), ReturnType(ReturnType), IsExternal(IsExternal), IsOverload(IsOverload), OwnerClass(std::move(OwnerClass)), IsPublic(IsPublic) {} const std::string &getName() const { return Name; } const std::vector<ParamDecl> &getParams() const { return Params; } const std::string &getReturnType() const { return ReturnType; } + bool isOverload() const { return IsOverload; } bool isExternal() const { return IsExternal; } const std::string &getOwnerClass() const { return OwnerClass; } bool isPublic() const { return IsPublic; } diff --git a/include/cps/Lexer.h b/include/cps/Lexer.h index 957ca48..40f168e 100644 --- a/include/cps/Lexer.h +++ b/include/cps/Lexer.h @@ -67,6 +67,7 @@ enum Token { tok_colon = -300, // : + tok_overload = -399, tok_function = -400, tok_endfunction = -401, tok_return = -402, diff --git a/include/cps/Parser.h b/include/cps/Parser.h index 9a53e95..d9e8358 100644 --- a/include/cps/Parser.h +++ b/include/cps/Parser.h @@ -73,8 +73,8 @@ class Parser { std::vector<std::unique_ptr<FunctionDefAST>> *Methods = nullptr); bool ParseRecordField(std::vector<RecordFieldDecl> &Out, bool IsPublic); - std::unique_ptr<FunctionDefAST> ParseFunction(const std::string &OwnerClass = {}, bool IsPublic = true); - std::unique_ptr<FunctionDefAST> ParseProcedure(const std::string &OwnerClass = {}, bool IsPublic = true); + std::unique_ptr<FunctionDefAST> ParseFunction(const std::string &OwnerClass = {}, bool IsPublic = true, bool IsOverload = false); + std::unique_ptr<FunctionDefAST> ParseProcedure(const std::string &OwnerClass = {}, bool IsPublic = true, bool IsOverload = false); std::unique_ptr<StmtAST> ParseCallStmt(); std::unique_ptr<StmtAST> ParseReturnStmt(); std::optional<std::vector<ParamDecl>> ParsePrototypeArgs(bool AllowByRef); diff --git a/lib/Lexer/Lexer.cc b/lib/Lexer/Lexer.cc index 44d40e5..9956cd9 100644 --- a/lib/Lexer/Lexer.cc +++ b/lib/Lexer/Lexer.cc @@ -130,6 +130,7 @@ int Lexer::readToken() { if (IdentifierStr == "OR") return tok_or; if (IdentifierStr == "NOT") return tok_not; + if (IdentifierStr == "OVERLOAD") return tok_overload; if (IdentifierStr == "FUNCTION") return tok_function; if (IdentifierStr == "ENDFUNCTION") return tok_endfunction; if (IdentifierStr == "PROCEDURE") return tok_procedure; diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc index d4dd18e..f7817ec 100644 --- a/lib/Parser/Parser.cc +++ b/lib/Parser/Parser.cc @@ -50,7 +50,7 @@ void Parser::syncToStatementStart() { case tok_delete: case tok_constant: case tok_declare: case tok_identifier: case tok_input: case tok_output: case tok_case: case tok_endcase: case tok_otherwise: case tok_if: case tok_while: case tok_repeat: case tok_for: - case tok_function: case tok_procedure: case tok_call: case tok_return: + case tok_overload: case tok_function: case tok_procedure: case tok_call: case tok_return: case tok_else: case tok_endif: case tok_endwhile: case tok_until: case tok_next: case tok_endfunction: case tok_endprocedure: case tok_openfile: case tok_readfile: case tok_writefile: case tok_closefile: @@ -212,6 +212,14 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() { else if (CurTok == tok_for) { return ParseForStmt(); } + else if (CurTok == tok_overload) { + int Line = Lex.getLine(); + 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); + return nullptr; + } else if (CurTok == tok_function) { return ParseFunction(); } diff --git a/lib/Parser/ParserFunction.cc b/lib/Parser/ParserFunction.cc index fa46dcf..3df324c 100644 --- a/lib/Parser/ParserFunction.cc +++ b/lib/Parser/ParserFunction.cc @@ -130,7 +130,7 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef return Params; } -std::unique_ptr<FunctionDefAST> Parser::ParseFunction(const std::string &OwnerClass, bool IsPublic) { +std::unique_ptr<FunctionDefAST> Parser::ParseFunction(const std::string &OwnerClass, bool IsPublic, bool IsOverload) { int Line = Lex.getLine(); getNextToken(); if (CurTok == tok_delete || (CurTok == tok_identifier && sameIdentifier(Lex.IdentifierStr, "DELETE"))) { @@ -167,7 +167,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseFunction(const std::string &OwnerCl } } - auto Proto = std::make_unique<PrototypeAST>(Name, std::move(*Args), RetType, false, OwnerClass, IsPublic); + auto Proto = std::make_unique<PrototypeAST>(Name, std::move(*Args), RetType, false, OwnerClass, IsPublic, IsOverload); std::vector<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_endfunction}); @@ -182,7 +182,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseFunction(const std::string &OwnerCl return Def; } -std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerClass, bool IsPublic) { +std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerClass, bool IsPublic, bool IsOverload) { int Line = Lex.getLine(); getNextToken(); if (CurTok != tok_identifier && CurTok != tok_new && CurTok != tok_delete) { @@ -207,7 +207,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerC cps::sourceDiagnostic(Lex.getLine(), "error: destructor DELETE must have no parameters at line %d\n", Line); return nullptr; } - auto Proto = std::make_unique<PrototypeAST>(Name, std::move(*Args), "VOID", false, OwnerClass, IsPublic); + auto Proto = std::make_unique<PrototypeAST>(Name, std::move(*Args), "VOID", false, OwnerClass, IsPublic, IsOverload); std::vector<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_endprocedure}); diff --git a/lib/Parser/ParserType.cc b/lib/Parser/ParserType.cc index b67558f..d281293 100644 --- a/lib/Parser/ParserType.cc +++ b/lib/Parser/ParserType.cc @@ -116,7 +116,7 @@ std::optional<std::vector<RecordFieldDecl>> Parser::ParseRecordBody( const char *EndKeyword = IsClass ? "ENDCLASS" : "ENDTYPE"; auto AtField = [&] { return IsClass ? (CurTok == tok_public || CurTok == tok_private || CurTok == tok_identifier || - CurTok == tok_function || CurTok == tok_procedure) + CurTok == tok_overload || CurTok == tok_function || CurTok == tok_procedure) : CurTok == tok_declare; }; std::vector<RecordFieldDecl> Fields; @@ -126,11 +126,18 @@ std::optional<std::vector<RecordFieldDecl>> Parser::ParseRecordBody( // Class fields default to public, like record fields. bool IsPublic = CurTok != tok_private; if (IsClass && (CurTok == tok_public || CurTok == tok_private) && - (Lex.peekToken() == tok_function || Lex.peekToken() == tok_procedure)) + (Lex.peekToken() == tok_overload || Lex.peekToken() == tok_function || Lex.peekToken() == tok_procedure)) getNextToken(); - if (IsClass && (CurTok == tok_function || CurTok == tok_procedure)) { - auto Method = CurTok == tok_function ? ParseFunction(Name, IsPublic) - : ParseProcedure(Name, IsPublic); + if (IsClass && (CurTok == tok_overload || CurTok == tok_function || CurTok == tok_procedure)) { + 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()); + HadFieldError = true; + continue; + } + auto Method = CurTok == tok_function ? ParseFunction(Name, IsPublic, IsOverload) + : ParseProcedure(Name, IsPublic, IsOverload); if (Method && Methods) { Methods->push_back(std::move(Method)); continue; diff --git a/tests/iii/overload-syntax-error/case.json b/tests/iii/overload-syntax-error/case.json new file mode 100644 index 0000000..3fcb463 --- /dev/null +++ b/tests/iii/overload-syntax-error/case.json @@ -0,0 +1 @@ +{"errors": [{"reason": "OVERLOAD must be followed by FUNCTION or PROCEDURE", "line": 1}]} diff --git a/tests/iii/overload-syntax-error/program.cps b/tests/iii/overload-syntax-error/program.cps new file mode 100644 index 0000000..923163b --- /dev/null +++ b/tests/iii/overload-syntax-error/program.cps @@ -0,0 +1 @@ +OVERLOAD DECLARE x : INTEGER |
