diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-22 04:00:38 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-22 04:05:51 +0000 |
| commit | 0b763257ed1e230767171234971cc8f660d59087 (patch) | |
| tree | 61287515873b94ab4eeccf608447c39019d7ba25 /lib/Parser | |
| parent | 56e97d0ddd3fff2bee160bae04e8f659671f398d (diff) | |
refactor(parser): share call-argument, result-access and type-token checks
Add ParseOptionalCallArgs() for member calls and NEW, diagnoseResultAccess()
for the duplicated "access on a function result" diagnostic, and
isBuiltinTypeToken() for the builtin type keyword list used by template-call
lookahead, cast detection and CASE label scanning.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib/Parser')
| -rw-r--r-- | lib/Parser/ParserControlFlow.cc | 7 | ||||
| -rw-r--r-- | lib/Parser/ParserExpression.cc | 57 |
2 files changed, 33 insertions, 31 deletions
diff --git a/lib/Parser/ParserControlFlow.cc b/lib/Parser/ParserControlFlow.cc index ba038d3..feedf44 100644 --- a/lib/Parser/ParserControlFlow.cc +++ b/lib/Parser/ParserControlFlow.cc @@ -156,14 +156,13 @@ bool Parser::isCaseLabel() { case ')': case ']': if (--Depth < 0) return false; break; case tok_identifier: case tok_number_int: case tok_number_real: case tok_string_literal: case tok_c_string_literal: case tok_char_literal: case tok_true: case tok_false: - case tok_integer_kw: case tok_real_kw: case tok_boolean_kw: - case tok_string_kw: case tok_char_kw: case tok_c_int: case tok_c_char: - case tok_c_string: case tok_c_double: case tok_to: case tok_otherwise: case tok_and: case tok_or: case tok_not: case tok_eq: case tok_ne: case tok_le: case tok_ge: case tok_div: case tok_mod: case '+': case '-': case '*': case '/': case '&': case '^': case '<': case '>': case '.': case ',': break; - default: return false; + default: + if (!isBuiltinTypeToken(T)) return false; + break; } } } diff --git a/lib/Parser/ParserExpression.cc b/lib/Parser/ParserExpression.cc index 398ba84..b3bb3d9 100644 --- a/lib/Parser/ParserExpression.cc +++ b/lib/Parser/ParserExpression.cc @@ -38,15 +38,20 @@ std::unique_ptr<ExprAST> Parser::ParseNumberExpr() { return std::make_unique<IntegerExprAST>(Value); } +// Keyword tokens that name a builtin or C scalar type. +bool Parser::isBuiltinTypeToken(int Tok) { + return Tok == tok_integer_kw || Tok == tok_real_kw || Tok == tok_boolean_kw || + Tok == tok_string_kw || Tok == tok_char_kw || + Tok == tok_c_int || Tok == tok_c_char || Tok == tok_c_string || Tok == tok_c_double; +} + // Grammar lookahead distinguishes a template call from a comparison without // consuming tokens. Like C#, A < B, C > (D) selects the template-call grammar. bool Parser::isTemplateCall() { if (CurTok != '<') return false; unsigned Offset = 0; auto IsTypeToken = [](int Tok) { - return Tok == tok_identifier || Tok == tok_integer_kw || Tok == tok_real_kw || - Tok == tok_boolean_kw || Tok == tok_string_kw || Tok == tok_char_kw || - Tok == tok_c_int || Tok == tok_c_char || Tok == tok_c_string || Tok == tok_c_double; + return Tok == tok_identifier || isBuiltinTypeToken(Tok); }; std::function<bool()> Type = [&] { if (!IsTypeToken(Lex.peekToken(Offset))) return false; @@ -99,10 +104,7 @@ std::unique_ptr<ExprAST> Parser::ParseIdentifierExpr() { getNextToken(); auto Args = ParseExprList(')', true); if (!Args) return nullptr; - if (CurTok == '[' || CurTok == '^') { - cps::sourceError(Lex.getLine(), "record/array/pointer access on a function result is not supported"); - return nullptr; - } + if (diagnoseResultAccess()) return nullptr; return ParseResultMethods(std::make_unique<CallExprAST>(IdName, std::move(*Args), Line, std::move(TemplateArgs)), Line); } @@ -126,6 +128,13 @@ std::unique_ptr<ExprAST> Parser::makeDesignator( return std::make_unique<DesignatorExprAST>(Name, std::move(Accesses), Line); } +// Indexing or dereferencing a call result is rejected; true means diagnosed. +bool Parser::diagnoseResultAccess() { + if (CurTok != '[' && CurTok != '^') return false; + cps::sourceError(Lex.getLine(), "record/array/pointer access on a function result is not supported"); + return true; +} + // The final field suffix names the method; preceding suffixes form its receiver. std::unique_ptr<MemberCallExprAST> Parser::ParseMemberCall( const std::string &Name, std::vector<DesignatorAccess> Accesses, int Line) { @@ -137,16 +146,8 @@ std::unique_ptr<MemberCallExprAST> Parser::ParseMemberCall( Accesses.pop_back(); auto Receiver = std::make_unique<DesignatorExprAST>(Name, std::move(Accesses), Line); std::vector<std::unique_ptr<ExprAST>> Args; - if (CurTok == '(') { - getNextToken(); - auto Parsed = ParseExprList(')', true); - if (!Parsed) return nullptr; - Args = std::move(*Parsed); - } - if (CurTok == '[' || CurTok == '^') { - cps::sourceError(Lex.getLine(), "record/array/pointer access on a function result is not supported"); - return nullptr; - } + if (!ParseOptionalCallArgs(Args)) return nullptr; + if (diagnoseResultAccess()) return nullptr; auto Result = ParseResultMethods(std::make_unique<MemberCallExprAST>(std::move(Receiver), Method, std::move(Args), Line), Line); return std::unique_ptr<MemberCallExprAST>(static_cast<MemberCallExprAST *>(Result.release())); } @@ -193,10 +194,7 @@ bool Parser::ParseDesignatorSuffix(std::vector<DesignatorAccess> &Out) { std::unique_ptr<ExprAST> Parser::ParseParenExpr() { getNextToken(); - bool IsType = CurTok == tok_integer_kw || CurTok == tok_real_kw || - CurTok == tok_boolean_kw || CurTok == tok_string_kw || CurTok == tok_char_kw || - CurTok == tok_c_int || CurTok == tok_c_char || CurTok == tok_c_string || - CurTok == tok_c_double || + bool IsType = isBuiltinTypeToken(CurTok) || (CurTok == tok_identifier && TypeNames.count(Lex.IdentifierStr)); if (IsType) { std::string TypeName = ParseTypeName(); @@ -389,6 +387,16 @@ std::optional<std::vector<std::unique_ptr<ExprAST>>> Parser::ParseExprList(char return Elems; } +// An optional parenthesized argument list; false means a diagnosed failure. +bool Parser::ParseOptionalCallArgs(std::vector<std::unique_ptr<ExprAST>> &Args) { + if (CurTok != '(') return true; + getNextToken(); + auto Parsed = ParseExprList(')', true); + if (!Parsed) return false; + Args = std::move(*Parsed); + return true; +} + std::unique_ptr<ExprAST> Parser::ParseAssignmentRHS() { if (CurTok != tok_new) return ParseExpression(); int Line = Lex.getLine(); @@ -396,11 +404,6 @@ std::unique_ptr<ExprAST> Parser::ParseAssignmentRHS() { std::string ClassName = ParseTypeName(false); if (ClassName.empty()) return nullptr; std::vector<std::unique_ptr<ExprAST>> Args; - if (CurTok == '(') { - getNextToken(); - auto Parsed = ParseExprList(')', true); - if (!Parsed) return nullptr; - Args = std::move(*Parsed); - } + if (!ParseOptionalCallArgs(Args)) return nullptr; return std::make_unique<NewExprAST>(ClassName, std::move(Args), Line); } |
