feat(parser): add dot notation for sub_concept declarations

Changed sub_concept syntax from heuristic parent extraction to
explicit dot notation: `sub_concept Parent.Name { ... }`

The old syntax inferred the parent concept from the name using
uppercase letter heuristics. The new syntax makes the parent
concept explicit and unambiguous.

Added type_system_tests module with comprehensive tests.
This commit is contained in:
2026-02-14 14:05:47 +00:00
parent 8e4bdd3942
commit 0cd00a9e73
4 changed files with 1048 additions and 883 deletions

View File

@@ -753,22 +753,8 @@ ConceptDecl: ConceptDecl = {
};
SubConceptDecl: SubConceptDecl = {
// Enum-like sub_concept: sub_concept PlateColor { Red, Blue, Green }
"sub_concept" <name:Ident> "{" <variants:Comma<Ident>> "}" => {
let parent = {
let mut last_cap = 0;
for (i, ch) in name.char_indices().skip(1) {
if ch.is_uppercase() {
last_cap = i;
}
}
if last_cap > 0 {
name[..last_cap].to_string()
} else {
name.clone()
}
};
// Enum-like sub_concept: sub_concept Cup.Type { Small, Medium, Large }
"sub_concept" <parent:Ident> "." <name:Ident> "{" <variants:Comma<Ident>> "}" => {
SubConceptDecl {
name,
parent_concept: parent,
@@ -776,22 +762,8 @@ SubConceptDecl: SubConceptDecl = {
span: Span::new(0, 0),
}
},
// Record-like sub_concept with at least one field
"sub_concept" <name:Ident> "{" <first:Ident> ":" <first_val:Value> <rest:("," <Ident> ":" <Value>)*> ","? "}" => {
let parent = {
let mut last_cap = 0;
for (i, ch) in name.char_indices().skip(1) {
if ch.is_uppercase() {
last_cap = i;
}
}
if last_cap > 0 {
name[..last_cap].to_string()
} else {
name.clone()
}
};
// Record-like sub_concept with at least one field: sub_concept Cup.Material { weight: 100 }
"sub_concept" <parent:Ident> "." <name:Ident> "{" <first:Ident> ":" <first_val:Value> <rest:("," <Ident> ":" <Value>)*> ","? "}" => {
let mut fields = vec![Field {
name: first,
value: first_val,