Browse Source

move parser to root of vire, add test code

master
Alison Watson 9 months ago
parent
commit
6bf7f8d92e
  1. 16
      bl/main.rs
  2. 98
      fw/vire.rs
  3. 97
      fw/vire/parser.rs
  4. 32
      fw/vire/tki.rs
  5. 6
      fw/vire/tok.rs

16
bl/main.rs

@ -2,10 +2,23 @@
use blonkus_fw as fw;
fn entry(conf: &fw::conf::Conf) -> Result<(), Box<dyn std::error::Error>> {
fn entry(_conf: &fw::conf::Conf) -> Result<(), Box<dyn std::error::Error>> {
let mut vfs = fw::data::vfs::Vfs::default();
vfs.add_path("testres")?;
let mut sym_t = fw::types::sym::SymbolTable::new();
log::trace!(
"{:#?}",
fw::vire::Cell::parse(
fw::vire::Token::read_all(
"main.vire",
vfs.get("main.vire").unwrap().text()?
)?,
&mut sym_t
)?
);
/*
let hal = fw::hal::ctx::Context::new()?;
let win = fw::hal::win::Window::new(&hal, fw::c_str!("BLONKUS"), 640, 480)?;
let mut ren = fw::render::Renderer::new(
@ -28,6 +41,7 @@ fn entry(conf: &fw::conf::Conf) -> Result<(), Box<dyn std::error::Error>> {
ren.draw_frame()?;
}
*/
Ok(())
}

98
fw/vire.rs

@ -1,9 +1,12 @@
use crate::types::sym;
mod tki;
mod tok;
pub mod parser;
pub mod rt;
//mod llvm;
use crate::types::sym;
pub use tki::TokenIter;
pub use tok::{Token, Type};
#[derive(Clone, Debug)]
pub enum Cell {
@ -23,4 +26,93 @@ pub enum Cell {
// struct Fixed(i64); // Q47.16s
// struct Angle(i32); // Q0.31s
#[derive(thiserror::Error, Debug)]
pub enum Err {
#[error(transparent)]
Iter(#[from] tki::Err),
#[error(transparent)]
Symb(#[from] sym::SymbolOverflowError),
}
impl Cell {
pub fn parse(
mut tki: TokenIter, syms: &mut sym::SymbolTable,
) -> Result<Vec<Self>, Err> {
let mut cells = Vec::new();
while tki.peek().is_some() {
cells.push(cell(&mut tki, syms)?);
}
Ok(cells)
}
}
fn cell(
tki: &mut TokenIter, syms: &mut sym::SymbolTable,
) -> Result<Cell, Err> {
use self::Type::*;
match tki.err_next()? {
// atoms
| Token { typ: Bool, cel, .. }
| Token { typ: Char, cel, .. }
| Token { typ: Numb, cel, .. }
| Token { typ: Strn, cel, .. } => Ok(cel),
| Token { typ: Symb, cel: Cell::Strn(s), .. } => {
Ok(Cell::Symb(syms.intern(s)?))
}
// lists
| Token { typ: Br1O, .. } => list(tki, syms, Br1C),
| Token { typ: Br3O, .. } => list(tki, syms, Br3C),
// abbreviations
| Token { typ: QQuo, .. } => abbrev(tki, syms, "quasiquote"),
| Token { typ: QSyn, .. } => abbrev(tki, syms, "quasisyntax"),
| Token { typ: Quot, .. } => abbrev(tki, syms, "quote"),
| Token { typ: Synt, .. } => abbrev(tki, syms, "syntax"),
| Token { typ: UnQS, .. } => abbrev(tki, syms, "unquote-splicing"),
| Token { typ: UnQu, .. } => abbrev(tki, syms, "unquote"),
| Token { typ: UnSS, .. } => abbrev(tki, syms, "unsyntax-splicing"),
| Token { typ: UnSy, .. } => abbrev(tki, syms, "unsyntax"),
| Token { typ, pos, .. } => Err(tki::Err::Unexpected(typ, pos).into()),
}
}
fn abbrev(
tki: &mut TokenIter, syms: &mut sym::SymbolTable, name: &'static str,
) -> Result<Cell, Err> {
let cdr = {
let cdr = Box::new(Cell::Null);
let car = Box::new(cell(tki, syms)?);
Box::new(Cell::Cons { cdr, car })
};
let car = Box::new(Cell::Symb(syms.intern(name)?));
Ok(Cell::Cons { cdr, car })
}
fn list(
tki: &mut TokenIter, syms: &mut sym::SymbolTable, end: Type,
) -> Result<Cell, Err> {
let mut data_v = Vec::new();
let mut cdr = Cell::Null;
while !tki.drop(end)? {
if tki.drop(Type::Peri)? {
cdr = cell(tki, syms)?;
tki.expect(end)?;
break;
} else {
data_v.push(cell(tki, syms)?);
}
}
for car in data_v.into_iter().rev() {
cdr = Cell::Cons { car: Box::new(car), cdr: Box::new(cdr) };
}
Ok(cdr)
}
// EOF

97
fw/vire/parser.rs

@ -1,97 +0,0 @@
pub mod tki;
pub mod tok;
use self::{
tki::TokenIter,
tok::{Token, Type::*},
};
use super::Cell;
use crate::types::sym;
#[derive(thiserror::Error, Debug)]
pub enum Err {
#[error(transparent)]
Iter(#[from] tki::Err),
#[error(transparent)]
Symb(#[from] sym::SymbolOverflowError),
}
pub fn parse(
tki: &mut TokenIter, syms: &mut sym::SymbolTable,
) -> Result<Vec<Cell>, Err> {
let mut cells = Vec::new();
while tki.peek().is_some() {
cells.push(cell(tki, syms)?);
}
Ok(cells)
}
fn cell(
tki: &mut TokenIter, syms: &mut sym::SymbolTable,
) -> Result<Cell, Err> {
match tki.err_next()? {
// atoms
| Token { typ: Bool, cel, .. }
| Token { typ: Char, cel, .. }
| Token { typ: Numb, cel, .. }
| Token { typ: Strn, cel, .. } => Ok(cel),
| Token { typ: Symb, cel: Cell::Strn(s), .. } => {
Ok(Cell::Symb(syms.intern(s)?))
}
// lists
| Token { typ: Br1O, .. } => list(tki, syms, Br1C),
| Token { typ: Br3O, .. } => list(tki, syms, Br3C),
// abbreviations
| Token { typ: QQuo, .. } => abbrev(tki, syms, "quasiquote"),
| Token { typ: QSyn, .. } => abbrev(tki, syms, "quasisyntax"),
| Token { typ: Quot, .. } => abbrev(tki, syms, "quote"),
| Token { typ: Synt, .. } => abbrev(tki, syms, "syntax"),
| Token { typ: UnQS, .. } => abbrev(tki, syms, "unquote-splicing"),
| Token { typ: UnQu, .. } => abbrev(tki, syms, "unquote"),
| Token { typ: UnSS, .. } => abbrev(tki, syms, "unsyntax-splicing"),
| Token { typ: UnSy, .. } => abbrev(tki, syms, "unsyntax"),
| Token { typ, pos, .. } => Err(tki::Err::Unexpected(typ, pos).into()),
}
}
fn abbrev(
tki: &mut TokenIter, syms: &mut sym::SymbolTable, name: &'static str,
) -> Result<Cell, Err> {
let cdr = {
let cdr = Box::new(Cell::Null);
let car = Box::new(cell(tki, syms)?);
Box::new(Cell::Cons { cdr, car })
};
let car = Box::new(Cell::Symb(syms.intern(name)?));
Ok(Cell::Cons { cdr, car })
}
fn list(
tki: &mut TokenIter, syms: &mut sym::SymbolTable, end: tok::Type,
) -> Result<Cell, Err> {
let mut data_v = Vec::new();
let mut cdr = Cell::Null;
while !tki.drop(end)? {
if tki.drop(Peri)? {
cdr = cell(tki, syms)?;
tki.expect(end)?;
break;
} else {
data_v.push(cell(tki, syms)?);
}
}
for car in data_v.into_iter().rev() {
cdr = Cell::Cons { car: Box::new(car), cdr: Box::new(cdr) };
}
Ok(cdr)
}
// EOF

32
fw/vire/parser/tki.rs → fw/vire/tki.rs

@ -1,4 +1,4 @@
use super::tok::{self, Token, Type};
use super::tok::{Token, Type};
use crate::data::text::Position;
use std::{iter::Peekable, vec};
@ -13,19 +13,9 @@ pub enum Err {
}
#[derive(Debug)]
pub struct TokenIter {
it: Peekable<vec::IntoIter<Token>>,
}
pub struct TokenIter(pub(super) Peekable<vec::IntoIter<Token>>);
impl TokenIter {
pub fn new(v: Vec<Token>) -> Self {
Self { it: v.into_iter().peekable() }
}
pub fn from_data(name: &str, data: &str) -> Result<Self, tok::Err> {
Ok(Self::new(Token::read_all(name, data)?))
}
pub fn drop(&mut self, typ: Type) -> Result<bool, Err> {
let tk = self.err_peek()?;
if tk.typ == typ {
@ -53,19 +43,21 @@ impl TokenIter {
pub fn err_next(&mut self) -> Result<Token, Err> {
self.next().ok_or(Err::Eof)
}
pub fn peek(&mut self) -> Option<&Token> {
self.0.peek()
}
}
impl std::ops::Deref for TokenIter {
type Target = Peekable<vec::IntoIter<Token>>;
impl Iterator for TokenIter {
type Item = Token;
fn deref(&self) -> &Self::Target {
&self.it
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
impl std::ops::DerefMut for TokenIter {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.it
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}

6
fw/vire/parser/tok.rs → fw/vire/tok.rs

@ -1,4 +1,4 @@
use super::Cell;
use super::{Cell, TokenIter};
use crate::data::text::{self, PosReader, Position};
use std::{fmt, ops::ControlFlow};
@ -348,7 +348,7 @@ impl Token {
Ok(ControlFlow::Continue(Some(tk)))
}
pub fn read_all(name: &str, data: &str) -> Result<Vec<Self>, Err> {
pub fn read_all(name: &str, data: &str) -> Result<TokenIter, Err> {
let mut tokens = Vec::new();
let rd = &mut PosReader::new(data, text::ellipsize_small_str(name));
@ -358,7 +358,7 @@ impl Token {
}
}
Ok(tokens)
Ok(TokenIter(tokens.into_iter().peekable()))
}
}
Loading…
Cancel
Save