factor out astIterator
This commit is contained in:
parent
3892562be9
commit
efa00a408b
13 changed files with 125 additions and 98 deletions
|
@ -6,7 +6,8 @@ use crate::{
|
||||||
enum_parse,
|
enum_parse,
|
||||||
error::AstResult,
|
error::AstResult,
|
||||||
parser::{
|
parser::{
|
||||||
ast::{Ast, AstIterator, Span},
|
ast::{Ast, Span},
|
||||||
|
ast_iterator::AstIterator,
|
||||||
from_ast::FromAstElementContent,
|
from_ast::FromAstElementContent,
|
||||||
},
|
},
|
||||||
value::NumWithUnit,
|
value::NumWithUnit,
|
||||||
|
|
|
@ -10,7 +10,8 @@ use crate::{
|
||||||
config::script_var_definition::{PollScriptVar, TailScriptVar},
|
config::script_var_definition::{PollScriptVar, TailScriptVar},
|
||||||
error::{AstError, AstResult, OptionAstErrorExt},
|
error::{AstError, AstResult, OptionAstErrorExt},
|
||||||
parser::{
|
parser::{
|
||||||
ast::{Ast, AstIterator, Span},
|
ast::{Ast, Span},
|
||||||
|
ast_iterator::AstIterator,
|
||||||
from_ast::{FromAst, FromAstElementContent},
|
from_ast::{FromAst, FromAstElementContent},
|
||||||
},
|
},
|
||||||
spanned,
|
spanned,
|
||||||
|
|
|
@ -5,7 +5,8 @@ use simplexpr::{dynval::DynVal, SimplExpr};
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{AstError, AstResult},
|
error::{AstError, AstResult},
|
||||||
parser::{
|
parser::{
|
||||||
ast::{Ast, AstIterator, Span},
|
ast::{Ast, Span},
|
||||||
|
ast_iterator::AstIterator,
|
||||||
from_ast::{FromAst, FromAstElementContent},
|
from_ast::{FromAst, FromAstElementContent},
|
||||||
},
|
},
|
||||||
spanned,
|
spanned,
|
||||||
|
|
|
@ -5,7 +5,8 @@ use simplexpr::SimplExpr;
|
||||||
use crate::{
|
use crate::{
|
||||||
error::AstResult,
|
error::AstResult,
|
||||||
parser::{
|
parser::{
|
||||||
ast::{Ast, AstIterator, Span},
|
ast::{Ast, Span},
|
||||||
|
ast_iterator::AstIterator,
|
||||||
from_ast::FromAst,
|
from_ast::FromAst,
|
||||||
},
|
},
|
||||||
spanned,
|
spanned,
|
||||||
|
|
|
@ -5,7 +5,8 @@ use simplexpr::{dynval::DynVal, SimplExpr};
|
||||||
use crate::{
|
use crate::{
|
||||||
error::AstResult,
|
error::AstResult,
|
||||||
parser::{
|
parser::{
|
||||||
ast::{Ast, AstIterator, Span},
|
ast::{Ast, Span},
|
||||||
|
ast_iterator::AstIterator,
|
||||||
from_ast::{FromAst, FromAstElementContent},
|
from_ast::{FromAst, FromAstElementContent},
|
||||||
},
|
},
|
||||||
spanned,
|
spanned,
|
||||||
|
|
|
@ -5,7 +5,8 @@ use simplexpr::SimplExpr;
|
||||||
use crate::{
|
use crate::{
|
||||||
error::AstResult,
|
error::AstResult,
|
||||||
parser::{
|
parser::{
|
||||||
ast::{Ast, AstIterator, Span},
|
ast::{Ast, Span},
|
||||||
|
ast_iterator::AstIterator,
|
||||||
from_ast::{FromAst, FromAstElementContent},
|
from_ast::{FromAst, FromAstElementContent},
|
||||||
},
|
},
|
||||||
spanned,
|
spanned,
|
||||||
|
|
|
@ -6,7 +6,8 @@ use crate::{
|
||||||
config::attributes::AttrEntry,
|
config::attributes::AttrEntry,
|
||||||
error::AstResult,
|
error::AstResult,
|
||||||
parser::{
|
parser::{
|
||||||
ast::{Ast, AstIterator, Span},
|
ast::{Ast, Span},
|
||||||
|
ast_iterator::AstIterator,
|
||||||
from_ast::FromAst,
|
from_ast::FromAst,
|
||||||
},
|
},
|
||||||
spanned,
|
spanned,
|
||||||
|
|
|
@ -5,7 +5,8 @@ use simplexpr::{dynval::DynVal, SimplExpr};
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{AstError, AstResult},
|
error::{AstError, AstResult},
|
||||||
parser::{
|
parser::{
|
||||||
ast::{Ast, AstIterator, Span},
|
ast::{Ast, Span},
|
||||||
|
ast_iterator::AstIterator,
|
||||||
from_ast::{FromAst, FromAstElementContent},
|
from_ast::{FromAst, FromAstElementContent},
|
||||||
},
|
},
|
||||||
spanned,
|
spanned,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||||
use simplexpr::{dynval::DynVal, SimplExpr};
|
use simplexpr::{dynval::DynVal, SimplExpr};
|
||||||
|
|
||||||
use crate::{enum_parse, error::{AstError, AstResult}, parser::{
|
use crate::{enum_parse, error::{AstError, AstResult}, parser::{
|
||||||
ast::{Ast, AstIterator, Span},
|
ast::{Ast, Span}, ast_iterator::AstIterator,
|
||||||
from_ast::{FromAst, FromAstElementContent},
|
from_ast::{FromAst, FromAstElementContent},
|
||||||
}, spanned, value::{AttrName, Coords, VarName}};
|
}, spanned, value::{AttrName, Coords, VarName}};
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use super::from_ast::FromAst;
|
use super::{ast_iterator::AstIterator, from_ast::FromAst};
|
||||||
use crate::{
|
use crate::{
|
||||||
config::attributes::{AttrEntry, Attributes},
|
config::attributes::{AttrEntry, Attributes},
|
||||||
error::{AstError, AstResult, OptionAstErrorExt},
|
error::{AstError, AstResult, OptionAstErrorExt},
|
||||||
|
@ -66,7 +66,7 @@ pub enum AstType {
|
||||||
Literal,
|
Literal,
|
||||||
SimplExpr,
|
SimplExpr,
|
||||||
Comment,
|
Comment,
|
||||||
// A value that could be used as a [SimplExpr]
|
/// A value that could be used as a [SimplExpr]
|
||||||
IntoPrimitive,
|
IntoPrimitive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,89 +185,3 @@ impl std::fmt::Debug for Ast {
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AstIterator<I: Iterator<Item = Ast>> {
|
|
||||||
remaining_span: Span,
|
|
||||||
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) => {
|
|
||||||
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<I: Iterator<Item = Ast>> AstIterator<I> {
|
|
||||||
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>) = Ast::List(span, x) => (span, x));
|
|
||||||
|
|
||||||
return_or_put_back!(expect_array, AstType::Array, (Span, Vec<Ast>) = 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<T: FromAst>(&mut self) -> AstResult<T> {
|
|
||||||
self.iter.next().or_missing().and_then(T::from_ast)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expect_key_values(&mut self) -> AstResult<Attributes> {
|
|
||||||
parse_key_values(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I: Iterator<Item = Ast>> Iterator for AstIterator<I> {
|
|
||||||
type Item = Ast;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
self.iter.next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse consecutive `:keyword value` pairs from an expression iterator into an [Attributes].
|
|
||||||
fn parse_key_values(iter: &mut AstIterator<impl Iterator<Item = Ast>>) -> AstResult<Attributes> {
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
101
src/parser/ast_iterator.rs
Normal file
101
src/parser/ast_iterator.rs
Normal file
|
@ -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<I: Iterator<Item = Ast>> {
|
||||||
|
remaining_span: Span,
|
||||||
|
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) => {
|
||||||
|
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<I: Iterator<Item = Ast>> AstIterator<I> {
|
||||||
|
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>) = Ast::List(span, x) => (span, x));
|
||||||
|
|
||||||
|
return_or_put_back!(expect_array, AstType::Array, (Span, Vec<Ast>) = 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<T: FromAst>(&mut self) -> AstResult<T> {
|
||||||
|
self.iter.next().or_missing().and_then(T::from_ast)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_key_values(&mut self) -> AstResult<Attributes> {
|
||||||
|
parse_key_values(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Iterator<Item = Ast>> Iterator for AstIterator<I> {
|
||||||
|
type Item = Ast;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.iter.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse consecutive `:keyword value` pairs from an expression iterator into an [Attributes].
|
||||||
|
fn parse_key_values(iter: &mut AstIterator<impl Iterator<Item = Ast>>) -> AstResult<Attributes> {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 crate::{error::*, parser, spanned, util, value::AttrName};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use simplexpr::{ast::SimplExpr, dynval::DynVal};
|
use simplexpr::{ast::SimplExpr, dynval::DynVal};
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::{fmt::Display, ops::Deref};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
|
pub mod ast_iterator;
|
||||||
pub mod from_ast;
|
pub mod from_ast;
|
||||||
pub(crate) mod lexer;
|
pub(crate) mod lexer;
|
||||||
pub(crate) mod parse_error;
|
pub(crate) mod parse_error;
|
||||||
|
|
Loading…
Add table
Reference in a new issue