mirror of
https://github.com/typst/typst
synced 2025-05-15 09:35:28 +08:00
188 lines
5.5 KiB
Rust
188 lines
5.5 KiB
Rust
// Acknowledgement:
|
|
// Based on rust-analyzer's `TokenSet`.
|
|
// https://github.com/rust-lang/rust-analyzer/blob/master/crates/parser/src/token_set.rs
|
|
|
|
use crate::SyntaxKind;
|
|
|
|
/// A set of syntax kinds.
|
|
#[derive(Default, Copy, Clone)]
|
|
pub struct SyntaxSet(u128);
|
|
|
|
impl SyntaxSet {
|
|
/// Create a new set from a slice of kinds.
|
|
pub const fn new() -> Self {
|
|
Self(0)
|
|
}
|
|
|
|
/// Insert a syntax kind into the set.
|
|
///
|
|
/// You can only add kinds with discriminator < 128.
|
|
pub const fn add(self, kind: SyntaxKind) -> Self {
|
|
assert!((kind as u8) < BITS);
|
|
Self(self.0 | bit(kind))
|
|
}
|
|
|
|
/// Combine two syntax sets.
|
|
pub const fn union(self, other: Self) -> Self {
|
|
Self(self.0 | other.0)
|
|
}
|
|
|
|
/// Whether the set contains the given syntax kind.
|
|
pub const fn contains(&self, kind: SyntaxKind) -> bool {
|
|
(kind as u8) < BITS && (self.0 & bit(kind)) != 0
|
|
}
|
|
}
|
|
|
|
const BITS: u8 = 128;
|
|
|
|
const fn bit(kind: SyntaxKind) -> u128 {
|
|
1 << (kind as usize)
|
|
}
|
|
|
|
/// Syntax kinds that can start a statement.
|
|
pub const STMT: SyntaxSet = SyntaxSet::new()
|
|
.add(SyntaxKind::Let)
|
|
.add(SyntaxKind::Set)
|
|
.add(SyntaxKind::Show)
|
|
.add(SyntaxKind::Import)
|
|
.add(SyntaxKind::Include)
|
|
.add(SyntaxKind::Return);
|
|
|
|
/// Syntax kinds that can start a markup expression.
|
|
pub const MARKUP_EXPR: SyntaxSet = SyntaxSet::new()
|
|
.add(SyntaxKind::Space)
|
|
.add(SyntaxKind::Parbreak)
|
|
.add(SyntaxKind::LineComment)
|
|
.add(SyntaxKind::BlockComment)
|
|
.add(SyntaxKind::Decorator)
|
|
.add(SyntaxKind::Text)
|
|
.add(SyntaxKind::Linebreak)
|
|
.add(SyntaxKind::Escape)
|
|
.add(SyntaxKind::Shorthand)
|
|
.add(SyntaxKind::SmartQuote)
|
|
.add(SyntaxKind::RawDelim)
|
|
.add(SyntaxKind::Link)
|
|
.add(SyntaxKind::Label)
|
|
.add(SyntaxKind::Hash)
|
|
.add(SyntaxKind::Star)
|
|
.add(SyntaxKind::Underscore)
|
|
.add(SyntaxKind::HeadingMarker)
|
|
.add(SyntaxKind::ListMarker)
|
|
.add(SyntaxKind::EnumMarker)
|
|
.add(SyntaxKind::TermMarker)
|
|
.add(SyntaxKind::RefMarker)
|
|
.add(SyntaxKind::Dollar)
|
|
.add(SyntaxKind::LeftBracket)
|
|
.add(SyntaxKind::RightBracket)
|
|
.add(SyntaxKind::Colon);
|
|
|
|
/// Syntax kinds that can start a math expression.
|
|
pub const MATH_EXPR: SyntaxSet = SyntaxSet::new()
|
|
.add(SyntaxKind::Hash)
|
|
.add(SyntaxKind::MathIdent)
|
|
.add(SyntaxKind::Text)
|
|
.add(SyntaxKind::Shorthand)
|
|
.add(SyntaxKind::Linebreak)
|
|
.add(SyntaxKind::MathAlignPoint)
|
|
.add(SyntaxKind::Escape)
|
|
.add(SyntaxKind::Str)
|
|
.add(SyntaxKind::Root)
|
|
.add(SyntaxKind::Prime);
|
|
|
|
/// Syntax kinds that can start a code expression.
|
|
pub const CODE_EXPR: SyntaxSet = CODE_PRIMARY.union(UNARY_OP);
|
|
|
|
/// Syntax kinds that can start an atomic code expression.
|
|
pub const ATOMIC_CODE_EXPR: SyntaxSet = ATOMIC_CODE_PRIMARY;
|
|
|
|
/// Syntax kinds that can start a code primary.
|
|
pub const CODE_PRIMARY: SyntaxSet = ATOMIC_CODE_PRIMARY.add(SyntaxKind::Underscore);
|
|
|
|
/// Syntax kinds that can start an atomic code primary.
|
|
pub const ATOMIC_CODE_PRIMARY: SyntaxSet = SyntaxSet::new()
|
|
.add(SyntaxKind::Ident)
|
|
.add(SyntaxKind::LeftBrace)
|
|
.add(SyntaxKind::LeftBracket)
|
|
.add(SyntaxKind::LeftParen)
|
|
.add(SyntaxKind::Dollar)
|
|
.add(SyntaxKind::Let)
|
|
.add(SyntaxKind::Set)
|
|
.add(SyntaxKind::Show)
|
|
.add(SyntaxKind::Context)
|
|
.add(SyntaxKind::If)
|
|
.add(SyntaxKind::While)
|
|
.add(SyntaxKind::For)
|
|
.add(SyntaxKind::Import)
|
|
.add(SyntaxKind::Include)
|
|
.add(SyntaxKind::Break)
|
|
.add(SyntaxKind::Continue)
|
|
.add(SyntaxKind::Return)
|
|
.add(SyntaxKind::None)
|
|
.add(SyntaxKind::Auto)
|
|
.add(SyntaxKind::Int)
|
|
.add(SyntaxKind::Float)
|
|
.add(SyntaxKind::Bool)
|
|
.add(SyntaxKind::Numeric)
|
|
.add(SyntaxKind::Str)
|
|
.add(SyntaxKind::Label)
|
|
.add(SyntaxKind::RawDelim);
|
|
|
|
/// Syntax kinds that are unary operators.
|
|
pub const UNARY_OP: SyntaxSet = SyntaxSet::new()
|
|
.add(SyntaxKind::Plus)
|
|
.add(SyntaxKind::Minus)
|
|
.add(SyntaxKind::Not);
|
|
|
|
/// Syntax kinds that are binary operators.
|
|
pub const BINARY_OP: SyntaxSet = SyntaxSet::new()
|
|
.add(SyntaxKind::Plus)
|
|
.add(SyntaxKind::Minus)
|
|
.add(SyntaxKind::Star)
|
|
.add(SyntaxKind::Slash)
|
|
.add(SyntaxKind::And)
|
|
.add(SyntaxKind::Or)
|
|
.add(SyntaxKind::EqEq)
|
|
.add(SyntaxKind::ExclEq)
|
|
.add(SyntaxKind::Lt)
|
|
.add(SyntaxKind::LtEq)
|
|
.add(SyntaxKind::Gt)
|
|
.add(SyntaxKind::GtEq)
|
|
.add(SyntaxKind::Eq)
|
|
.add(SyntaxKind::In)
|
|
.add(SyntaxKind::PlusEq)
|
|
.add(SyntaxKind::HyphEq)
|
|
.add(SyntaxKind::StarEq)
|
|
.add(SyntaxKind::SlashEq);
|
|
|
|
/// Syntax kinds that can start an argument in a function call.
|
|
pub const ARRAY_OR_DICT_ITEM: SyntaxSet = CODE_EXPR.add(SyntaxKind::Dots);
|
|
|
|
/// Syntax kinds that can start an argument in a function call.
|
|
pub const ARG: SyntaxSet = CODE_EXPR.add(SyntaxKind::Dots);
|
|
|
|
/// Syntax kinds that can start a parameter in a parameter list.
|
|
pub const PARAM: SyntaxSet = PATTERN.add(SyntaxKind::Dots);
|
|
|
|
/// Syntax kinds that can start a destructuring item.
|
|
pub const DESTRUCTURING_ITEM: SyntaxSet = PATTERN.add(SyntaxKind::Dots);
|
|
|
|
/// Syntax kinds that can start a pattern.
|
|
pub const PATTERN: SyntaxSet =
|
|
PATTERN_LEAF.add(SyntaxKind::LeftParen).add(SyntaxKind::Underscore);
|
|
|
|
/// Syntax kinds that can start a pattern leaf.
|
|
pub const PATTERN_LEAF: SyntaxSet = ATOMIC_CODE_EXPR;
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_set() {
|
|
let set = SyntaxSet::new().add(SyntaxKind::And).add(SyntaxKind::Or);
|
|
assert!(set.contains(SyntaxKind::And));
|
|
assert!(set.contains(SyntaxKind::Or));
|
|
assert!(!set.contains(SyntaxKind::Not));
|
|
}
|
|
}
|