test top level expr parsing

This commit is contained in:
🪞👃🪞 2025-01-18 22:17:10 +01:00
parent d14d67172c
commit 9756862091
7 changed files with 129 additions and 82 deletions

View file

@ -20,48 +20,44 @@ pub const fn peek_src <'a> (source: &'a str) -> Option<Token<'a>> {
Err(_) => return Some(token),
Nil => match c {
' '|'\n'|'\r'|'\t' => token.grow(),
'(' => Token {
source, start, length: 1,
'(' => Token { source, start, length: 1,
value: Value::Exp(1, TokenIter(str_range(source, start, start + 1))),
},
'0'..='9' => Token {
source, start, length: 1,
':'|'@' => Token { source, start, length: 1,
value: Value::Sym(str_range(source, start, start + 1)),
},
'/'|'a'..='z' => Token { source, start, length: 1,
value: Value::Key(str_range(source, start, start + 1)),
},
'0'..='9' => Token { source, start, length: 1,
value: match to_digit(c) {
Ok(c) => Value::Num(c),
Result::Err(e) => Value::Err(e)
}
},
':'|'@' => Token {
source, start, length: 1,
value: Value::Sym(str_range(source, start, start + 1)),
},
'/'|'a'..='z' => Token {
source, start, length: 1,
value: Value::Key(str_range(source, start, start + 1)),
},
_ => token.error(Unexpected(c))
},
Num(_) => match c {
'0'..='9' => token.grow(),
Num(n) => match c {
'0'..='9' => token.grow_num(n, c),
' '|'\n'|'\r'|'\t' => return Some(token),
_ => token.error(Unexpected(c))
},
Sym(_) => match c {
'a'..='z'|'0'..='9'|'-' => token.grow(),
'a'..='z'|'0'..='9'|'-' => token.grow_sym(),
' '|'\n'|'\r'|'\t' => return Some(token),
_ => token.error(Unexpected(c))
},
Key(_) => match c {
'a'..='z'|'0'..='9'|'-'|'/' => token.grow(),
'a'..='z'|'0'..='9'|'-'|'/' => token.grow_key(),
' '|'\n'|'\r'|'\t' => return Some(token),
_ => token.error(Unexpected(c))
},
Exp(depth, _) => match depth {
0 => return Some(token),
0 => return Some(token.grow_exp()),
_ => match c {
')' => token.grow_out(),
'(' => token.grow_in(),
_ => token.grow(),
_ => token.grow_exp(),
}
},
});

View file

@ -43,44 +43,65 @@ pub(crate) use std::fmt::{Debug, Display, Formatter, Result as FormatResult, Err
}
}
#[cfg(test)] #[test] fn test_token () -> Result<(), Box<dyn std::error::Error>> {
use Token::*;
assert_eq!(Nil, Token::chomp_one("")?);
assert_eq!(Nil, Token::chomp_one(" \n \r \t ")?);
assert_eq!(Num("8", 0, 1), Token::chomp_one("8")?);
assert_eq!(Num(" 8 ", 3, 1), Token::chomp_one(" 8 ")?);
assert_eq!(Sym(":foo", 0, 4), Token::chomp_one(":foo")?);
assert_eq!(Sym("@bar", 0, 4), Token::chomp_one("@bar")?);
assert_eq!(Key("foo/bar", 0, 7), Token::chomp_one("foo/bar")?);
let source = ":f00";
let mut token = Token { source, start: 0, length: 1, value: Sym(":") };
token = token.grow_sym();
assert_eq!(token, Token { source, start: 0, length: 2, value: Sym(":f") });
token = token.grow_sym();
assert_eq!(token, Token { source, start: 0, length: 3, value: Sym(":f0") });
token = token.grow_sym();
assert_eq!(token, Token { source, start: 0, length: 4, value: Sym(":f00") });
let src = "";
assert_eq!(None, TokenIter(src).next());
let src = " \n \r \t ";
assert_eq!(None, TokenIter(src).next());
let src = "7";
assert_eq!(Num(7), TokenIter(src).next().unwrap().0.value);
let src = " 100 ";
assert_eq!(Num(100), TokenIter(src).next().unwrap().0.value);
let src = " 9a ";
assert_eq!(Err(Unexpected('a')), TokenIter(src).next().unwrap().0.value);
let src = " :123foo ";
assert_eq!(Sym(":123foo"), TokenIter(src).next().unwrap().0.value);
let src = " \r\r\r\n\n\n@bar456\t\t\t\t\t\t";
assert_eq!(Sym("@bar456"), TokenIter(src).next().unwrap().0.value);
let src = "foo123";
assert_eq!(Key("foo123"), TokenIter(src).next().unwrap().0.value);
let src = "foo/bar";
assert_eq!(Key("foo/bar"), TokenIter(src).next().unwrap().0.value);
Ok(())
}
#[cfg(test)] #[test] fn test_lang () -> Result<(), ParseError> {
use Atom::*;
assert_eq!(Atom::read_all("")?,
vec![]);
assert_eq!(Atom::read_all(" ")?,
vec![]);
assert_eq!(Atom::read_all("1234")?,
vec![Num(1234)]);
assert_eq!(Atom::read_all("1234 5 67")?,
vec![Num(1234), Num(5), Num(67)]);
assert_eq!(Atom::read_all("foo/bar")?,
vec![Key("foo/bar".into())]);
assert_eq!(Atom::read_all(":symbol")?,
vec![Sym(":symbol".into())]);
assert_eq!(Atom::read_all(" foo/bar :baz 456")?,
vec![Key("foo/bar".into()), Sym(":baz".into()), Num(456)]);
assert_eq!(Atom::read_all(" (foo/bar :baz 456) ")?,
vec![Exp(vec![Key("foo/bar".into()), Sym(":baz".into()), Num(456)])]);
Ok(())
}
#[cfg(test)] #[test] fn test_lang_examples () -> Result<(), ParseError> {
for example in [
include_str!("../../tui/examples/edn01.edn"),
include_str!("../../tui/examples/edn02.edn"),
] {
let items = Atom::read_all(example)?;
//panic!("{layout:?}");
//let content = <dyn ViewContext<::tek_engine::tui::Tui>>::from(&layout);
}
#[cfg(test)] #[test] fn test_examples () -> Result<(), ParseError> {
let src = include_str!("../../tek/src/view_arranger.edn");
let mut view = TokenIter(src);
assert_eq!(view.0, src);
let mut expr = view.peek();
assert_eq!(view.0, src);
assert_eq!(expr, Some(Token {
source: src,
start: 0,
length: src.len(),
value: Exp(0, TokenIter(src))
}));
//panic!("{view:?}");
//panic!("{:#?}", expr);
//for example in [
//include_str!("../../tui/examples/edn01.edn"),
//include_str!("../../tui/examples/edn02.edn"),
//] {
////let items = Atom::read_all(example)?;
////panic!("{layout:?}");
////let content = <dyn ViewContext<::tek_engine::tui::Tui>>::from(&layout);
//}
Ok(())
}

View file

@ -4,7 +4,7 @@ use self::Value::*;
pub source: &'a str,
pub start: usize,
pub length: usize,
pub value: Value<'a>,
pub value: Value<'a>,
}
#[derive(Debug, Copy, Clone, Default, PartialEq)] pub enum Value<'a> {
#[default] Nil,
@ -37,25 +37,51 @@ impl<'a> Token<'a> {
pub const fn grow (self) -> Self {
Self { length: self.length + 1, ..self }
}
pub const fn grow_in (self) -> Self {
match self.value {
Value::Exp(depth, source) => Self {
value: Value::Exp(depth + 1, TokenIter(self.grow().slice_source(source.0))),
..self.grow()
},
_ => self.grow()
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_exp (self) -> Self {
let mut token = self.grow();
if let Exp(depth, _) = token.value {
token.value = Exp(depth, TokenIter(token.slice_source(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 + 1, source)
} else {
unreachable!()
}
token
}
pub const fn grow_out (self) -> Self {
match self.value {
Value::Exp(depth, source) => match depth {
0 => self.error(Unexpected(')')),
d => Self {
value: Value::Exp(d - 1, TokenIter(self.grow().slice_source(source.0))),
..self.grow()
}
},
_ => self.grow()
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
}
}