Make `ASTNode` sensitive to COW style parsing

next
Sayan Nandan 2 years ago
parent e4836fd7b3
commit 25ef03221b
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -523,9 +523,9 @@ pub enum Statement<'a> {
/// DDL query to switch between spaces and models /// DDL query to switch between spaces and models
Use(Entity<'a>), Use(Entity<'a>),
/// DDL query to create a model /// DDL query to create a model
CreateModel(ddl::crt::Model<'a>), CreateModel(ddl::crt::CreateModel<'a>),
/// DDL query to create a space /// DDL query to create a space
CreateSpace(ddl::crt::Space<'a>), CreateSpace(ddl::crt::CreateSpace<'a>),
/// DDL query to alter a space (properties) /// DDL query to alter a space (properties)
AlterSpace(ddl::alt::AlterSpace<'a>), AlterSpace(ddl::alt::AlterSpace<'a>),
/// DDL query to alter a model (properties, field types, etc) /// DDL query to alter a model (properties, field types, etc)

@ -28,12 +28,49 @@
use crate::engine::ql::{ast::InplaceData, lex::Token}; use crate::engine::ql::{ast::InplaceData, lex::Token};
use crate::engine::ql::{ use crate::engine::ql::{
ast::{QueryData, State}, ast::{QueryData, State},
LangResult, LangError, LangResult,
}; };
/// An AST node
pub trait ASTNode<'a>: Sized { pub trait ASTNode<'a>: Sized {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self>; const VERIFY: bool = false;
/// Parse this AST node from the given state
///
/// Note to implementors:
/// - If the implementor uses a cow style parse, then set [`ASTNode::VERIFY`] to
/// true
/// - Try to propagate errors via [`State`] if possible
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self>;
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let r = <Self as ASTNode>::_from_state(state);
if Self::VERIFY {
return if state.okay() {
r
} else {
Err(LangError::UnexpectedToken)
};
}
r
}
#[cfg(test)] #[cfg(test)]
/// Parse multiple nodes of this AST node type. Intended for the test suite.
fn _multiple_from_state<Qd: QueryData<'a>>(_: &mut State<'a, Qd>) -> LangResult<Vec<Self>> {
unimplemented!()
}
#[cfg(test)]
fn multiple_from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Vec<Self>> {
let r = <Self as ASTNode>::_multiple_from_state(state);
if Self::VERIFY {
return if state.okay() {
r
} else {
Err(LangError::UnexpectedToken)
};
}
r
}
#[cfg(test)]
/// Parse this AST node utilizing the full token-stream. Intended for the test suite.
fn from_insecure_tokens_full(tok: &'a [Token<'a>]) -> LangResult<Self> { fn from_insecure_tokens_full(tok: &'a [Token<'a>]) -> LangResult<Self> {
let mut state = State::new(tok, InplaceData::new()); let mut state = State::new(tok, InplaceData::new());
let r = <Self as ASTNode>::from_state(&mut state)?; let r = <Self as ASTNode>::from_state(&mut state)?;
@ -41,10 +78,8 @@ pub trait ASTNode<'a>: Sized {
Ok(r) Ok(r)
} }
#[cfg(test)] #[cfg(test)]
fn multiple_from_state<Qd: QueryData<'a>>(_: &mut State<'a, Qd>) -> LangResult<Vec<Self>> { /// Parse multiple nodes of this AST node type, utilizing the full token stream.
unimplemented!() /// Intended for the test suite.
}
#[cfg(test)]
fn multiple_from_insecure_tokens_full(tok: &'a [Token<'a>]) -> LangResult<Vec<Self>> { fn multiple_from_insecure_tokens_full(tok: &'a [Token<'a>]) -> LangResult<Vec<Self>> {
let mut state = State::new(tok, InplaceData::new()); let mut state = State::new(tok, InplaceData::new());
let r = Self::multiple_from_state(&mut state); let r = Self::multiple_from_state(&mut state);

@ -183,12 +183,12 @@ mod impls {
LangResult, LangResult,
}; };
impl<'a> ASTNode<'a> for AlterModel<'a> { impl<'a> ASTNode<'a> for AlterModel<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse(state) Self::parse(state)
} }
} }
impl<'a> ASTNode<'a> for AlterSpace<'a> { impl<'a> ASTNode<'a> for AlterSpace<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse(state) Self::parse(state)
} }
} }

@ -36,14 +36,14 @@ use crate::{
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
/// A space /// A space
pub struct Space<'a> { pub struct CreateSpace<'a> {
/// the space name /// the space name
pub(super) space_name: Slice<'a>, pub(super) space_name: Slice<'a>,
/// properties /// properties
pub(super) props: Dict, pub(super) props: Dict,
} }
impl<'a> Space<'a> { impl<'a> CreateSpace<'a> {
#[inline(always)] #[inline(always)]
/// Parse space data from the given tokens /// Parse space data from the given tokens
fn parse<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn parse<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
@ -63,7 +63,7 @@ impl<'a> Space<'a> {
syn::rfold_dict(DictFoldState::OB, state, &mut d); syn::rfold_dict(DictFoldState::OB, state, &mut d);
} }
if state.okay() { if state.okay() {
Ok(Space { Ok(CreateSpace {
space_name: unsafe { extract!(space_name, Token::Ident(ref id) => id.clone()) }, space_name: unsafe { extract!(space_name, Token::Ident(ref id) => id.clone()) },
props: d, props: d,
}) })
@ -75,7 +75,7 @@ impl<'a> Space<'a> {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
/// A model definition /// A model definition
pub struct Model<'a> { pub struct CreateModel<'a> {
/// the model name /// the model name
model_name: Slice<'a>, model_name: Slice<'a>,
/// the fields /// the fields
@ -91,7 +91,7 @@ pub struct Model<'a> {
) )
*/ */
impl<'a> Model<'a> { impl<'a> CreateModel<'a> {
pub fn new(model_name: Slice<'a>, fields: Vec<Field<'a>>, props: Dict) -> Self { pub fn new(model_name: Slice<'a>, fields: Vec<Field<'a>>, props: Dict) -> Self {
Self { Self {
model_name, model_name,
@ -142,18 +142,18 @@ impl<'a> Model<'a> {
} }
mod impls { mod impls {
use super::{Model, Space}; use super::{CreateModel, CreateSpace};
use crate::engine::ql::{ use crate::engine::ql::{
ast::{traits::ASTNode, QueryData, State}, ast::{traits::ASTNode, QueryData, State},
LangResult, LangResult,
}; };
impl<'a> ASTNode<'a> for Space<'a> { impl<'a> ASTNode<'a> for CreateSpace<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse(state) Self::parse(state)
} }
} }
impl<'a> ASTNode<'a> for Model<'a> { impl<'a> ASTNode<'a> for CreateModel<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse(state) Self::parse(state)
} }
} }

@ -107,19 +107,19 @@ mod impls {
LangResult, LangResult,
}; };
impl<'a> ASTNode<'a> for DropModel<'a> { impl<'a> ASTNode<'a> for DropModel<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse(state) Self::parse(state)
} }
} }
impl<'a> ASTNode<'a> for DropSpace<'a> { impl<'a> ASTNode<'a> for DropSpace<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse(state) Self::parse(state)
} }
} }
#[derive(sky_macros::Wrapper, Debug)] #[derive(sky_macros::Wrapper, Debug)]
pub struct DropStatementAST<'a>(Statement<'a>); pub struct DropStatementAST<'a>(Statement<'a>);
impl<'a> ASTNode<'a> for DropStatementAST<'a> { impl<'a> ASTNode<'a> for DropStatementAST<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
super::parse_drop(state).map(Self) super::parse_drop(state).map(Self)
} }
} }

