Files
storybook/src/syntax/keywords.rs
Sienna Meridian Satterwhite 25d59d6107 feat(type-system): implement concept_comparison with pattern matching
Added complete support for the new type system syntax including:

- concept: Base type declarations
- sub_concept: Enum and record sub-type definitions
- concept_comparison: Compile-time pattern matching with conditional guards

Parser changes:
- Added VariantPattern, FieldCondition, and Condition AST nodes
- Implemented "is" keyword for pattern matching (e.g., "CupType is Glass or CupType is Plastic")
- Added Value::Any variant to support universal type matching
- Disambiguated enum-like vs record-like sub_concept syntax

LSP updates:
- Added Value::Any match arms across code_actions, completion, hover, inlay_hints, and semantic_tokens
- Type inference and formatting support for Any values

Example fixes:
- Fixed syntax error in baker-family behaviors (missing closing brace in nested if)
- Removed deprecated core_enums.sb file
2026-02-14 09:28:20 +00:00

186 lines
5.1 KiB
Rust

//! 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::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::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::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);
}
}