use core::fmt;
use std::ops::Range;
use std::ops::RangeBounds;
use byteyarn::Yarn;
use twie::Trie;
use crate::token;
use crate::Never;
use crate::WrongKind;
pub trait Rule: fmt::Debug + TryFrom<Any> + Into<Any> + 'static {
type Token<'lex>: token::Token<'lex>;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind>;
}
pub use crate::token::Sign;
#[derive(Debug)]
#[allow(missing_docs)]
pub enum Any {
Keyword(Keyword),
Bracket(Bracket),
Ident(Ident),
Quoted(Quoted),
Comment(Comment),
Digital(Digital),
}
impl Any {
pub(crate) fn debug_name(&self) -> &'static str {
match self {
Any::Keyword(_) => "Keyword",
Any::Bracket(_) => "Bracket",
Any::Ident(_) => "Ident",
Any::Digital(_) => "Digital",
Any::Quoted(_) => "Quoted",
Any::Comment(_) => "Comment",
}
}
}
impl Rule for Any {
type Token<'lex> = token::Any<'lex>;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind> {
Ok(value)
}
}
#[derive(Debug)]
pub struct Eof(Never);
impl Rule for Eof {
type Token<'lex> = token::Eof<'lex>;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind> {
Err(WrongKind { want: "Eof", got: value.debug_name() })
}
}
impl From<Eof> for Any {
fn from(value: Eof) -> Self {
value.0.from_nothing_anything()
}
}
impl TryFrom<Any> for Eof {
type Error = WrongKind;
fn try_from(value: Any) -> Result<Self, Self::Error> {
Err(WrongKind { want: "Eof", got: value.debug_name() })
}
}
#[derive(Debug)]
pub struct Keyword {
pub(crate) value: Yarn,
}
impl Keyword {
pub fn new(value: impl Into<Yarn>) -> Self {
Self { value: value.into() }
}
}
impl<Y: Into<Yarn>> From<Y> for Keyword {
fn from(value: Y) -> Self {
Keyword::new(value)
}
}
impl Rule for Keyword {
type Token<'lex> = token::Keyword<'lex>;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind> {
match value {
Any::Keyword(rule) => Ok(rule),
_ => Err(WrongKind { want: "Keyword", got: value.debug_name() }),
}
}
}
impl From<Keyword> for Any {
fn from(value: Keyword) -> Self {
Any::Keyword(value)
}
}
impl TryFrom<Any> for Keyword {
type Error = WrongKind;
fn try_from(value: Any) -> Result<Self, Self::Error> {
match value {
Any::Keyword(rule) => Ok(rule),
_ => Err(WrongKind { want: "Keyword", got: value.debug_name() }),
}
}
}
#[derive(Debug)]
pub struct Bracket {
pub(crate) kind: BracketKind,
}
impl Bracket {
pub fn paired(open: impl Into<Yarn>, close: impl Into<Yarn>) -> Self {
let open = open.into();
let close = close.into();
assert!(
!open.is_empty() && !close.is_empty(),
"both arguments to Bracket::paired() must be non-empty"
);
Self { kind: BracketKind::Paired(open, close) }
}
#[track_caller]
pub fn rust_style(
repeating: impl Into<Yarn>,
(open_start, open_end): (impl Into<Yarn>, impl Into<Yarn>),
(close_start, close_end): (impl Into<Yarn>, impl Into<Yarn>),
) -> Self {
let repeating = repeating.into();
let open = (open_start.into(), open_end.into());
let close = (close_start.into(), close_end.into());
assert!(
!repeating.is_empty(),
"the repeating argument of Bracket::rust_style() cannot be empty"
);
assert!(
!open.0.is_empty() || !open.1.is_empty(),
"open_start and open_end cannot both be empty"
);
assert!(
!close.0.is_empty() || !close.1.is_empty(),
"close_start and close_end cannot both be empty"
);
assert!(
!open.1.starts_with(repeating.as_str())
&& !close.1.starts_with(repeating.as_str()),
"open_end and close_end cannot start with the repeating string"
);
Self {
kind: BracketKind::RustLike { repeating, open, close },
}
}
#[track_caller]
pub fn cxx_style(
ident: Ident,
(open_start, open_end): (impl Into<Yarn>, impl Into<Yarn>),
(close_start, close_end): (impl Into<Yarn>, impl Into<Yarn>),
) -> Self {
assert!(
ident.affixes.prefixes.is_empty() && ident.affixes.prefixes.is_empty(),
"Bracket::cxx_style() requires an identifier with no affixes"
);
let open = (open_start.into(), open_end.into());
let close = (close_start.into(), close_end.into());
assert!(
!open.0.is_empty() || !open.1.is_empty(),
"open_start and open_end cannot both be empty"
);
assert!(
!close.0.is_empty() || !close.1.is_empty() || ident.min_len > 0,
"close_start and close_end cannot both be empty with ident having zero minimum length"
);
Self {
kind: BracketKind::CxxLike { ident_rule: ident, open, close },
}
}
}
#[derive(Debug)]
pub(crate) enum BracketKind {
Paired(Yarn, Yarn),
RustLike {
repeating: Yarn,
open: (Yarn, Yarn),
close: (Yarn, Yarn),
},
CxxLike {
ident_rule: Ident,
open: (Yarn, Yarn),
close: (Yarn, Yarn),
},
}
impl Rule for Bracket {
type Token<'lex> = token::Bracket<'lex>;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind> {
match value {
Any::Bracket(rule) => Ok(rule),
_ => Err(WrongKind { want: "Bracket", got: value.debug_name() }),
}
}
}
impl From<Bracket> for Any {
fn from(value: Bracket) -> Self {
Any::Bracket(value)
}
}
impl<Y: Into<Yarn>, Z: Into<Yarn>> From<(Y, Z)> for Bracket {
fn from((y, z): (Y, Z)) -> Self {
Bracket::paired(y, z)
}
}
impl TryFrom<Any> for Bracket {
type Error = WrongKind;
fn try_from(value: Any) -> Result<Self, Self::Error> {
match value {
Any::Bracket(rule) => Ok(rule),
_ => Err(WrongKind { want: "Bracket", got: value.debug_name() }),
}
}
}
#[derive(Debug, Default)]
pub(crate) struct Affixes {
prefixes: Vec<Yarn>,
suffixes: Vec<Yarn>,
}
impl Affixes {
const EMPTY: &'static [Yarn] = &[Yarn::new("")];
pub fn prefixes(&self) -> &[Yarn] {
if self.prefixes.is_empty() {
return Self::EMPTY;
}
&self.prefixes
}
pub fn suffixes(&self) -> &[Yarn] {
if self.suffixes.is_empty() {
return Self::EMPTY;
}
&self.suffixes
}
}
impl fmt::Display for Affixes {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if !self.prefixes.is_empty() {
for (i, pre) in self.prefixes.iter().enumerate() {
if i != 0 {
f.write_str(", ")?;
}
write!(f, "`{pre}`-")?;
}
f.write_str("prefixed")?;
}
if !self.suffixes.is_empty() {
if !self.prefixes.is_empty() {
f.write_str(", ")?;
}
for (i, pre) in self.suffixes.iter().enumerate() {
if i != 0 {
f.write_str(", ")?;
}
write!(f, "`{pre}`-")?;
}
f.write_str("suffixed")?;
}
if !self.prefixes.is_empty() || !self.suffixes.is_empty() {
f.write_str(" ")?;
}
Ok(())
}
}
macro_rules! affixes {
() => {
pub fn prefix(self, prefix: impl Into<Yarn>) -> Self {
self.prefixes([prefix])
}
pub fn suffix(self, suffix: impl Into<Yarn>) -> Self {
self.suffixes([suffix])
}
pub fn prefixes<Y: Into<Yarn>>(
mut self,
prefixes: impl IntoIterator<Item = Y>,
) -> Self {
self
.affixes
.prefixes
.extend(prefixes.into_iter().map(Y::into));
self
}
pub fn suffixes<Y: Into<Yarn>>(
mut self,
suffixes: impl IntoIterator<Item = Y>,
) -> Self {
self
.affixes
.suffixes
.extend(suffixes.into_iter().map(Y::into));
self
}
};
}
#[derive(Default, Debug)]
pub struct Ident {
pub(crate) ascii_only: bool,
pub(crate) extra_starts: String,
pub(crate) extra_continues: String,
pub(crate) affixes: Affixes,
pub(crate) min_len: usize,
}
impl Ident {
pub fn new() -> Self {
Self::default()
}
pub fn ascii_only(mut self) -> Self {
self.ascii_only = true;
self
}
pub fn extra_start(self, c: char) -> Self {
self.extra_starts([c])
}
pub fn extra_starts(mut self, chars: impl IntoIterator<Item = char>) -> Self {
self.extra_starts.extend(chars);
self
}
pub fn extra_continue(self, c: char) -> Self {
self.extra_continues([c])
}
pub fn extra_continues(
mut self,
chars: impl IntoIterator<Item = char>,
) -> Self {
self.extra_continues.extend(chars);
self
}
pub fn min_len(mut self, len: usize) -> Self {
self.min_len = len;
self
}
affixes!();
}
impl Rule for Ident {
type Token<'lex> = token::Ident<'lex>;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind> {
match value {
Any::Ident(rule) => Ok(rule),
_ => Err(WrongKind { want: "Ident", got: value.debug_name() }),
}
}
}
impl From<Ident> for Any {
fn from(value: Ident) -> Self {
Any::Ident(value)
}
}
impl TryFrom<Any> for Ident {
type Error = WrongKind;
fn try_from(value: Any) -> Result<Self, Self::Error> {
match value {
Any::Ident(rule) => Ok(rule),
_ => Err(WrongKind { want: "Ident", got: value.debug_name() }),
}
}
}
#[derive(Debug)]
pub struct Quoted {
pub(crate) bracket: Bracket,
pub(crate) escapes: Trie<str, Escape>,
pub(crate) affixes: Affixes,
}
impl Quoted {
pub fn new(quote: impl Into<Yarn>) -> Self {
let quote = quote.into();
Self::with(Bracket::paired(quote.clone(), quote))
}
pub fn with(bracket: Bracket) -> Self {
Self {
bracket,
escapes: Trie::new(),
affixes: Affixes::default(),
}
}
pub fn escape(self, key: impl Into<Yarn>) -> Self {
self.escapes([key])
}
pub fn escapes<Y: Into<Yarn>>(
mut self,
keys: impl IntoIterator<Item = Y>,
) -> Self {
for key in keys {
let key = key.into();
assert!(!key.is_empty());
self.escapes.insert(&key, Escape::Basic);
}
self
}
pub fn invalid_escape(mut self, key: impl Into<Yarn>) -> Self {
let key = key.into();
assert!(!key.is_empty());
self.escapes.insert(&key, Escape::Invalid);
self
}
pub fn fixed_length_escape(mut self, key: impl Into<Yarn>, len: u32) -> Self {
let key = key.into();
assert!(!key.is_empty());
assert!(len != 0, "cannot create a fixed length escape with length zero");
self.escapes.insert(&key, Escape::Fixed(len));
self
}
pub fn bracketed_escape(
mut self,
key: impl Into<Yarn>,
open: impl Into<Yarn>,
close: impl Into<Yarn>,
) -> Self {
let key = key.into();
assert!(!key.is_empty());
let (open, close) = (open.into(), close.into());
assert!(
!open.is_empty() && !close.is_empty(),
"cannot create a bracketed escape with empty brackets"
);
self.escapes.insert(&key, Escape::Bracketed(open, close));
self
}
pub fn add_rust_escapes(self) -> Self {
self
.invalid_escape(r"\")
.escapes([r"\0", r"\n", r"\r", r"\t", r"\\", "\\\"", r"\'"])
.fixed_length_escape(r"\x", 2)
.bracketed_escape(r"\u", '{', '}')
}
affixes!();
}
impl From<Bracket> for Quoted {
fn from(value: Bracket) -> Self {
Self::with(value)
}
}
impl Rule for Quoted {
type Token<'lex> = token::Quoted<'lex>;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind> {
match value {
Any::Quoted(rule) => Ok(rule),
_ => Err(WrongKind { want: "Quoted", got: value.debug_name() }),
}
}
}
impl From<Quoted> for Any {
fn from(value: Quoted) -> Self {
Any::Quoted(value)
}
}
impl TryFrom<Any> for Quoted {
type Error = WrongKind;
fn try_from(value: Any) -> Result<Self, Self::Error> {
match value {
Any::Quoted(rule) => Ok(rule),
_ => Err(WrongKind { want: "Quoted", got: value.debug_name() }),
}
}
}
#[derive(Debug)]
pub(crate) enum Escape {
Invalid,
Basic,
Fixed(u32),
Bracketed(Yarn, Yarn),
}
#[derive(Debug)]
pub struct Digital {
pub(crate) mant: Digits,
pub(crate) exps: Vec<(Yarn, Digits)>,
pub(crate) max_exps: u32,
pub(crate) separator: Yarn,
pub(crate) corner_cases: SeparatorCornerCases,
pub(crate) point: Yarn,
pub(crate) affixes: Affixes,
}
#[derive(Debug)]
pub struct SeparatorCornerCases {
pub prefix: bool,
pub suffix: bool,
pub around_point: bool,
pub around_exp: bool,
}
impl Default for SeparatorCornerCases {
fn default() -> Self {
SeparatorCornerCases {
prefix: false,
suffix: false,
around_point: true,
around_exp: true,
}
}
}
impl Digital {
pub fn new(radix: u8) -> Self {
assert!(
(2..=16).contains(&radix),
"radix must be within 2..=16, got {radix}"
);
Self::from_digits(Digits::new(radix))
}
pub fn from_digits(digits: Digits) -> Self {
Self {
mant: digits,
exps: Vec::new(),
max_exps: 1,
separator: "".into(),
corner_cases: Default::default(),
point: ".".into(),
affixes: Affixes::default(),
}
}
pub fn separator(self, sep: impl Into<Yarn>) -> Self {
self.separator_with(sep, Default::default())
}
pub fn separator_with(
mut self,
sep: impl Into<Yarn>,
corner_cases: SeparatorCornerCases,
) -> Self {
self.separator = sep.into();
self.corner_cases = corner_cases;
self
}
pub fn point(mut self, x: impl Into<Yarn>) -> Self {
self.point = x.into();
assert!(!self.point.is_empty(), "the point separator cannot be empty");
self
}
pub fn sign(mut self, prefix: impl Into<Yarn>, value: Sign) -> Self {
self.mant = self.mant.sign(prefix, value);
self
}
pub fn plus(self) -> Self {
self.sign('+', Sign::Pos)
}
pub fn minus(self) -> Self {
self.sign('-', Sign::Neg)
}
pub fn point_limit(mut self, range: Range<u32>) -> Self {
self.mant = self.mant.point_limit(range);
self
}
pub fn exponent(mut self, delim: impl Into<Yarn>, exp: Digits) -> Self {
self.exps.push((delim.into(), exp));
self
}
pub fn exponents<Y: Into<Yarn>>(
mut self,
delims: impl IntoIterator<Item = Y>,
exp: Digits,
) -> Self {
for delim in delims {
self.exps.push((delim.into(), exp.clone()));
}
self
}
pub fn max_exponents(mut self, limit: u32) -> Self {
self.max_exps = limit;
self
}
affixes!();
}
#[derive(Debug, Clone)]
pub struct Digits {
pub(crate) radix: u8,
pub(crate) signs: Vec<(Yarn, Sign)>,
pub(crate) min_chunks: u32,
pub(crate) max_chunks: u32,
}
impl Digits {
pub fn new(radix: u8) -> Self {
assert!(
(2..=16).contains(&radix),
"radix must be within 2..=16, got {radix}"
);
Self {
radix,
signs: Vec::new(),
min_chunks: 1,
max_chunks: 1,
}
}
pub fn radix_name(&self) -> &'static str {
match self.radix {
2 => "binary",
3 => "ternary",
4 => "quaternary",
5 => "quinary",
6 => "senary",
7 => "septenary",
8 => "octal",
9 => "nonary",
10 => "decimal",
11 => "undecimal",
12 => "duodecimal",
13 => "tridecimal",
14 => "tetradecimal",
15 => "pentadecimal",
16 => "hexadecmial",
_ => unreachable!(),
}
}
pub fn sign(mut self, prefix: impl Into<Yarn>, value: Sign) -> Self {
self.signs.push((prefix.into(), value));
self
}
pub fn plus(self) -> Self {
self.sign('+', Sign::Pos)
}
pub fn minus(self) -> Self {
self.sign('-', Sign::Neg)
}
pub fn point_limit(mut self, range: impl RangeBounds<u32>) -> Self {
self.min_chunks = match range.start_bound() {
std::ops::Bound::Included(&x) => x.saturating_add(1),
std::ops::Bound::Excluded(&x) => x.saturating_add(2),
std::ops::Bound::Unbounded => 1,
};
self.max_chunks = match range.end_bound() {
std::ops::Bound::Included(&x) => x.saturating_add(1),
std::ops::Bound::Excluded(&x) => x,
std::ops::Bound::Unbounded => u32::MAX,
};
self
}
}
impl Rule for Digital {
type Token<'lex> = token::Digital<'lex>;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind> {
match value {
Any::Digital(rule) => Ok(rule),
_ => Err(WrongKind { want: "Digital", got: value.debug_name() }),
}
}
}
impl From<Digital> for Any {
fn from(value: Digital) -> Self {
Any::Digital(value)
}
}
impl TryFrom<Any> for Digital {
type Error = WrongKind;
fn try_from(value: Any) -> Result<Self, Self::Error> {
match value {
Any::Digital(rule) => Ok(rule),
_ => Err(WrongKind { want: "Digital", got: value.debug_name() }),
}
}
}
#[derive(Debug)]
pub struct Comment {
pub(crate) bracket: Bracket,
pub(crate) can_nest: bool,
}
impl Comment {
pub fn line(delim: impl Into<Yarn>) -> Self {
Self::non_nesting((delim, "\n").into())
}
pub fn block(open: impl Into<Yarn>, close: impl Into<Yarn>) -> Self {
Self::nesting((open, close).into())
}
pub fn nesting(bracket: Bracket) -> Self {
Self { bracket, can_nest: true }
}
pub fn non_nesting(bracket: Bracket) -> Self {
Self { bracket, can_nest: false }
}
}
impl From<&'static str> for Comment {
fn from(value: &'static str) -> Self {
Self::line(value)
}
}
impl From<char> for Comment {
fn from(value: char) -> Self {
Self::line(value)
}
}
impl From<Yarn> for Comment {
fn from(value: Yarn) -> Self {
Self::line(value)
}
}
impl<Y: Into<Yarn>, Z: Into<Yarn>> From<(Y, Z)> for Comment {
fn from((y, z): (Y, Z)) -> Self {
Self::block(y, z)
}
}
impl Rule for Comment {
type Token<'lex> = Never;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind> {
match value {
Any::Comment(rule) => Ok(rule),
_ => Err(WrongKind { want: "Comment", got: value.debug_name() }),
}
}
}
impl From<Comment> for Any {
fn from(value: Comment) -> Self {
Any::Comment(value)
}
}
impl TryFrom<Any> for Comment {
type Error = WrongKind;
fn try_from(value: Any) -> Result<Self, Self::Error> {
match value {
Any::Comment(rule) => Ok(rule),
_ => Err(WrongKind { want: "Comment", got: value.debug_name() }),
}
}
}
impl Rule for Never {
type Token<'lex> = token::Eof<'lex>;
fn try_from_ref(value: &Any) -> Result<&Self, WrongKind> {
Err(WrongKind { want: "Never", got: value.debug_name() })
}
}
impl From<Never> for Any {
fn from(value: Never) -> Self {
value.from_nothing_anything()
}
}
impl TryFrom<Any> for Never {
type Error = WrongKind;
fn try_from(value: Any) -> Result<Self, Self::Error> {
Err(WrongKind { want: "Never", got: value.debug_name() })
}
}