diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-18 06:09:01 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-18 06:09:01 +0000 |
| commit | b17f101cfc75565f9991c856ec62f1e17b0ab104 (patch) | |
| tree | 6c925f06c45dbaa557a0451cfca33f17be71ec67 /lib/Parser | |
| parent | 16231050058131860f710073c17d3bca7c6637eb (diff) | |
feat(operators): add member and unary overloads with explicit calls
Select member and global candidates together, enforce private access, and
reuse argument marshalling. Materialize temporary receivers for chaining
and register them for the existing object cleanup mechanism.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib/Parser')
| -rw-r--r-- | lib/Parser/Parser.cc | 15 | ||||
| -rw-r--r-- | lib/Parser/ParserExpression.cc | 25 | ||||
| -rw-r--r-- | lib/Parser/ParserFunction.cc | 17 |
3 files changed, 44 insertions, 13 deletions
diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc index f22e3c6..afe0e80 100644 --- a/lib/Parser/Parser.cc +++ b/lib/Parser/Parser.cc @@ -48,7 +48,7 @@ void Parser::syncToStatementStart() { switch (CurTok) { case tok_include: case tok_global: case tok_endglobal: case tok_include_obj: case tok_extern: - case tok_delete: case tok_constant: case tok_declare: case tok_identifier: case tok_input: case tok_output: + case tok_delete: case tok_constant: case tok_declare: case tok_identifier: case tok_operator: 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_overload: case tok_function: case tok_procedure: case tok_call: case tok_return: @@ -163,7 +163,7 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() { if (CurTok == tok_declare) { return ParseDeclare(); } - else if (CurTok == tok_identifier) { + else if (CurTok == tok_identifier || CurTok == tok_operator) { return ParseAssignStmt(); } else if (CurTok == tok_input) { @@ -284,9 +284,16 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() { // Bare-name and single-index targets degrade to their legacy nodes so the // existing assignment code paths stay untouched. std::unique_ptr<StmtAST> Parser::ParseAssignStmt() { - std::string Name = Lex.IdentifierStr; int Line = Lex.getLine(); - getNextToken(); + std::string Name; + if (CurTok == tok_operator) { + int Op; + Name = ParseOperatorName(Op); + if (Name.empty()) return nullptr; + } else { + Name = Lex.IdentifierStr; + getNextToken(); + } if (CurTok == '(') { getNextToken(); diff --git a/lib/Parser/ParserExpression.cc b/lib/Parser/ParserExpression.cc index a4f4fcc..6cde5bf 100644 --- a/lib/Parser/ParserExpression.cc +++ b/lib/Parser/ParserExpression.cc @@ -41,9 +41,16 @@ std::unique_ptr<ExprAST> Parser::ParseNumberExpr() { } std::unique_ptr<ExprAST> Parser::ParseIdentifierExpr() { - std::string IdName = Lex.IdentifierStr; int Line = Lex.getLine(); - getNextToken(); + std::string IdName; + if (CurTok == tok_operator) { + int Op; + IdName = ParseOperatorName(Op); + if (IdName.empty()) return nullptr; + } else { + IdName = Lex.IdentifierStr; + getNextToken(); + } if (CurTok == '(' && !atCaseBoundary()) { getNextToken(); @@ -110,15 +117,21 @@ bool Parser::ParseDesignatorSuffix(std::vector<DesignatorAccess> &Out) { Out.push_back(std::move(A)); } else if (CurTok == '.') { getNextToken(); - if (CurTok != tok_identifier && CurTok != tok_new && CurTok != tok_delete) { + 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()); return false; } DesignatorAccess A; A.Kind = AccessKind::Field; - A.FieldName = CurTok == tok_new ? "NEW" : CurTok == tok_delete ? "DELETE" : Lex.IdentifierStr; + if (CurTok == tok_operator) { + int Op; + A.FieldName = ParseOperatorName(Op); + if (A.FieldName.empty()) return false; + } else { + A.FieldName = CurTok == tok_new ? "NEW" : CurTok == tok_delete ? "DELETE" : Lex.IdentifierStr; + getNextToken(); + } Out.push_back(std::move(A)); - getNextToken(); } else if (CurTok == '^') { getNextToken(); DesignatorAccess A; @@ -172,7 +185,7 @@ std::unique_ptr<ExprAST> Parser::ParsePrimaryImpl() { case tok_new: cps::sourceDiagnostic(Lex.getLine(), "error: NEW is only allowed on the right of an assignment at line %d\n", Lex.getLine()); return nullptr; - case tok_identifier: return ParseIdentifierExpr(); + case tok_identifier: case tok_operator: return ParseIdentifierExpr(); case tok_number_int: return ParseNumberExpr(); case tok_number_real: return ParseNumberExpr(); case tok_string_literal: { diff --git a/lib/Parser/ParserFunction.cc b/lib/Parser/ParserFunction.cc index 3ff54da..dfb689a 100644 --- a/lib/Parser/ParserFunction.cc +++ b/lib/Parser/ParserFunction.cc @@ -140,6 +140,10 @@ std::string Parser::ParseOperatorName(int &Op) { return {}; } getNextToken(); + if (CurTok != '(') { + sourceDiagnostic(Lex.getLine(), "error: Expected '(' after operator name at line %d\n", Lex.getLine()); + return {}; + } return operatorName(Op); } @@ -339,13 +343,20 @@ std::unique_ptr<StmtAST> Parser::ParseExternDecl() { std::unique_ptr<StmtAST> Parser::ParseCallStmt() { int Line = Lex.getLine(); getNextToken(); - if (CurTok != tok_identifier) { + if (CurTok != tok_identifier && CurTok != tok_operator) { cps::sourceDiagnostic(Lex.getLine(), "error: Expected callee name after CALL\n"); return nullptr; } - std::string Callee = Lex.IdentifierStr; - getNextToken(); + std::string Callee; + if (CurTok == tok_operator) { + int Op; + Callee = ParseOperatorName(Op); + if (Callee.empty()) return nullptr; + } else { + Callee = Lex.IdentifierStr; + getNextToken(); + } std::vector<DesignatorAccess> Accesses; if (!ParseDesignatorSuffix(Accesses)) return nullptr; |
