mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 19:56:44 +01:00
dsl: compact
This commit is contained in:
parent
5e09f5a4bb
commit
ab07fd2b43
8 changed files with 363 additions and 384 deletions
|
|
@ -1,120 +0,0 @@
|
|||
//! [Token]s are parsed substrings with an associated [Value].
|
||||
//!
|
||||
//! * [ ] FIXME: Value may be [Err] which may shadow [Result::Err]
|
||||
//! * [Value::Exp] wraps an expression depth and a [SourceIter]
|
||||
//! with the remaining part of the expression.
|
||||
//! * expression depth other that 0 mean unclosed parenthesis.
|
||||
//! * closing and unopened parenthesis panics during reading.
|
||||
//! * [ ] TODO: signed depth might be interesting
|
||||
//! * [Value::Sym] and [Value::Key] are stringish literals
|
||||
//! with slightly different parsing rules.
|
||||
//! * [Value::Num] is an unsigned integer literal.
|
||||
//!```
|
||||
//! use tengri_dsl::{*, Value::*};
|
||||
//! let source = include_str!("../test.edn");
|
||||
//! let mut view = TokenIter::new(source);
|
||||
//! assert_eq!(view.peek(), Some(Token {
|
||||
//! source,
|
||||
//! start: 0,
|
||||
//! length: source.len(),
|
||||
//! value: Exp(0, TokenIter::new(&source[1..]))
|
||||
//! }));
|
||||
//!```
|
||||
use crate::*;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, PartialEq)] pub struct Token<'source> {
|
||||
pub source: &'source str,
|
||||
pub start: usize,
|
||||
pub length: usize,
|
||||
pub value: Value<'source>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, PartialEq)] pub enum Value<'source> {
|
||||
#[default] Nil,
|
||||
Err(ParseError),
|
||||
Num(usize),
|
||||
Sym(&'source str),
|
||||
Key(&'source str),
|
||||
Str(&'source str),
|
||||
Exp(usize, TokenIter<'source>),
|
||||
}
|
||||
|
||||
impl<'source> Token<'source> {
|
||||
pub const fn new (source: &'source str, start: usize, length: usize, value: Value<'source>) -> Self {
|
||||
Self { source, start, length, value }
|
||||
}
|
||||
pub const fn end (&self) -> usize {
|
||||
self.start.saturating_add(self.length)
|
||||
}
|
||||
pub const fn slice (&'source self) -> &'source str {
|
||||
self.slice_source(self.source)
|
||||
//str_range(self.source, self.start, self.end())
|
||||
}
|
||||
pub const fn slice_source <'range> (&'source self, source: &'range str) -> &'range str {
|
||||
str_range(source, self.start, self.end())
|
||||
}
|
||||
pub const fn slice_source_exp <'range> (&'source self, source: &'range str) -> &'range str {
|
||||
str_range(source, self.start.saturating_add(1), self.end())
|
||||
}
|
||||
pub const fn value (&self) -> Value {
|
||||
self.value
|
||||
}
|
||||
pub const fn error (self, error: ParseError) -> Self {
|
||||
Self { value: Value::Err(error), ..self }
|
||||
}
|
||||
pub const fn grow (self) -> Self {
|
||||
Self { length: self.length.saturating_add(1), ..self }
|
||||
}
|
||||
pub const fn grow_num (self, m: usize, c: char) -> Self {
|
||||
match to_digit(c) {
|
||||
Ok(n) => Self { value: Num(10*m+n), ..self.grow() },
|
||||
Result::Err(e) => Self { value: Err(e), ..self.grow() },
|
||||
}
|
||||
}
|
||||
pub const fn grow_key (self) -> Self {
|
||||
let mut token = self.grow();
|
||||
token.value = Key(token.slice_source(self.source));
|
||||
token
|
||||
}
|
||||
pub const fn grow_sym (self) -> Self {
|
||||
let mut token = self.grow();
|
||||
token.value = Sym(token.slice_source(self.source));
|
||||
token
|
||||
}
|
||||
pub const fn grow_str (self) -> Self {
|
||||
let mut token = self.grow();
|
||||
token.value = Str(token.slice_source(self.source));
|
||||
token
|
||||
}
|
||||
pub const fn grow_exp (self) -> Self {
|
||||
let mut token = self.grow();
|
||||
if let Exp(depth, _) = token.value {
|
||||
token.value = Exp(depth, TokenIter::new(token.slice_source_exp(self.source)));
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
token
|
||||
}
|
||||
pub const fn grow_in (self) -> Self {
|
||||
let mut token = self.grow_exp();
|
||||
if let Value::Exp(depth, source) = token.value {
|
||||
token.value = Value::Exp(depth.saturating_add(1), source)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
token
|
||||
}
|
||||
pub const fn grow_out (self) -> Self {
|
||||
let mut token = self.grow_exp();
|
||||
if let Value::Exp(depth, source) = token.value {
|
||||
if depth > 0 {
|
||||
token.value = Value::Exp(depth - 1, source)
|
||||
} else {
|
||||
return self.error(Unexpected(')'))
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
token
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue