release: Storybook v0.2.0 - Major syntax and features update

BREAKING CHANGES:
- Relationship syntax now requires blocks for all participants
- Removed self/other perspective blocks from relationships
- Replaced 'guard' keyword with 'if' for behavior tree decorators

Language Features:
- Add tree-sitter grammar with improved if/condition disambiguation
- Add comprehensive tutorial and reference documentation
- Add SBIR v0.2.0 binary format specification
- Add resource linking system for behaviors and schedules
- Add year-long schedule patterns (day, season, recurrence)
- Add behavior tree enhancements (named nodes, decorators)

Documentation:
- Complete tutorial series (9 chapters) with baker family examples
- Complete reference documentation for all language features
- SBIR v0.2.0 specification with binary format details
- Added locations and institutions documentation

Examples:
- Convert all examples to baker family scenario
- Add comprehensive working examples

Tooling:
- Zed extension with LSP integration
- Tree-sitter grammar for syntax highlighting
- Build scripts and development tools

Version Updates:
- Main package: 0.1.0 → 0.2.0
- Tree-sitter grammar: 0.1.0 → 0.2.0
- Zed extension: 0.1.0 → 0.2.0
- Storybook editor: 0.1.0 → 0.2.0
This commit is contained in:
2026-02-13 21:52:03 +00:00
parent 80332971b8
commit 16deb5d237
290 changed files with 90316 additions and 5827 deletions

188
src/syntax/keywords.rs Normal file
View File

@@ -0,0 +1,188 @@
//! Shared keyword definitions derived from the lexer Token enum
//!
//! This module provides structured access to Storybook language keywords
//! without duplicating the keyword strings across different LSP modules.
//! All keywords are defined in the Token enum in lexer.rs using the
//! #[token(...)] attribute.
use crate::syntax::lexer::Token;
/// Top-level declaration keywords that start a new declaration
pub const DECLARATION_KEYWORDS: &[&str] = &[
"character",
"template",
"species",
"behavior",
"life_arc",
"relationship",
"institution",
"location",
"enum",
"schedule",
];
/// All structural keywords (declarations + use)
pub const STRUCTURAL_KEYWORDS: &[&str] = &[
"use",
"character",
"template",
"species",
"behavior",
"life_arc",
"relationship",
"institution",
"location",
"enum",
"schedule",
];
/// Keywords used in behavior tree definitions
pub const BEHAVIOR_KEYWORDS: &[&str] = &[
"choose",
"then",
"if",
"when",
"repeat",
"invert",
"retry",
"timeout",
"cooldown",
// "guard" removed - use "if" instead
"succeed_always",
"fail_always",
];
/// Modifier keywords used in various contexts
pub const MODIFIER_KEYWORDS: &[&str] = &["strict", "include", "from", "as"];
/// State machine keywords
pub const STATE_KEYWORDS: &[&str] = &["state", "on", "enter"];
/// Expression keywords
pub const EXPRESSION_KEYWORDS: &[&str] =
&["forall", "exists", "in", "where", "and", "or", "not", "is"];
/// Special identifier keywords
pub const IDENTIFIER_KEYWORDS: &[&str] = &["self", "other"];
/// Operation keywords
pub const OPERATION_KEYWORDS: &[&str] = &["remove", "append"];
/// Boolean literals
pub const BOOLEAN_LITERALS: &[&str] = &["true", "false"];
/// Check if a string is a top-level declaration keyword
pub fn is_declaration_keyword(s: &str) -> bool {
DECLARATION_KEYWORDS.contains(&s)
}
/// Check if a string is any structural keyword (includes 'use')
pub fn is_structural_keyword(s: &str) -> bool {
STRUCTURAL_KEYWORDS.contains(&s)
}
/// Check if a string is a behavior tree keyword
pub fn is_behavior_keyword(s: &str) -> bool {
BEHAVIOR_KEYWORDS.contains(&s)
}
/// Check if a token is a declaration keyword token
pub fn token_is_declaration_keyword(token: &Token) -> bool {
matches!(
token,
Token::Character |
Token::Template |
Token::Species |
Token::Behavior |
Token::LifeArc |
Token::Relationship |
Token::Institution |
Token::Location |
Token::Enum |
Token::Schedule
)
}
/// Check if a token is a structural keyword token (includes Use)
pub fn token_is_structural_keyword(token: &Token) -> bool {
matches!(
token,
Token::Use |
Token::Character |
Token::Template |
Token::Species |
Token::Behavior |
Token::LifeArc |
Token::Relationship |
Token::Institution |
Token::Location |
Token::Enum |
Token::Schedule
)
}
/// Get the string representation of a declaration token
pub fn declaration_token_to_str(token: &Token) -> Option<&'static str> {
match token {
| Token::Character => Some("character"),
| Token::Template => Some("template"),
| Token::Species => Some("species"),
| Token::Behavior => Some("behavior"),
| Token::LifeArc => Some("life_arc"),
| Token::Relationship => Some("relationship"),
| Token::Institution => Some("institution"),
| Token::Location => Some("location"),
| Token::Enum => Some("enum"),
| Token::Schedule => Some("schedule"),
| _ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_declaration_keywords() {
assert!(is_declaration_keyword("character"));
assert!(is_declaration_keyword("template"));
assert!(is_declaration_keyword("behavior"));
assert!(!is_declaration_keyword("use"));
assert!(!is_declaration_keyword("unknown"));
}
#[test]
fn test_structural_keywords() {
assert!(is_structural_keyword("character"));
assert!(is_structural_keyword("use"));
assert!(!is_structural_keyword("if"));
}
#[test]
fn test_behavior_keywords() {
assert!(is_behavior_keyword("choose"));
assert!(is_behavior_keyword("repeat"));
assert!(!is_behavior_keyword("character"));
}
#[test]
fn test_token_checks() {
assert!(token_is_declaration_keyword(&Token::Character));
assert!(token_is_declaration_keyword(&Token::Behavior));
assert!(!token_is_declaration_keyword(&Token::Use));
assert!(token_is_structural_keyword(&Token::Use));
assert!(token_is_structural_keyword(&Token::Character));
assert!(!token_is_structural_keyword(&Token::If));
}
#[test]
fn test_token_to_str() {
assert_eq!(
declaration_token_to_str(&Token::Character),
Some("character")
);
assert_eq!(declaration_token_to_str(&Token::Behavior), Some("behavior"));
assert_eq!(declaration_token_to_str(&Token::Use), None);
}
}