use crate::validated::{
ExternalTokenDecl, ExternalTokenFact, ExternalTokenId, ExternalTokenOrdinal, GrammarExpr,
GrammarExprId, ValidatedGrammar,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LexicalFacts {
external_tokens: Vec<ExternalScannerToken>,
valid_symbol_mask_width: usize,
extra_roots: Vec<GrammarExprId>,
lexical_roots: Vec<LexicalRoot>,
terminals: Vec<TerminalFact>,
scanner_abi: ScannerHostAbi,
}
impl LexicalFacts {
pub fn from_grammar(grammar: &ValidatedGrammar) -> Self {
let external_tokens = grammar
.externals()
.iter()
.map(ExternalScannerToken::from_fact)
.collect::<Vec<_>>();
let mut lexical_roots = Vec::new();
let mut terminals = Vec::new();
for (id, expr) in grammar.expressions() {
match expr {
GrammarExpr::Token(content) => lexical_roots.push(LexicalRoot {
id,
content: *content,
immediate: false,
}),
GrammarExpr::ImmediateToken(content) => lexical_roots.push(LexicalRoot {
id,
content: *content,
immediate: true,
}),
GrammarExpr::StringToken(value) => terminals.push(TerminalFact {
expr: id,
kind: TerminalKind::String,
spelling: value.clone(),
}),
GrammarExpr::PatternToken { value, .. } => terminals.push(TerminalFact {
expr: id,
kind: TerminalKind::Pattern,
spelling: value.clone(),
}),
_ => {}
}
}
let valid_symbol_mask_width = external_tokens.len();
Self {
external_tokens,
valid_symbol_mask_width,
extra_roots: grammar.extras().to_vec(),
lexical_roots,
terminals,
scanner_abi: ScannerHostAbi::new(valid_symbol_mask_width),
}
}
pub fn external_tokens(&self) -> &[ExternalScannerToken] {
&self.external_tokens
}
pub fn valid_symbol_mask_width(&self) -> usize {
self.valid_symbol_mask_width
}
pub fn extra_roots(&self) -> &[GrammarExprId] {
&self.extra_roots
}
pub fn lexical_roots(&self) -> &[LexicalRoot] {
&self.lexical_roots
}
pub fn terminals(&self) -> &[TerminalFact] {
&self.terminals
}
pub fn scanner_abi(&self) -> &ScannerHostAbi {
&self.scanner_abi
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExternalScannerToken {
id: ExternalTokenId,
ordinal: ExternalTokenOrdinal,
name: Option<String>,
declaration: ExternalTokenDecl,
}
impl ExternalScannerToken {
fn from_fact(fact: &ExternalTokenFact) -> Self {
Self {
id: fact.id(),
ordinal: fact.ordinal(),
name: fact.name().map(str::to_owned),
declaration: fact.declaration().clone(),
}
}
pub const fn id(&self) -> ExternalTokenId {
self.id
}
pub const fn ordinal(&self) -> ExternalTokenOrdinal {
self.ordinal
}
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}
pub const fn declaration(&self) -> &ExternalTokenDecl {
&self.declaration
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LexicalRoot {
pub id: GrammarExprId,
pub content: GrammarExprId,
pub immediate: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TerminalFact {
pub expr: GrammarExprId,
pub kind: TerminalKind,
pub spelling: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum TerminalKind {
String,
Pattern,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScannerHostAbi {
valid_symbol_mask_width: usize,
operations: Vec<ScannerHostOperation>,
supports_serialized_state: bool,
}
impl ScannerHostAbi {
fn new(valid_symbol_mask_width: usize) -> Self {
Self {
valid_symbol_mask_width,
operations: vec![
ScannerHostOperation::Advance,
ScannerHostOperation::MarkEnd,
ScannerHostOperation::SetResultSymbol,
ScannerHostOperation::IsAtEnd,
ScannerHostOperation::Serialize,
ScannerHostOperation::Deserialize,
],
supports_serialized_state: true,
}
}
pub fn valid_symbol_mask_width(&self) -> usize {
self.valid_symbol_mask_width
}
pub fn operations(&self) -> &[ScannerHostOperation] {
&self.operations
}
pub fn supports_serialized_state(&self) -> bool {
self.supports_serialized_state
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum ScannerHostOperation {
Advance,
MarkEnd,
SetResultSymbol,
IsAtEnd,
Serialize,
Deserialize,
}