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
186 lines
5.1 KiB
Rust
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);
|
|
}
|
|
}
|