@ -72,7 +72,7 @@ mod impls {
#[derive(sky_macros::Wrapper, Debug)] #[derive(sky_macros::Wrapper, Debug)]
pub struct InspectStatementAST<'a>(Statement<'a>); pub struct InspectStatementAST<'a>(Statement<'a>);
impl<'a> ASTNode<'a> for InspectStatementAST<'a> { impl<'a> ASTNode<'a> for InspectStatementAST<'a> {
fn from_state<Qd: QueryData<'a>>( fn _from_state<Qd: QueryData<'a>>(
state: &mut State<'a, Qd>, state: &mut State<'a, Qd>,
) -> crate::engine::ql::LangResult<Self> { ) -> crate::engine::ql::LangResult<Self> {
super::parse_inspect(state).map(Self) super::parse_inspect(state).map(Self)

@ -505,78 +505,70 @@ mod impls {
}; };
use crate::engine::ql::{ use crate::engine::ql::{
ast::{traits::ASTNode, QueryData, State}, ast::{traits::ASTNode, QueryData, State},
LangError, LangResult, LangResult,
}; };
impl<'a> ASTNode<'a> for ExpandedField<'a> { impl<'a> ASTNode<'a> for ExpandedField<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse(state) Self::parse(state)
} }
fn multiple_from_state<Qd: QueryData<'a>>( fn _multiple_from_state<Qd: QueryData<'a>>(
state: &mut State<'a, Qd>, state: &mut State<'a, Qd>,
) -> LangResult<Vec<Self>> { ) -> LangResult<Vec<Self>> {
Self::parse_multiple(state).map(Vec::from) Self::parse_multiple(state).map(Vec::from)
} }
} }
impl<'a> ASTNode<'a> for Layer<'a> { impl<'a> ASTNode<'a> for Layer<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { // important: upstream must verify this
const VERIFY: bool = true;
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let mut layers = Vec::new(); let mut layers = Vec::new();
rfold_layers(LayerFoldState::BEGIN_IDENT, state, &mut layers); rfold_layers(LayerFoldState::BEGIN_IDENT, state, &mut layers);
assert!(layers.len() == 1); assert!(layers.len() == 1);
Ok(layers.swap_remove(0)) Ok(layers.swap_remove(0))
} }
fn multiple_from_state<Qd: QueryData<'a>>( fn _multiple_from_state<Qd: QueryData<'a>>(
state: &mut State<'a, Qd>, state: &mut State<'a, Qd>,
) -> LangResult<Vec<Self>> { ) -> LangResult<Vec<Self>> {
let mut l = Vec::new(); let mut l = Vec::new();
rfold_layers(LayerFoldState::BEGIN_IDENT, state, &mut l); rfold_layers(LayerFoldState::BEGIN_IDENT, state, &mut l);
if state.okay() {
Ok(l) Ok(l)
} else {
Err(LangError::UnexpectedToken)
}
} }
} }
#[derive(sky_macros::Wrapper, Debug)] #[derive(sky_macros::Wrapper, Debug)]
pub struct DictBasic(Dict); pub struct DictBasic(Dict);
impl<'a> ASTNode<'a> for DictBasic { impl<'a> ASTNode<'a> for DictBasic {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { // important: upstream must verify this
const VERIFY: bool = true;
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let mut dict = Dict::new(); let mut dict = Dict::new();
rfold_dict(DictFoldState::OB, state, &mut dict); rfold_dict(DictFoldState::OB, state, &mut dict);
if state.okay() {
Ok(Self(dict)) Ok(Self(dict))
} else {
Err(LangError::UnexpectedToken)
}
} }
} }
#[derive(sky_macros::Wrapper, Debug)] #[derive(sky_macros::Wrapper, Debug)]
pub struct DictTypeMetaSplit(Dict); pub struct DictTypeMetaSplit(Dict);
impl<'a> ASTNode<'a> for DictTypeMetaSplit { impl<'a> ASTNode<'a> for DictTypeMetaSplit {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { // important: upstream must verify this
const VERIFY: bool = true;
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let mut dict = Dict::new(); let mut dict = Dict::new();
rfold_tymeta(DictFoldState::CB_OR_IDENT, state, &mut dict); rfold_tymeta(DictFoldState::CB_OR_IDENT, state, &mut dict);
if state.okay() {
Ok(Self(dict)) Ok(Self(dict))
} else {
Err(LangError::UnexpectedToken)
}
} }
} }
#[derive(sky_macros::Wrapper, Debug)] #[derive(sky_macros::Wrapper, Debug)]
pub struct DictTypeMeta(Dict); pub struct DictTypeMeta(Dict);
impl<'a> ASTNode<'a> for DictTypeMeta { impl<'a> ASTNode<'a> for DictTypeMeta {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { // important: upstream must verify this
const VERIFY: bool = true;
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let mut dict = Dict::new(); let mut dict = Dict::new();
rfold_tymeta(DictFoldState::OB, state, &mut dict); rfold_tymeta(DictFoldState::OB, state, &mut dict);
if state.okay() {
Ok(Self(dict)) Ok(Self(dict))
} else {
Err(LangError::UnexpectedToken)
}
} }
} }
impl<'a> ASTNode<'a> for Field<'a> { impl<'a> ASTNode<'a> for Field<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse(state) Self::parse(state)
} }
} }

