From efa00a408b5840b5b6cf83b68ae75ab0b82e4307 Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Wed, 21 Jul 2021 15:23:21 +0200 Subject: [PATCH] factor out astIterator --- src/config/backend_window_options.rs | 3 +- src/config/config.rs | 3 +- src/config/script_var_definition.rs | 3 +- src/config/validate.rs | 3 +- src/config/var_definition.rs | 3 +- src/config/widget_definition.rs | 3 +- src/config/widget_use.rs | 3 +- src/config/window_definition.rs | 3 +- src/config/window_geometry.rs | 2 +- src/parser/ast.rs | 90 +----------------------- src/parser/ast_iterator.rs | 101 +++++++++++++++++++++++++++ src/parser/from_ast.rs | 5 +- src/parser/mod.rs | 1 + 13 files changed, 125 insertions(+), 98 deletions(-) create mode 100644 src/parser/ast_iterator.rs diff --git a/src/config/backend_window_options.rs b/src/config/backend_window_options.rs index 99918cd..0cc0a9e 100644 --- a/src/config/backend_window_options.rs +++ b/src/config/backend_window_options.rs @@ -6,7 +6,8 @@ use crate::{ enum_parse, error::AstResult, parser::{ - ast::{Ast, AstIterator, Span}, + ast::{Ast, Span}, + ast_iterator::AstIterator, from_ast::FromAstElementContent, }, value::NumWithUnit, diff --git a/src/config/config.rs b/src/config/config.rs index 8cd5f7c..556c850 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -10,7 +10,8 @@ use crate::{ config::script_var_definition::{PollScriptVar, TailScriptVar}, error::{AstError, AstResult, OptionAstErrorExt}, parser::{ - ast::{Ast, AstIterator, Span}, + ast::{Ast, Span}, + ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, spanned, diff --git a/src/config/script_var_definition.rs b/src/config/script_var_definition.rs index 147c5c0..4089cda 100644 --- a/src/config/script_var_definition.rs +++ b/src/config/script_var_definition.rs @@ -5,7 +5,8 @@ use simplexpr::{dynval::DynVal, SimplExpr}; use crate::{ error::{AstError, AstResult}, parser::{ - ast::{Ast, AstIterator, Span}, + ast::{Ast, Span}, + ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, spanned, diff --git a/src/config/validate.rs b/src/config/validate.rs index 99b049b..e4ca804 100644 --- a/src/config/validate.rs +++ b/src/config/validate.rs @@ -5,7 +5,8 @@ use simplexpr::SimplExpr; use crate::{ error::AstResult, parser::{ - ast::{Ast, AstIterator, Span}, + ast::{Ast, Span}, + ast_iterator::AstIterator, from_ast::FromAst, }, spanned, diff --git a/src/config/var_definition.rs b/src/config/var_definition.rs index 37948cd..29d5364 100644 --- a/src/config/var_definition.rs +++ b/src/config/var_definition.rs @@ -5,7 +5,8 @@ use simplexpr::{dynval::DynVal, SimplExpr}; use crate::{ error::AstResult, parser::{ - ast::{Ast, AstIterator, Span}, + ast::{Ast, Span}, + ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, spanned, diff --git a/src/config/widget_definition.rs b/src/config/widget_definition.rs index 518286d..7418a71 100644 --- a/src/config/widget_definition.rs +++ b/src/config/widget_definition.rs @@ -5,7 +5,8 @@ use simplexpr::SimplExpr; use crate::{ error::AstResult, parser::{ - ast::{Ast, AstIterator, Span}, + ast::{Ast, Span}, + ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, spanned, diff --git a/src/config/widget_use.rs b/src/config/widget_use.rs index 4bdd06a..6ce0332 100644 --- a/src/config/widget_use.rs +++ b/src/config/widget_use.rs @@ -6,7 +6,8 @@ use crate::{ config::attributes::AttrEntry, error::AstResult, parser::{ - ast::{Ast, AstIterator, Span}, + ast::{Ast, Span}, + ast_iterator::AstIterator, from_ast::FromAst, }, spanned, diff --git a/src/config/window_definition.rs b/src/config/window_definition.rs index bc792b8..1ae9c99 100644 --- a/src/config/window_definition.rs +++ b/src/config/window_definition.rs @@ -5,7 +5,8 @@ use simplexpr::{dynval::DynVal, SimplExpr}; use crate::{ error::{AstError, AstResult}, parser::{ - ast::{Ast, AstIterator, Span}, + ast::{Ast, Span}, + ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, spanned, diff --git a/src/config/window_geometry.rs b/src/config/window_geometry.rs index 599984e..db9f93d 100644 --- a/src/config/window_geometry.rs +++ b/src/config/window_geometry.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use simplexpr::{dynval::DynVal, SimplExpr}; use crate::{enum_parse, error::{AstError, AstResult}, parser::{ - ast::{Ast, AstIterator, Span}, + ast::{Ast, Span}, ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, spanned, value::{AttrName, Coords, VarName}}; diff --git a/src/parser/ast.rs b/src/parser/ast.rs index a9f0903..eb0b45a 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use std::fmt::Display; -use super::from_ast::FromAst; +use super::{ast_iterator::AstIterator, from_ast::FromAst}; use crate::{ config::attributes::{AttrEntry, Attributes}, error::{AstError, AstResult, OptionAstErrorExt}, @@ -66,7 +66,7 @@ pub enum AstType { Literal, SimplExpr, Comment, - // A value that could be used as a [SimplExpr] + /// A value that could be used as a [SimplExpr] IntoPrimitive, } @@ -185,89 +185,3 @@ impl std::fmt::Debug for Ast { //} } } - -pub struct AstIterator> { - remaining_span: Span, - iter: itertools::PutBack, -} - -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) => { - let (span, value) = $ret; - self.remaining_span.1 = span.1; - Ok((span, value)) - } - 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)), - } - } - }; -} - -impl> AstIterator { - return_or_put_back!(expect_symbol, AstType::Symbol, (Span, String) = Ast::Symbol(span, x) => (span, x)); - - return_or_put_back!(expect_literal, AstType::Literal, (Span, DynVal) = Ast::Literal(span, x) => (span, x)); - - return_or_put_back!(expect_list, AstType::List, (Span, Vec) = Ast::List(span, x) => (span, x)); - - return_or_put_back!(expect_array, AstType::Array, (Span, Vec) = Ast::Array(span, x) => (span, x)); - - pub fn new(span: Span, iter: I) -> Self { - AstIterator { remaining_span: span, iter: itertools::put_back(iter) } - } - - pub fn expect_any(&mut self) -> AstResult { - self.iter.next().or_missing().and_then(T::from_ast) - } - - pub fn expect_key_values(&mut self) -> AstResult { - parse_key_values(self) - } -} - -impl> Iterator for AstIterator { - type Item = Ast; - - fn next(&mut self) -> Option { - self.iter.next() - } -} - -/// Parse consecutive `:keyword value` pairs from an expression iterator into an [Attributes]. -fn parse_key_values(iter: &mut AstIterator>) -> AstResult { - let mut data = HashMap::new(); - let mut attrs_span = Span(iter.remaining_span.0, iter.remaining_span.0, iter.remaining_span.1); - loop { - match iter.next() { - Some(Ast::Keyword(key_span, kw)) => match iter.next() { - Some(value) => { - attrs_span.1 = iter.remaining_span.0; - let attr_value = AttrEntry { key_span, value }; - data.insert(AttrName(kw), attr_value); - } - None => { - iter.iter.put_back(Ast::Keyword(key_span, kw)); - attrs_span.1 = iter.remaining_span.0; - return Ok(Attributes::new(attrs_span, data)); - } - }, - next => { - if let Some(expr) = next { - iter.iter.put_back(expr); - } - attrs_span.1 = iter.remaining_span.0; - return Ok(Attributes::new(attrs_span, data)); - } - } - } -} diff --git a/src/parser/ast_iterator.rs b/src/parser/ast_iterator.rs new file mode 100644 index 0000000..097e330 --- /dev/null +++ b/src/parser/ast_iterator.rs @@ -0,0 +1,101 @@ +use itertools::Itertools; +use simplexpr::{ast::SimplExpr, dynval::DynVal}; +use std::collections::HashMap; + +use std::fmt::Display; + +use super::{ + ast::{Ast, AstType, Span}, + from_ast::FromAst, +}; +use crate::{ + config::attributes::{AttrEntry, Attributes}, + error::{AstError, AstResult, OptionAstErrorExt}, + value::AttrName, +}; + +pub struct AstIterator> { + remaining_span: Span, + iter: itertools::PutBack, +} + +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) => { + let (span, value) = $ret; + self.remaining_span.1 = span.1; + Ok((span, value)) + } + 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)), + } + } + }; +} + +impl> AstIterator { + return_or_put_back!(expect_symbol, AstType::Symbol, (Span, String) = Ast::Symbol(span, x) => (span, x)); + + return_or_put_back!(expect_literal, AstType::Literal, (Span, DynVal) = Ast::Literal(span, x) => (span, x)); + + return_or_put_back!(expect_list, AstType::List, (Span, Vec) = Ast::List(span, x) => (span, x)); + + return_or_put_back!(expect_array, AstType::Array, (Span, Vec) = Ast::Array(span, x) => (span, x)); + + pub fn new(span: Span, iter: I) -> Self { + AstIterator { remaining_span: span, iter: itertools::put_back(iter) } + } + + pub fn expect_any(&mut self) -> AstResult { + self.iter.next().or_missing().and_then(T::from_ast) + } + + pub fn expect_key_values(&mut self) -> AstResult { + parse_key_values(self) + } +} + +impl> Iterator for AstIterator { + type Item = Ast; + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +/// Parse consecutive `:keyword value` pairs from an expression iterator into an [Attributes]. +fn parse_key_values(iter: &mut AstIterator>) -> AstResult { + let mut data = HashMap::new(); + let mut attrs_span = Span(iter.remaining_span.0, iter.remaining_span.0, iter.remaining_span.1); + loop { + match iter.next() { + Some(Ast::Keyword(key_span, kw)) => match iter.next() { + Some(value) => { + attrs_span.1 = iter.remaining_span.0; + let attr_value = AttrEntry { key_span, value }; + data.insert(AttrName(kw), attr_value); + } + None => { + iter.iter.put_back(Ast::Keyword(key_span, kw)); + attrs_span.1 = iter.remaining_span.0; + return Ok(Attributes::new(attrs_span, data)); + } + }, + next => { + if let Some(expr) = next { + iter.iter.put_back(expr); + } + attrs_span.1 = iter.remaining_span.0; + return Ok(Attributes::new(attrs_span, data)); + } + } + } +} diff --git a/src/parser/from_ast.rs b/src/parser/from_ast.rs index 21ab4bd..ed495d8 100644 --- a/src/parser/from_ast.rs +++ b/src/parser/from_ast.rs @@ -1,4 +1,7 @@ -use super::ast::{Ast, AstIterator, AstType, Span}; +use super::{ + ast::{Ast, AstType, Span}, + ast_iterator::AstIterator, +}; use crate::{error::*, parser, spanned, util, value::AttrName}; use itertools::Itertools; use simplexpr::{ast::SimplExpr, dynval::DynVal}; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d0a99d2..c4654b2 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -8,6 +8,7 @@ use std::{fmt::Display, ops::Deref}; use itertools::Itertools; pub mod ast; +pub mod ast_iterator; pub mod from_ast; pub(crate) mod lexer; pub(crate) mod parse_error;