use alloc::vec::Vec;
use core::fmt;
use mf2_model::{Diagnostic, Diagnostics, Parsed, Span};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[repr(u8)]
#[non_exhaustive]
pub enum SyntaxKind {
SimpleMessage,
ComplexMessage,
InputDeclaration,
LocalDeclaration,
QuotedPattern,
Pattern,
Matcher,
Variant,
Expression,
MarkupOpen,
MarkupStandalone,
MarkupClose,
Function,
Option,
Attribute,
Variable,
Identifier,
QuotedLiteral,
Text,
Escape,
LiteralText,
UnquotedLiteral,
Name,
Star,
KwInput,
KwLocal,
KwMatch,
LBrace,
RBrace,
LBrace2,
RBrace2,
Pipe,
Dollar,
Colon,
Hash,
Slash,
At,
Equals,
Trivia,
Error,
}
impl SyntaxKind {
pub fn is_token(self) -> bool {
(self as u8) >= (SyntaxKind::Text as u8)
}
pub fn is_node(self) -> bool {
!self.is_token()
}
pub(crate) fn is_semantic_token(self) -> bool {
matches!(
self,
SyntaxKind::Text
| SyntaxKind::Escape
| SyntaxKind::LiteralText
| SyntaxKind::UnquotedLiteral
| SyntaxKind::Name
| SyntaxKind::Star
)
}
pub fn is_markup(self) -> bool {
matches!(
self,
SyntaxKind::MarkupOpen | SyntaxKind::MarkupStandalone | SyntaxKind::MarkupClose
)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct Node {
pub(crate) start: u32,
pub(crate) end: u32,
pub(crate) last: u32,
pub(crate) kind: SyntaxKind,
}
impl Node {
pub fn kind(&self) -> SyntaxKind {
self.kind
}
pub fn span(&self) -> Span {
Span {
start: self.start,
end: self.end,
}
}
pub(crate) fn range(&self) -> core::ops::Range<usize> {
self.start as usize..self.end as usize
}
}
#[derive(Clone, Copy, Debug)]
pub struct CstRef<'a, 'src> {
pub(crate) src: &'src str,
pub(crate) nodes: &'a [Node],
pub(crate) diagnostics: &'a [Diagnostic],
}
impl<'a, 'src> CstRef<'a, 'src> {
pub fn source(&self) -> &'src str {
self.src
}
pub fn root(&self) -> Option<SyntaxNode<'a, 'src>> {
(!self.nodes.is_empty()).then_some(SyntaxNode {
src: self.src,
nodes: self.nodes,
index: 0,
})
}
pub fn nodes(&self) -> &'a [Node] {
self.nodes
}
pub fn diagnostics(&self) -> &'a [Diagnostic] {
self.diagnostics
}
pub fn has_errors(&self) -> bool {
!self.diagnostics.is_empty()
}
pub fn tokens(&self) -> impl Iterator<Item = SyntaxNode<'a, 'src>> + use<'a, 'src> {
let (src, nodes) = (self.src, self.nodes);
nodes
.iter()
.enumerate()
.filter(|(_, n)| n.kind.is_token())
.map(move |(i, _)| SyntaxNode {
src,
nodes,
index: u32::try_from(i).unwrap_or(u32::MAX),
})
}
pub fn to_model(&self) -> Parsed<'src> {
if self.has_errors() || self.nodes.is_empty() {
return Parsed {
message: None,
diagnostics: Diagnostics::from(self.diagnostics.to_vec()),
};
}
crate::model_from_arena(self.src, self.nodes)
}
}
impl fmt::Display for CstRef<'_, '_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for t in self.tokens() {
f.write_str(t.text())?;
}
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct Cst<'src> {
pub(crate) src: &'src str,
pub(crate) nodes: Vec<Node>,
pub(crate) diagnostics: Vec<Diagnostic>,
}
impl<'src> Cst<'src> {
pub fn view(&self) -> CstRef<'_, 'src> {
CstRef {
src: self.src,
nodes: &self.nodes,
diagnostics: &self.diagnostics,
}
}
pub fn source(&self) -> &'src str {
self.src
}
pub fn root(&self) -> Option<SyntaxNode<'_, 'src>> {
self.view().root()
}
pub fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
pub fn has_errors(&self) -> bool {
!self.diagnostics.is_empty()
}
pub fn to_model(&self) -> Parsed<'src> {
self.view().to_model()
}
}
impl fmt::Display for Cst<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.view(), f)
}
}
#[derive(Clone, Copy, Debug)]
pub struct SyntaxNode<'a, 'src> {
src: &'src str,
nodes: &'a [Node],
index: u32,
}
impl<'a, 'src> SyntaxNode<'a, 'src> {
fn node(&self) -> Node {
self.nodes[self.index as usize]
}
pub fn index(&self) -> usize {
self.index as usize
}
pub fn kind(&self) -> SyntaxKind {
self.node().kind
}
pub fn span(&self) -> Span {
self.node().span()
}
pub fn text(&self) -> &'src str {
self.src.get(self.node().range()).unwrap_or("")
}
pub fn is_token(&self) -> bool {
self.kind().is_token()
}
pub fn children(&self) -> impl Iterator<Item = SyntaxNode<'a, 'src>> + use<'a, 'src> {
let (src, nodes) = (self.src, self.nodes);
let end = self.node().last;
let mut next = self.index + 1;
core::iter::from_fn(move || {
if next >= end {
return None;
}
let index = next;
next = nodes.get(index as usize).map_or(end, |n| n.last);
Some(SyntaxNode { src, nodes, index })
})
}
pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode<'a, 'src>> + use<'a, 'src> {
let (src, nodes) = (self.src, self.nodes);
(self.index + 1..self.node().last).map(move |index| SyntaxNode { src, nodes, index })
}
}