@ -30,7 +30,7 @@ use {
super::WhereClause, super::WhereClause,
crate::{ crate::{
engine::ql::{ engine::ql::{
ast::{traits::ASTNode, Entity, QueryData, State}, ast::{Entity, QueryData, State},
LangError, LangResult, LangError, LangResult,
}, },
util::{compiler, MaybeInit}, util::{compiler, MaybeInit},
@ -94,8 +94,15 @@ impl<'a> DeleteStatement<'a> {
} }
} }
mod impls {
use super::DeleteStatement;
use crate::engine::ql::{
ast::{traits::ASTNode, QueryData, State},
LangResult,
};
impl<'a> ASTNode<'a> for DeleteStatement<'a> { impl<'a> ASTNode<'a> for DeleteStatement<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse_delete(state) Self::parse_delete(state)
} }
} }
}

@ -30,7 +30,7 @@ use {
engine::{ engine::{
core::DataType, core::DataType,
ql::{ ql::{
ast::{traits::ASTNode, Entity, QueryData, State}, ast::{Entity, QueryData, State},
lex::Token, lex::Token,
LangError, LangResult, LangError, LangResult,
}, },
@ -207,22 +207,6 @@ unsafe fn handle_func_sub<'a, Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> O
ldfunc(func).map(move |f| f()) ldfunc(func).map(move |f| f())
} }
#[cfg(test)]
#[derive(sky_macros::Wrapper, Debug)]
pub struct List(Vec<DataType>);
#[cfg(test)]
impl<'a> ASTNode<'a> for List {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let mut l = Vec::new();
parse_list(state, &mut l);
if state.okay() {
Ok(List(l))
} else {
Err(LangError::UnexpectedToken)
}
}
}
/// ## Panics /// ## Panics
/// - If tt is empty /// - If tt is empty
pub(super) fn parse_data_tuple_syntax<'a, Qd: QueryData<'a>>( pub(super) fn parse_data_tuple_syntax<'a, Qd: QueryData<'a>>(
@ -270,21 +254,6 @@ pub(super) fn parse_data_tuple_syntax<'a, Qd: QueryData<'a>>(
data data
} }
#[cfg(test)]
#[derive(sky_macros::Wrapper, Debug)]
pub struct DataTuple(Vec<Option<DataType>>);
#[cfg(test)]
impl<'a> ASTNode<'a> for DataTuple {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let r = parse_data_tuple_syntax(state);
if state.okay() {
Ok(Self(r))
} else {
Err(LangError::UnexpectedToken)
}
}
}
/// ## Panics /// ## Panics
/// Panics if tt is empty /// Panics if tt is empty
pub(super) fn parse_data_map_syntax<'a, Qd: QueryData<'a>>( pub(super) fn parse_data_map_syntax<'a, Qd: QueryData<'a>>(
@ -341,30 +310,6 @@ pub(super) fn parse_data_map_syntax<'a, Qd: QueryData<'a>>(
data data
} }
#[cfg(test)]
#[derive(sky_macros::Wrapper, Debug)]
pub struct DataMap(HashMap<Box<str>, Option<DataType>>);
#[cfg(test)]
impl<'a> ASTNode<'a> for DataMap {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let r = parse_data_map_syntax(state);
if state.okay() {
Ok(Self(
r.into_iter()
.map(|(ident, val)| {
(
String::from_utf8_lossy(ident).to_string().into_boxed_str(),
val,
)
})
.collect(),
))
} else {
Err(LangError::UnexpectedToken)
}
}
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum InsertData<'a> { pub enum InsertData<'a> {
Ordered(Vec<Option<DataType>>), Ordered(Vec<Option<DataType>>),
@ -444,8 +389,67 @@ impl<'a> InsertStatement<'a> {
} }
} }
#[cfg(test)]
pub use impls::test::{DataMap, DataTuple, List};
mod impls {
use super::InsertStatement;
use crate::engine::ql::{
ast::{traits::ASTNode, QueryData, State},
LangResult,
};
impl<'a> ASTNode<'a> for InsertStatement<'a> { impl<'a> ASTNode<'a> for InsertStatement<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse_insert(state) Self::parse_insert(state)
} }
} }
#[cfg(test)]
pub mod test {
use super::super::{
parse_data_map_syntax, parse_data_tuple_syntax, parse_list, DataType, HashMap,
};
use crate::engine::ql::{
ast::{traits::ASTNode, QueryData, State},
LangResult,
};
#[derive(sky_macros::Wrapper, Debug)]
pub struct List(Vec<DataType>);
impl<'a> ASTNode<'a> for List {
// important: upstream must verify this
const VERIFY: bool = true;
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let mut l = Vec::new();
parse_list(state, &mut l);
Ok(List(l))
}
}
#[derive(sky_macros::Wrapper, Debug)]
pub struct DataTuple(Vec<Option<DataType>>);
impl<'a> ASTNode<'a> for DataTuple {
// important: upstream must verify this
const VERIFY: bool = true;
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let r = parse_data_tuple_syntax(state);
Ok(Self(r))
}
}
#[derive(sky_macros::Wrapper, Debug)]
pub struct DataMap(HashMap<Box<str>, Option<DataType>>);
impl<'a> ASTNode<'a> for DataMap {
// important: upstream must verify this
const VERIFY: bool = true;
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let r = parse_data_map_syntax(state);
Ok(Self(
r.into_iter()
.map(|(ident, val)| {
(
String::from_utf8_lossy(ident).to_string().into_boxed_str(),
val,
)
})
.collect(),
))
}
}
}
}

