aboutsummaryrefslogtreecommitdiff
path: root/lib/Parser
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-13 13:40:57 +0000
committer_ov4 <ov4@ov4.org>2026-10-13 13:40:57 +0000
commitf5a2541ed3faf9a942b867e2d54577352153afce (patch)
treed5f737fdb8d77dc67d46cc12f8603c7df6a168c7 /lib/Parser
parent5b08d59dba28b99cf991c02e837297fbfdb190c9 (diff)
Refactor record fields to preserve visibility and share parsing
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'lib/Parser')
-rw-r--r--lib/Parser/ParserType.cc61
1 files changed, 33 insertions, 28 deletions
diff --git a/lib/Parser/ParserType.cc b/lib/Parser/ParserType.cc
index 8be7e46..ae671d5 100644
--- a/lib/Parser/ParserType.cc
+++ b/lib/Parser/ParserType.cc
@@ -66,30 +66,9 @@ std::unique_ptr<StmtAST> Parser::ParseTypeDecl() {
return nullptr;
}
} else {
- // Record body: DECLARE-only lines, so nothing here can leak into the
- // statement chain. One bad field yields one diagnostic; parsing then
- // resumes at the next field or ENDTYPE.
- std::vector<RecordFieldDecl> Fields;
- bool HadFieldError = false;
- while (CurTok == tok_declare) {
- if (!ParseRecordField(Fields)) {
- HadFieldError = true;
- while (CurTok != tok_declare && CurTok != tok_endtype && CurTok != tok_eof)
- getNextToken();
- }
- }
- if (CurTok != tok_endtype) {
- fprintf(stderr, "error: Expected DECLARE or ENDTYPE in TYPE %s at line %d\n",
- Name.c_str(), Lex.getLine());
- return nullptr; // token left for the outer recovery
- }
- getNextToken(); // eat ENDTYPE
- if (Fields.empty()) {
- fprintf(stderr, "error: Record TYPE %s has no fields at line %d\n", Name.c_str(), Line);
- return nullptr;
- }
- if (HadFieldError) return nullptr;
- Decl = std::make_unique<RecordTypeDeclAST>(Name, std::move(Fields));
+ auto Fields = ParseRecordBody(Name, Line, tok_endtype);
+ if (!Fields) return nullptr;
+ Decl = std::make_unique<RecordTypeDeclAST>(Name, std::move(*Fields));
}
if (!AtTopLevel) {
@@ -99,9 +78,35 @@ std::unique_ptr<StmtAST> Parser::ParseTypeDecl() {
return Decl;
}
-// DECLARE <field> : <type> — one record field. Array fields are deferred.
-bool Parser::ParseRecordField(std::vector<RecordFieldDecl> &Out) {
- getNextToken(); // eat DECLARE
+// Shared record body and field parsing. Fields are data, never statements.
+std::optional<std::vector<RecordFieldDecl>> Parser::ParseRecordBody(
+ const std::string &Name, int Line, int EndToken) {
+ std::vector<RecordFieldDecl> Fields;
+ bool HadFieldError = false;
+ while (CurTok == tok_declare) {
+ if (!ParseRecordField(Fields, true)) {
+ HadFieldError = true;
+ while (CurTok != tok_declare && CurTok != EndToken && CurTok != tok_eof)
+ getNextToken();
+ }
+ }
+ if (CurTok != EndToken) {
+ fprintf(stderr, "error: Expected DECLARE or ENDTYPE in TYPE %s at line %d\n",
+ Name.c_str(), Lex.getLine());
+ return std::nullopt;
+ }
+ getNextToken(); // eat body terminator
+ if (Fields.empty()) {
+ fprintf(stderr, "error: Record TYPE %s has no fields at line %d\n", Name.c_str(), Line);
+ return std::nullopt;
+ }
+ if (HadFieldError) return std::nullopt;
+ return Fields;
+}
+
+// <field introducer> <field> : <type>. Array fields are deferred.
+bool Parser::ParseRecordField(std::vector<RecordFieldDecl> &Out, bool IsPublic) {
+ getNextToken(); // eat field introducer
if (CurTok != tok_identifier) {
fprintf(stderr, "error: Expected field name after DECLARE at line %d\n", Lex.getLine());
return false;
@@ -125,6 +130,6 @@ bool Parser::ParseRecordField(std::vector<RecordFieldDecl> &Out) {
std::string TypeName = ParseTypeName(false);
if (TypeName.empty()) return false;
- Out.push_back({FieldName, TypeName});
+ Out.push_back({FieldName, TypeName, IsPublic});
return true;
}