pub trait Syntax {
type Lang: Language;
type Component: Display + Debug + Clone + PartialEq + Eq + Hash;
type COMPONENTS: ArrayLength + Debug + Eq + Hash;
type REQUIRED: ArrayLength + Debug + Eq + Hash;
const KIND: <Self::Lang as Language>::SyntaxKind;
// Required methods
fn possible_components( ) -> &'static GenericArrayDeque<Self::Component, Self::COMPONENTS>;
fn required_components( ) -> &'static GenericArrayDeque<Self::Component, Self::REQUIRED>;
}Expand description
A trait representing a syntax with a type-level number of components.
This trait defines the structure of a syntax element that has a known number
of required components. It uses typenum for type-level component count,
enabling compile-time arithmetic and better integration with generic-array-based code.
§Type Parameters
Component: The type representing individual syntax components (usually an enum)COMPONENTS: A type-level unsigned integer (viaArrayLength) specifying component count
§Examples
use tokora::{utils::{typenum, GenericArrayDeque}, syntax::{Syntax, Language}};
use typenum::U5;
use core::fmt;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct MyLanguage;
impl Language for MyLanguage {
type SyntaxKind = (); // () is a placeholder
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum LetStatementComponent {
LetKeyword,
Identifier,
Equals,
Expression,
Semicolon,
}
impl fmt::Display for LetStatementComponent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::LetKeyword => write!(f, "'let' keyword"),
Self::Identifier => write!(f, "identifier"),
Self::Equals => write!(f, "'=' operator"),
Self::Expression => write!(f, "expression"),
Self::Semicolon => write!(f, "';' semicolon"),
}
}
}
struct LetStatement;
impl Syntax for LetStatement {
type Lang = MyLanguage;
const KIND: () = (); // () is a placeholder
type Component = LetStatementComponent;
type COMPONENTS = U5;
type REQUIRED = U5;
fn possible_components() -> &'static GenericArrayDeque<Self::Component, Self::COMPONENTS> {
static COMPONENTS: GenericArrayDeque<LetStatementComponent, typenum::U5> = {
let mut deque = GenericArrayDeque::new();
deque.push_back(LetStatementComponent::LetKeyword);
deque.push_back(LetStatementComponent::Identifier);
deque.push_back(LetStatementComponent::Equals);
deque.push_back(LetStatementComponent::Expression);
deque.push_back(LetStatementComponent::Semicolon);
deque
};
&COMPONENTS
}
fn required_components() -> &'static GenericArrayDeque<Self::Component, Self::REQUIRED> {
static REQUIRED: GenericArrayDeque<LetStatementComponent, typenum::U5> = {
let mut deque = GenericArrayDeque::new();
deque.push_back(LetStatementComponent::LetKeyword);
deque.push_back(LetStatementComponent::Identifier);
deque.push_back(LetStatementComponent::Equals);
deque.push_back(LetStatementComponent::Expression);
deque.push_back(LetStatementComponent::Semicolon);
deque
};
&REQUIRED
}
}Required Associated Constants§
Sourceconst KIND: <Self::Lang as Language>::SyntaxKind
const KIND: <Self::Lang as Language>::SyntaxKind
The kind of the syntax.
Required Associated Types§
Sourcetype Component: Display + Debug + Clone + PartialEq + Eq + Hash
type Component: Display + Debug + Clone + PartialEq + Eq + Hash
The component type of this syntax.
Usually this is an enum representing different variants of syntax components. This type is used for error reporting to specify which components are missing.
Do not implement this so that Eq, Hash, or Display can report something
different for the same value over time — most easily done by deriving one of them from
a Cell, an atomic, or other interior-mutable or ambient state.
IncompleteSyntax stores Component values in a
deduplicating set keyed on exactly those impls, and after insertion can only ever hand
this type back out by shared reference — so Component’s own author is the only one able
to keep that promise, or break it. See Uniqueness is a logic error on
IncompleteSyntax for what breaking it costs.
Sourcetype COMPONENTS: ArrayLength + Debug + Eq + Hash
type COMPONENTS: ArrayLength + Debug + Eq + Hash
The number of components in this syntax, represented as a type-level unsigned integer.
Uses typenum to represent the count at the type level, enabling compile-time
arithmetic without requiring unstable generic_const_exprs feature.
§Examples
use typenum::U3; // For a syntax with 3 components
impl Syntax for MySyntax {
type COMPONENTS = U3;
// ...
}Sourcetype REQUIRED: ArrayLength + Debug + Eq + Hash
type REQUIRED: ArrayLength + Debug + Eq + Hash
The number of required components in this syntax, represented as a type-level unsigned integer.
Uses typenum to represent the count at the type level, enabling compile-time
arithmetic without requiring unstable generic_const_exprs feature.
§Examples
use typenum::U3; // For a syntax with 3 components
impl Syntax for MySyntax {
type COMPONENTS = U3;
// ...
}Required Methods§
Sourcefn possible_components() -> &'static GenericArrayDeque<Self::Component, Self::COMPONENTS>
fn possible_components() -> &'static GenericArrayDeque<Self::Component, Self::COMPONENTS>
Returns a static reference to all possible components for this syntax.
The deque contains all components that can be part of this syntax element, in a canonical order. The returned reference points to a static, never-changing collection that is initialized once at program startup.
§Implementation Pattern
Implementations should use a static item initialized in a const context:
fn possible_components() -> &'static GenericArrayDeque<Self::Component, Self::COMPONENTS> {
static COMPONENTS: GenericArrayDeque<MyComponent, U3> = {
let mut deque = GenericArrayDeque::new();
// Push components in const context
deque.push_back(MyComponent::Foo);
deque.push_back(MyComponent::Bar);
deque.push_back(MyComponent::Baz);
deque
};
&COMPONENTS
}§Examples
let components = MySyntax::possible_components();
for component in components.iter() {
println!("{}", component);
}Sourcefn required_components() -> &'static GenericArrayDeque<Self::Component, Self::REQUIRED>
fn required_components() -> &'static GenericArrayDeque<Self::Component, Self::REQUIRED>
Returns a static reference to all required components for this syntax.
The deque contains all components that are required for this syntax element, in a canonical order. The returned reference points to a static, never-changing collection that is initialized once at program startup.
§Implementation Pattern
Implementations should use a static item initialized in a const context:
fn required_components() -> &'static GenericArrayDeque<Self::Component, Self::REQUIRED> {
static REQUIRED: GenericArrayDeque<MyComponent, U2> = {
let mut deque = GenericArrayDeque::new();
deque.push_back(MyComponent::Foo);
deque.push_back(MyComponent::Bar);
deque
};
&REQUIRED
}§Examples
let required = MySyntax::required_components();
assert_eq!(required.len(), 2);Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".