@ -36,9 +36,8 @@ pub mod upd;
use { use {
super::{ super::{
ast::{traits::ASTNode, QueryData, State}, ast::{QueryData, State},
lex::{LitIR, Token}, lex::{LitIR, Token},
LangError, LangResult,
}, },
crate::util::compiler, crate::util::compiler,
std::collections::HashMap, std::collections::HashMap,
@ -119,12 +118,6 @@ impl<'a> RelationalExpr<'a> {
} }
} }
impl<'a> ASTNode<'a> for RelationalExpr<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::try_parse(state).ok_or(LangError::UnexpectedToken)
}
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct WhereClause<'a> { pub struct WhereClause<'a> {
c: WhereClauseCollection<'a>, c: WhereClauseCollection<'a>,
@ -164,13 +157,26 @@ impl<'a> WhereClause<'a> {
} }
} }
#[cfg(test)]
mod impls {
use super::{
super::{
ast::{traits::ASTNode, QueryData, State},
LangError, LangResult,
},
RelationalExpr, WhereClause,
};
impl<'a> ASTNode<'a> for WhereClause<'a> { impl<'a> ASTNode<'a> for WhereClause<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { // important: upstream must verify this
const VERIFY: bool = true;
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let wh = Self::parse_where(state); let wh = Self::parse_where(state);
if state.okay() {
Ok(wh) Ok(wh)
} else { }
Err(LangError::UnexpectedToken) }
impl<'a> ASTNode<'a> for RelationalExpr<'a> {
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::try_parse(state).ok_or(LangError::UnexpectedToken)
} }
} }
} }

@ -28,7 +28,7 @@ use {
super::{WhereClause, WhereClauseCollection}, super::{WhereClause, WhereClauseCollection},
crate::{ crate::{
engine::ql::{ engine::ql::{
ast::{traits::ASTNode, Entity, QueryData, State}, ast::{Entity, QueryData, State},
lex::Token, lex::Token,
LangError, LangResult, LangError, LangResult,
}, },
@ -134,8 +134,15 @@ impl<'a> SelectStatement<'a> {
} }
} }
mod impls {
use super::SelectStatement;
use crate::engine::ql::{
ast::{traits::ASTNode, QueryData, State},
LangResult,
};
impl<'a> ASTNode<'a> for SelectStatement<'a> { impl<'a> ASTNode<'a> for SelectStatement<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse_select(state) Self::parse_select(state)
} }
} }
}

@ -25,15 +25,12 @@
*/ */
#[cfg(test)] #[cfg(test)]
use { use super::WhereClauseCollection;
super::WhereClauseCollection,
crate::engine::ql::{ast::InplaceData, lex::Token},
};
use { use {
super::{read_ident, u, WhereClause}, super::{read_ident, u, WhereClause},
crate::{ crate::{
engine::ql::{ engine::ql::{
ast::{traits::ASTNode, Entity, QueryData, State}, ast::{Entity, QueryData, State},
lex::LitIR, lex::LitIR,
LangError, LangResult, LangError, LangResult,
}, },
@ -132,20 +129,6 @@ impl<'a> AssignmentExpression<'a> {
} }
} }
#[cfg(test)]
pub fn parse_assn_expression_full<'a>(tok: &'a [Token]) -> Option<AssignmentExpression<'a>> {
let mut state = State::new(tok, InplaceData::new());
let mut exprs = Vec::new();
AssignmentExpression::parse_and_append_expression(&mut state, &mut exprs);
assert_full_tt!(state);
if state.okay() {
assert_eq!(exprs.len(), 1, "expected one expression, found multiple");
Some(exprs.remove(0))
} else {
None
}
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct UpdateStatement<'a> { pub struct UpdateStatement<'a> {
pub(super) entity: Entity<'a>, pub(super) entity: Entity<'a>,
@ -227,8 +210,36 @@ impl<'a> UpdateStatement<'a> {
} }
} }
mod impls {
use super::UpdateStatement;
use crate::engine::ql::{
ast::{traits::ASTNode, QueryData, State},
LangResult,
};
impl<'a> ASTNode<'a> for UpdateStatement<'a> { impl<'a> ASTNode<'a> for UpdateStatement<'a> {
fn from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> { fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
Self::parse_update(state) Self::parse_update(state)
} }
} }
#[cfg(test)]
mod test {
use super::{super::AssignmentExpression, *};
impl<'a> ASTNode<'a> for AssignmentExpression<'a> {
// important: upstream must verify this
const VERIFY: bool = true;
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> LangResult<Self> {
let mut expr = Vec::new();
AssignmentExpression::parse_and_append_expression(state, &mut expr);
state.poison_if_not(expr.len() == 1);
Ok(expr.remove(0))
}
fn _multiple_from_state<Qd: QueryData<'a>>(
state: &mut State<'a, Qd>,
) -> LangResult<Vec<Self>> {
let mut expr = Vec::new();
AssignmentExpression::parse_and_append_expression(state, &mut expr);
Ok(expr)
}
}
}
}

