cleanup
This commit is contained in:
parent
6a4d7361f0
commit
86c02e86bb
5 changed files with 203 additions and 155 deletions
|
@ -1,9 +1,14 @@
|
||||||
use std::{collections::HashMap, iter::FromIterator};
|
use crate::{
|
||||||
|
error::*,
|
||||||
use super::*;
|
expr::{Expr, ExprIterator, ExprType, Span},
|
||||||
use crate::error::*;
|
parser, spanned,
|
||||||
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::collections::LinkedList;
|
use std::{
|
||||||
|
collections::{HashMap, LinkedList},
|
||||||
|
iter::FromIterator,
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
type VarName = String;
|
type VarName = String;
|
||||||
type AttrValue = String;
|
type AttrValue = String;
|
||||||
|
@ -24,15 +29,13 @@ pub enum DefType {
|
||||||
Widget,
|
Widget,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromExpr for DefType {
|
impl FromStr for DefType {
|
||||||
fn from_expr(e: Expr) -> AstResult<Self> {
|
type Err = ();
|
||||||
if let Expr::Symbol(span, sym) = e {
|
|
||||||
match sym.as_str() {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
"defwidget" => Ok(DefType::Widget),
|
match s {
|
||||||
_ => Err(AstError::InvalidDefinition(Some(span))),
|
"defwidget" => Ok(DefType::Widget),
|
||||||
}
|
_ => Err(()),
|
||||||
} else {
|
|
||||||
Err(AstError::WrongExprType(Some(e.span()), ExprType::Symbol, e))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,13 +54,13 @@ impl<C: FromExpr, A: FromExpr> FromExpr for Definitional<C, A> {
|
||||||
let span = e.span();
|
let span = e.span();
|
||||||
spanned!(e.span(), {
|
spanned!(e.span(), {
|
||||||
let list = e.as_list()?;
|
let list = e.as_list()?;
|
||||||
let mut iter = itertools::put_back(list.into_iter());
|
let mut iter = ExprIterator::new(list.into_iter());
|
||||||
|
let (span, def_type) = iter.next_symbol()?;
|
||||||
|
let def_type = def_type.parse().map_err(|_| AstError::InvalidDefinition(Some(span)))?;
|
||||||
|
|
||||||
let def_type = DefType::from_expr(iter.next().or_missing(ExprType::Symbol)?)?;
|
let (_, name) = iter.next_symbol()?;
|
||||||
let name = iter.next().or_missing(ExprType::Symbol)?.as_symbol()?;
|
let attrs = iter.key_values()?;
|
||||||
let attrs = parse_key_values(&mut iter)?;
|
|
||||||
let children = iter.map(|x| C::from_expr(x)).collect::<AstResult<Vec<_>>>()?;
|
let children = iter.map(|x| C::from_expr(x)).collect::<AstResult<Vec<_>>>()?;
|
||||||
|
|
||||||
Definitional { span, def_type, name, attrs, children }
|
Definitional { span, def_type, name, attrs, children }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -76,40 +79,15 @@ impl<C: FromExpr, A: FromExpr> FromExpr for Element<C, A> {
|
||||||
let span = e.span();
|
let span = e.span();
|
||||||
spanned!(e.span(), {
|
spanned!(e.span(), {
|
||||||
let list = e.as_list()?;
|
let list = e.as_list()?;
|
||||||
let mut iter = itertools::put_back(list.into_iter());
|
let mut iter = ExprIterator::new(list.into_iter());
|
||||||
|
let (_, name) = iter.next_symbol()?;
|
||||||
let name = iter.next().or_missing(ExprType::Str)?.as_symbol()?;
|
let attrs = iter.key_values()?;
|
||||||
let attrs = parse_key_values(&mut iter)?;
|
let children = iter.map(|x| C::from_expr(x)).collect::<AstResult<Vec<_>>>()?;
|
||||||
let children = iter.map(C::from_expr).collect::<AstResult<Vec<_>>>()?;
|
|
||||||
|
|
||||||
Element { span, name, attrs, children }
|
Element { span, name, attrs, children }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse consecutive `:keyword value` pairs from an expression iterator into a HashMap. Transforms the keys using the FromExpr trait.
|
|
||||||
fn parse_key_values<T: FromExpr, I: Iterator<Item = Expr>>(iter: &mut itertools::PutBack<I>) -> AstResult<HashMap<String, T>> {
|
|
||||||
let mut data = HashMap::new();
|
|
||||||
loop {
|
|
||||||
match iter.next() {
|
|
||||||
Some(Expr::Keyword(span, kw)) => match iter.next() {
|
|
||||||
Some(value) => {
|
|
||||||
data.insert(kw, T::from_expr(value)?);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
iter.put_back(Expr::Keyword(span, kw));
|
|
||||||
return Ok(data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Some(expr) => {
|
|
||||||
iter.put_back(expr);
|
|
||||||
return Ok(data);
|
|
||||||
}
|
|
||||||
None => return Ok(data),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{Expr, ExprType, Span};
|
use crate::expr::{Expr, ExprType, Span};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
pub type AstResult<T> = Result<T, AstError>;
|
pub type AstResult<T> = Result<T, AstError>;
|
||||||
|
@ -10,7 +10,7 @@ pub enum AstError {
|
||||||
#[error("Expected a {1}, but got nothing")]
|
#[error("Expected a {1}, but got nothing")]
|
||||||
MissingNode(Option<Span>, ExprType),
|
MissingNode(Option<Span>, ExprType),
|
||||||
#[error("Wrong type of expression: Expected {1} but got {2}")]
|
#[error("Wrong type of expression: Expected {1} but got {2}")]
|
||||||
WrongExprType(Option<Span>, ExprType, Expr),
|
WrongExprType(Option<Span>, ExprType, ExprType),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned(span: Span, err: impl Into<AstError>) -> AstError {
|
pub fn spanned(span: Span, err: impl Into<AstError>) -> AstError {
|
||||||
|
|
173
src/expr.rs
Normal file
173
src/expr.rs
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::{config::FromExpr, error::*};
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Copy)]
|
||||||
|
pub struct Span(pub usize, pub usize);
|
||||||
|
|
||||||
|
impl std::fmt::Display for Span {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}..{}", self.0, self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for Span {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub enum ExprType {
|
||||||
|
List,
|
||||||
|
Table,
|
||||||
|
Keyword,
|
||||||
|
Symbol,
|
||||||
|
Str,
|
||||||
|
Number,
|
||||||
|
Comment,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ExprType {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
|
pub enum Expr {
|
||||||
|
List(Span, Vec<Expr>),
|
||||||
|
Table(Span, Vec<(Expr, Expr)>),
|
||||||
|
Keyword(Span, String),
|
||||||
|
Symbol(Span, String),
|
||||||
|
Str(Span, String),
|
||||||
|
Number(Span, i32),
|
||||||
|
Comment(Span),
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! as_func {
|
||||||
|
($exprtype:expr, $name:ident < $t:ty > = $p:pat => $value:expr) => {
|
||||||
|
pub fn $name(self) -> Result<$t, AstError> {
|
||||||
|
match self {
|
||||||
|
$p => Ok($value),
|
||||||
|
x => Err(AstError::WrongExprType(Some(x.span()), $exprtype, x.expr_type())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Expr {
|
||||||
|
as_func!(ExprType::Str, as_str<String> = Expr::Str(_, x) => x);
|
||||||
|
|
||||||
|
as_func!(ExprType::Symbol, as_symbol<String> = Expr::Symbol(_, x) => x);
|
||||||
|
|
||||||
|
as_func!(ExprType::List, as_list<Vec<Expr>> = Expr::List(_, x) => x);
|
||||||
|
|
||||||
|
pub fn expr_type(&self) -> ExprType {
|
||||||
|
match self {
|
||||||
|
Expr::List(..) => ExprType::List,
|
||||||
|
Expr::Table(..) => ExprType::Table,
|
||||||
|
Expr::Keyword(..) => ExprType::Keyword,
|
||||||
|
Expr::Symbol(..) => ExprType::Symbol,
|
||||||
|
Expr::Str(..) => ExprType::Str,
|
||||||
|
Expr::Number(..) => ExprType::Number,
|
||||||
|
Expr::Comment(_) => ExprType::Number,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn span(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
Expr::List(span, _) => *span,
|
||||||
|
Expr::Table(span, _) => *span,
|
||||||
|
Expr::Keyword(span, _) => *span,
|
||||||
|
Expr::Symbol(span, _) => *span,
|
||||||
|
Expr::Str(span, _) => *span,
|
||||||
|
Expr::Number(span, _) => *span,
|
||||||
|
Expr::Comment(span) => *span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Expr {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
use Expr::*;
|
||||||
|
match self {
|
||||||
|
Number(_, x) => write!(f, "{}", x),
|
||||||
|
List(_, x) => write!(f, "({})", x.iter().map(|e| format!("{}", e)).join(" ")),
|
||||||
|
Table(_, x) => write!(f, "{{{}}}", x.iter().map(|(k, v)| format!("{} {}", k, v)).join(" ")),
|
||||||
|
Keyword(_, x) => write!(f, "{}", x),
|
||||||
|
Symbol(_, x) => write!(f, "{}", x),
|
||||||
|
Str(_, x) => write!(f, "{}", x),
|
||||||
|
Comment(_) => write!(f, ""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ExprIterator<I: Iterator<Item = Expr>> {
|
||||||
|
iter: itertools::PutBack<I>,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! return_or_put_back {
|
||||||
|
($name:ident, $expr_type:expr, $t:ty = $p:pat => $ret:expr) => {
|
||||||
|
pub fn $name(&mut self) -> AstResult<$t> {
|
||||||
|
let expr_type = $expr_type;
|
||||||
|
match self.next() {
|
||||||
|
Some($p) => Ok($ret),
|
||||||
|
Some(other) => {
|
||||||
|
let span = other.span();
|
||||||
|
let actual_type = other.expr_type();
|
||||||
|
self.iter.put_back(other);
|
||||||
|
Err(AstError::WrongExprType(Some(span), expr_type, actual_type))
|
||||||
|
}
|
||||||
|
None => Err(AstError::MissingNode(None, expr_type)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Iterator<Item = Expr>> ExprIterator<I> {
|
||||||
|
return_or_put_back!(next_symbol, ExprType::Symbol, (Span, String) = Expr::Symbol(span, x) => (span, x));
|
||||||
|
|
||||||
|
return_or_put_back!(next_string, ExprType::Str, (Span, String) = Expr::Str(span, x) => (span, x));
|
||||||
|
|
||||||
|
pub fn new(iter: I) -> Self {
|
||||||
|
ExprIterator { iter: itertools::put_back(iter) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn key_values<T: FromExpr>(&mut self) -> AstResult<HashMap<String, T>> {
|
||||||
|
parse_key_values(&mut self.iter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Iterator<Item = Expr>> Iterator for ExprIterator<I> {
|
||||||
|
type Item = Expr;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.iter.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse consecutive `:keyword value` pairs from an expression iterator into a HashMap. Transforms the keys using the FromExpr trait.
|
||||||
|
fn parse_key_values<T: FromExpr, I: Iterator<Item = Expr>>(iter: &mut itertools::PutBack<I>) -> AstResult<HashMap<String, T>> {
|
||||||
|
let mut data = HashMap::new();
|
||||||
|
loop {
|
||||||
|
match iter.next() {
|
||||||
|
Some(Expr::Keyword(span, kw)) => match iter.next() {
|
||||||
|
Some(value) => {
|
||||||
|
data.insert(kw, T::from_expr(value)?);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
iter.put_back(Expr::Keyword(span, kw));
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(expr) => {
|
||||||
|
iter.put_back(expr);
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
None => return Ok(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
104
src/main.rs
104
src/main.rs
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod expr;
|
||||||
use error::AstError;
|
use error::AstError;
|
||||||
|
|
||||||
use std::{fmt::Display, ops::Deref};
|
use std::{fmt::Display, ops::Deref};
|
||||||
|
@ -16,109 +17,6 @@ use lalrpop_util::lalrpop_mod;
|
||||||
|
|
||||||
lalrpop_mod!(pub parser);
|
lalrpop_mod!(pub parser);
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Copy)]
|
|
||||||
pub struct Span(pub usize, pub usize);
|
|
||||||
|
|
||||||
impl std::fmt::Display for Span {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{}..{}", self.0, self.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for Span {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{}", self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
|
||||||
pub enum ExprType {
|
|
||||||
List,
|
|
||||||
Table,
|
|
||||||
Keyword,
|
|
||||||
Symbol,
|
|
||||||
Str,
|
|
||||||
Number,
|
|
||||||
Comment,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for ExprType {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{:?}", self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
||||||
pub enum Expr {
|
|
||||||
List(Span, Vec<Expr>),
|
|
||||||
Table(Span, Vec<(Expr, Expr)>),
|
|
||||||
Keyword(Span, String),
|
|
||||||
Symbol(Span, String),
|
|
||||||
Str(Span, String),
|
|
||||||
Number(Span, i32),
|
|
||||||
Comment(Span),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Expr> for ExprType {
|
|
||||||
fn from(x: Expr) -> Self {
|
|
||||||
match x {
|
|
||||||
Expr::List(..) => ExprType::List,
|
|
||||||
Expr::Table(..) => ExprType::Table,
|
|
||||||
Expr::Keyword(..) => ExprType::Keyword,
|
|
||||||
Expr::Symbol(..) => ExprType::Symbol,
|
|
||||||
Expr::Str(..) => ExprType::Str,
|
|
||||||
Expr::Number(..) => ExprType::Number,
|
|
||||||
Expr::Comment(_) => ExprType::Number,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! as_func {
|
|
||||||
($exprtype:expr, $name:ident < $t:ty > = $p:pat => $value:expr) => {
|
|
||||||
fn $name(self) -> Result<$t, AstError> {
|
|
||||||
match self {
|
|
||||||
$p => Ok($value),
|
|
||||||
x => Err(AstError::WrongExprType(Some(x.span()), $exprtype, x)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Expr {
|
|
||||||
as_func!(ExprType::Str, as_str<String> = Expr::Str(_, x) => x);
|
|
||||||
|
|
||||||
as_func!(ExprType::Symbol, as_symbol<String> = Expr::Symbol(_, x) => x);
|
|
||||||
|
|
||||||
as_func!(ExprType::List, as_list<Vec<Expr>> = Expr::List(_, x) => x);
|
|
||||||
|
|
||||||
pub fn span(&self) -> Span {
|
|
||||||
match self {
|
|
||||||
Expr::List(span, _) => *span,
|
|
||||||
Expr::Table(span, _) => *span,
|
|
||||||
Expr::Keyword(span, _) => *span,
|
|
||||||
Expr::Symbol(span, _) => *span,
|
|
||||||
Expr::Str(span, _) => *span,
|
|
||||||
Expr::Number(span, _) => *span,
|
|
||||||
Expr::Comment(span) => *span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for Expr {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
use Expr::*;
|
|
||||||
match self {
|
|
||||||
Number(_, x) => write!(f, "{}", x),
|
|
||||||
List(_, x) => write!(f, "({})", x.iter().map(|e| format!("{}", e)).join(" ")),
|
|
||||||
Table(_, x) => write!(f, "{{{}}}", x.iter().map(|(k, v)| format!("{} {}", k, v)).join(" ")),
|
|
||||||
Keyword(_, x) => write!(f, "{}", x),
|
|
||||||
Symbol(_, x) => write!(f, "{}", x),
|
|
||||||
Str(_, x) => write!(f, "{}", x),
|
|
||||||
Comment(_) => write!(f, ""),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
//use crate::lexer;
|
//use crate::lexer;
|
||||||
use crate::Expr;
|
use crate::expr::{Expr, Span};
|
||||||
use crate::Span;
|
|
||||||
|
|
||||||
grammar;
|
grammar;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue