feat(ast): add species base to template declarations
Added optional species_base field to Template struct enabling
template-species inheritance syntax: `template Name: Species { ... }`.
Updated LALRPOP grammar and all Template construction sites.
This commit is contained in:
@@ -138,6 +138,7 @@ pub struct Character {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Template {
|
||||
pub name: String,
|
||||
pub species_base: Option<String>, // `: Species` - type constraint from species
|
||||
pub fields: Vec<Field>,
|
||||
pub strict: bool,
|
||||
pub includes: Vec<String>,
|
||||
|
||||
@@ -169,7 +169,7 @@ UsesScheduleClause: Vec<String> = {
|
||||
// ===== Template =====
|
||||
|
||||
Template: Template = {
|
||||
"template" <name:Ident> <strict:"strict"?> "{" <body:TemplateBodyItem*> "}" => {
|
||||
"template" <name:Ident> <species_base:(":" <Ident>)?> <strict:"strict"?> "{" <body:TemplateBodyItem*> "}" => {
|
||||
let mut fields = Vec::new();
|
||||
let mut includes = Vec::new();
|
||||
let mut uses_behaviors = None;
|
||||
@@ -186,6 +186,7 @@ Template: Template = {
|
||||
|
||||
Template {
|
||||
name,
|
||||
species_base,
|
||||
fields,
|
||||
strict: strict.is_some(),
|
||||
includes,
|
||||
|
||||
3298
src/syntax/parser.rs
3298
src/syntax/parser.rs
File diff suppressed because it is too large
Load Diff
@@ -182,3 +182,91 @@ sub_concept Cup.Material { Glass, Ceramic, Metal }
|
||||
| _ => panic!("Expected SubConcept"),
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Template species base tests =====
|
||||
|
||||
#[test]
|
||||
fn test_template_with_species_base() {
|
||||
let input = r#"
|
||||
template Person: Human {
|
||||
age: 30
|
||||
name: "default"
|
||||
}
|
||||
"#;
|
||||
let file = parse(input);
|
||||
|
||||
assert_eq!(file.declarations.len(), 1);
|
||||
match &file.declarations[0] {
|
||||
| Declaration::Template(t) => {
|
||||
assert_eq!(t.name, "Person");
|
||||
assert_eq!(t.species_base, Some("Human".to_string()));
|
||||
assert_eq!(t.fields.len(), 2);
|
||||
},
|
||||
| _ => panic!("Expected Template declaration"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_template_without_species_base() {
|
||||
let input = r#"
|
||||
template Person {
|
||||
age: 30
|
||||
}
|
||||
"#;
|
||||
let file = parse(input);
|
||||
|
||||
assert_eq!(file.declarations.len(), 1);
|
||||
match &file.declarations[0] {
|
||||
| Declaration::Template(t) => {
|
||||
assert_eq!(t.name, "Person");
|
||||
assert_eq!(t.species_base, None);
|
||||
assert_eq!(t.fields.len(), 1);
|
||||
},
|
||||
| _ => panic!("Expected Template declaration"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_template_strict_with_species_base() {
|
||||
let input = r#"
|
||||
template Warrior: Human strict {
|
||||
strength: 50..100
|
||||
weapon: "sword"
|
||||
}
|
||||
"#;
|
||||
let file = parse(input);
|
||||
|
||||
assert_eq!(file.declarations.len(), 1);
|
||||
match &file.declarations[0] {
|
||||
| Declaration::Template(t) => {
|
||||
assert_eq!(t.name, "Warrior");
|
||||
assert_eq!(t.species_base, Some("Human".to_string()));
|
||||
assert!(t.strict);
|
||||
assert_eq!(t.fields.len(), 2);
|
||||
},
|
||||
| _ => panic!("Expected Template declaration"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_template_species_base_with_includes() {
|
||||
let input = r#"
|
||||
template Knight: Human {
|
||||
include Warrior
|
||||
honor: 80
|
||||
}
|
||||
"#;
|
||||
let file = parse(input);
|
||||
|
||||
assert_eq!(file.declarations.len(), 1);
|
||||
match &file.declarations[0] {
|
||||
| Declaration::Template(t) => {
|
||||
assert_eq!(t.name, "Knight");
|
||||
assert_eq!(t.species_base, Some("Human".to_string()));
|
||||
assert_eq!(t.includes, vec!["Warrior".to_string()]);
|
||||
assert_eq!(t.fields.len(), 1);
|
||||
assert_eq!(t.fields[0].name, "honor");
|
||||
},
|
||||
| _ => panic!("Expected Template declaration"),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user