@ -24,21 +24,6 @@
* *
*/ */
#[cfg(test)]
macro_rules! assert_full_tt {
($a:expr, $b:expr) => {
assert_eq!($a, $b, "full token stream not utilized")
};
($a:expr) => {
assert!(
crate::engine::ql::ast::State::exhausted(&$a),
"full tt not utilized at: {}:{}",
::core::file!(),
::core::line!()
)
};
}
macro_rules! __sym_token { macro_rules! __sym_token {
($ident:ident) => { ($ident:ident) => {
$crate::engine::ql::lex::Token::Symbol($crate::engine::ql::lex::Symbol::$ident) $crate::engine::ql::lex::Token::Symbol($crate::engine::ql::lex::Symbol::$ident)

@ -690,17 +690,15 @@ mod expression_tests {
use { use {
super::*, super::*,
crate::engine::ql::{ crate::engine::ql::{
dml::{ ast::parse_ast_node_full,
self, dml::upd::{AssignmentExpression, Operator},
upd::{AssignmentExpression, Operator},
},
lex::LitIR, lex::LitIR,
}, },
}; };
#[test] #[test]
fn expr_assign() { fn expr_assign() {
let src = lex_insecure(b"username = 'sayan'").unwrap(); let src = lex_insecure(b"username = 'sayan'").unwrap();
let r = dml::upd::parse_assn_expression_full(&src).unwrap(); let r = parse_ast_node_full::<AssignmentExpression>(&src).unwrap();
assert_eq!( assert_eq!(
r, r,
AssignmentExpression::new(b"username", LitIR::Str("sayan"), Operator::Assign) AssignmentExpression::new(b"username", LitIR::Str("sayan"), Operator::Assign)
@ -709,7 +707,7 @@ mod expression_tests {
#[test] #[test]
fn expr_add_assign() { fn expr_add_assign() {
let src = lex_insecure(b"followers += 100").unwrap(); let src = lex_insecure(b"followers += 100").unwrap();
let r = dml::upd::parse_assn_expression_full(&src).unwrap(); let r = parse_ast_node_full::<AssignmentExpression>(&src).unwrap();
assert_eq!( assert_eq!(
r, r,
AssignmentExpression::new(b"followers", LitIR::UInt(100), Operator::AddAssign) AssignmentExpression::new(b"followers", LitIR::UInt(100), Operator::AddAssign)
@ -718,7 +716,7 @@ mod expression_tests {
#[test] #[test]
fn expr_sub_assign() { fn expr_sub_assign() {
let src = lex_insecure(b"following -= 150").unwrap(); let src = lex_insecure(b"following -= 150").unwrap();
let r = dml::upd::parse_assn_expression_full(&src).unwrap(); let r = parse_ast_node_full::<AssignmentExpression>(&src).unwrap();
assert_eq!( assert_eq!(
r, r,
AssignmentExpression::new(b"following", LitIR::UInt(150), Operator::SubAssign) AssignmentExpression::new(b"following", LitIR::UInt(150), Operator::SubAssign)
@ -727,7 +725,7 @@ mod expression_tests {
#[test] #[test]
fn expr_mul_assign() { fn expr_mul_assign() {
let src = lex_insecure(b"product_qty *= 2").unwrap(); let src = lex_insecure(b"product_qty *= 2").unwrap();
let r = dml::upd::parse_assn_expression_full(&src).unwrap(); let r = parse_ast_node_full::<AssignmentExpression>(&src).unwrap();
assert_eq!( assert_eq!(
r, r,
AssignmentExpression::new(b"product_qty", LitIR::UInt(2), Operator::MulAssign) AssignmentExpression::new(b"product_qty", LitIR::UInt(2), Operator::MulAssign)
@ -736,7 +734,7 @@ mod expression_tests {
#[test] #[test]
fn expr_div_assign() { fn expr_div_assign() {
let src = lex_insecure(b"image_crop_factor /= 2").unwrap(); let src = lex_insecure(b"image_crop_factor /= 2").unwrap();
let r = dml::upd::parse_assn_expression_full(&src).unwrap(); let r = parse_ast_node_full::<AssignmentExpression>(&src).unwrap();
assert_eq!( assert_eq!(
r, r,
AssignmentExpression::new(b"image_crop_factor", LitIR::UInt(2), Operator::DivAssign) AssignmentExpression::new(b"image_crop_factor", LitIR::UInt(2), Operator::DivAssign)

@ -408,7 +408,7 @@ mod schemas {
use crate::engine::ql::{ use crate::engine::ql::{
ast::parse_ast_node_full, ast::parse_ast_node_full,
ddl::{ ddl::{
crt::Model, crt::CreateModel,
syn::{Field, Layer}, syn::{Field, Layer},
}, },
}; };
@ -426,11 +426,11 @@ mod schemas {
let tok = &tok[2..]; let tok = &tok[2..];
// parse model // parse model
let model = parse_ast_node_full::<Model>(tok).unwrap(); let model = parse_ast_node_full::<CreateModel>(tok).unwrap();
assert_eq!( assert_eq!(
model, model,
Model::new( CreateModel::new(
b"mymodel", b"mymodel",
vec![ vec![
Field::new( Field::new(
@ -465,11 +465,11 @@ mod schemas {
let tok = &tok[2..]; let tok = &tok[2..];
// parse model // parse model
let model = parse_ast_node_full::<Model>(tok).unwrap(); let model = parse_ast_node_full::<CreateModel>(tok).unwrap();
assert_eq!( assert_eq!(
model, model,
Model::new( CreateModel::new(
b"mymodel", b"mymodel",
vec![ vec![
Field::new( Field::new(
@ -515,11 +515,11 @@ mod schemas {
let tok = &tok[2..]; let tok = &tok[2..];
// parse model // parse model
let model = parse_ast_node_full::<Model>(tok).unwrap(); let model = parse_ast_node_full::<CreateModel>(tok).unwrap();
assert_eq!( assert_eq!(
model, model,
Model::new( CreateModel::new(
b"mymodel", b"mymodel",
vec![ vec![
Field::new( Field::new(
@ -584,11 +584,11 @@ mod schemas {
let tok = &tok[2..]; let tok = &tok[2..];
// parse model // parse model
let model = parse_ast_node_full::<Model>(tok).unwrap(); let model = parse_ast_node_full::<CreateModel>(tok).unwrap();
assert_eq!( assert_eq!(
model, model,
Model::new( CreateModel::new(
b"mymodel", b"mymodel",
vec![ vec![
Field::new( Field::new(

Loading…
Cancel
Save