Relax requirements for field filters to allow for more useful error msg
This commit is contained in:
parent
ec03746b41
commit
93fd85b0fc
5 changed files with 21 additions and 13 deletions
|
@ -169,7 +169,6 @@ pub fn assert_type(tokens: &mut VecDeque<MpsToken>) -> Result<MpsTypePrimitive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
pub fn assert_empty(tokens: &mut VecDeque<MpsToken>) -> Result<(), SyntaxError> {
|
pub fn assert_empty(tokens: &mut VecDeque<MpsToken>) -> Result<(), SyntaxError> {
|
||||||
match tokens.pop_front() {
|
match tokens.pop_front() {
|
||||||
None => Ok(()),
|
None => Ok(()),
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::VecDeque;
|
||||||
use std::fmt::{Debug, Display, Error, Formatter};
|
use std::fmt::{Debug, Display, Error, Formatter};
|
||||||
|
|
||||||
use super::utility::{assert_comparison_operator, comparison_op};
|
use super::utility::{assert_comparison_operator, comparison_op};
|
||||||
use crate::lang::utility::{assert_token, assert_type, check_is_type};
|
use crate::lang::utility::{assert_token, assert_type, check_is_type, assert_empty};
|
||||||
use crate::lang::MpsLanguageDictionary;
|
use crate::lang::MpsLanguageDictionary;
|
||||||
use crate::lang::MpsTypePrimitive;
|
use crate::lang::MpsTypePrimitive;
|
||||||
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
|
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
|
||||||
|
@ -104,11 +104,12 @@ pub struct FieldFilterFactory;
|
||||||
impl MpsFilterFactory<FieldFilter> for FieldFilterFactory {
|
impl MpsFilterFactory<FieldFilter> for FieldFilterFactory {
|
||||||
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
||||||
let tokens_len = tokens.len();
|
let tokens_len = tokens.len();
|
||||||
(tokens_len == 3 // field > variable OR field < variable
|
(tokens_len >= 3
|
||||||
|
// field > variable OR field < variable
|
||||||
&& tokens[0].is_name()
|
&& tokens[0].is_name()
|
||||||
&& (tokens[1].is_open_angle_bracket() || tokens[1].is_close_angle_bracket())
|
&& (tokens[1].is_open_angle_bracket() || tokens[1].is_close_angle_bracket())
|
||||||
&& (tokens[2].is_name() || check_is_type(tokens[2])))
|
&& (tokens[2].is_name() || check_is_type(tokens[2])))
|
||||||
|| (tokens_len == 4 // field >= variable OR field <= variable OR field != variable
|
|| (tokens_len >= 4 // field >= variable OR field <= variable OR field != variable
|
||||||
&& tokens[0].is_name()
|
&& tokens[0].is_name()
|
||||||
&& (tokens[1].is_open_angle_bracket() || tokens[1].is_close_angle_bracket() || tokens[1].is_equals() || tokens[1].is_exclamation())
|
&& (tokens[1].is_open_angle_bracket() || tokens[1].is_close_angle_bracket() || tokens[1].is_equals() || tokens[1].is_exclamation())
|
||||||
&& tokens[2].is_equals()
|
&& tokens[2].is_equals()
|
||||||
|
@ -131,6 +132,7 @@ impl MpsFilterFactory<FieldFilter> for FieldFilterFactory {
|
||||||
let compare_operator = assert_comparison_operator(tokens)?;
|
let compare_operator = assert_comparison_operator(tokens)?;
|
||||||
if check_is_type(&tokens[0]) {
|
if check_is_type(&tokens[0]) {
|
||||||
let value = VariableOrValue::Value(assert_type(tokens)?);
|
let value = VariableOrValue::Value(assert_type(tokens)?);
|
||||||
|
assert_empty(tokens)?;
|
||||||
Ok(FieldFilter {
|
Ok(FieldFilter {
|
||||||
field_name: field,
|
field_name: field,
|
||||||
field_errors: FieldFilterErrorHandling::Error,
|
field_errors: FieldFilterErrorHandling::Error,
|
||||||
|
@ -147,6 +149,7 @@ impl MpsFilterFactory<FieldFilter> for FieldFilterFactory {
|
||||||
MpsToken::Name("variable_name".into()),
|
MpsToken::Name("variable_name".into()),
|
||||||
tokens,
|
tokens,
|
||||||
)?);
|
)?);
|
||||||
|
assert_empty(tokens)?;
|
||||||
Ok(FieldFilter {
|
Ok(FieldFilter {
|
||||||
field_name: field,
|
field_name: field,
|
||||||
field_errors: FieldFilterErrorHandling::Error,
|
field_errors: FieldFilterErrorHandling::Error,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::VecDeque;
|
||||||
|
|
||||||
use super::utility::assert_comparison_operator;
|
use super::utility::assert_comparison_operator;
|
||||||
use super::{field_filter::VariableOrValue, FieldFilter, FieldFilterErrorHandling};
|
use super::{field_filter::VariableOrValue, FieldFilter, FieldFilterErrorHandling};
|
||||||
use crate::lang::utility::{assert_token, assert_token_raw, assert_type, check_is_type};
|
use crate::lang::utility::{assert_token, assert_token_raw, assert_type, check_is_type, assert_empty};
|
||||||
use crate::lang::MpsLanguageDictionary;
|
use crate::lang::MpsLanguageDictionary;
|
||||||
use crate::lang::SyntaxError;
|
use crate::lang::SyntaxError;
|
||||||
use crate::lang::{MpsFilterFactory, MpsFilterStatementFactory};
|
use crate::lang::{MpsFilterFactory, MpsFilterStatementFactory};
|
||||||
|
@ -13,12 +13,12 @@ pub struct FieldFilterMaybeFactory;
|
||||||
impl MpsFilterFactory<FieldFilter> for FieldFilterMaybeFactory {
|
impl MpsFilterFactory<FieldFilter> for FieldFilterMaybeFactory {
|
||||||
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
||||||
let tokens_len = tokens.len();
|
let tokens_len = tokens.len();
|
||||||
(tokens_len == 4 // field > variable OR field < variable
|
(tokens_len >= 4 // field > variable OR field < variable
|
||||||
&& tokens[0].is_name()
|
&& tokens[0].is_name()
|
||||||
&& (tokens[1].is_interrogation() || tokens[1].is_exclamation())
|
&& (tokens[1].is_interrogation() || tokens[1].is_exclamation())
|
||||||
&& (tokens[2].is_open_angle_bracket() || tokens[2].is_close_angle_bracket())
|
&& (tokens[2].is_open_angle_bracket() || tokens[2].is_close_angle_bracket())
|
||||||
&& (tokens[3].is_name() || check_is_type(tokens[3])))
|
&& (tokens[3].is_name() || check_is_type(tokens[3])))
|
||||||
|| (tokens_len == 5 // field >= variable OR field <= variable OR field != variable
|
|| (tokens_len >= 5 // field >= variable OR field <= variable OR field != variable
|
||||||
&& tokens[0].is_name()
|
&& tokens[0].is_name()
|
||||||
&& (tokens[1].is_interrogation() || tokens[1].is_exclamation())
|
&& (tokens[1].is_interrogation() || tokens[1].is_exclamation())
|
||||||
&& (tokens[2].is_open_angle_bracket() || tokens[2].is_close_angle_bracket() || tokens[2].is_equals() || tokens[2].is_exclamation())
|
&& (tokens[2].is_open_angle_bracket() || tokens[2].is_close_angle_bracket() || tokens[2].is_equals() || tokens[2].is_exclamation())
|
||||||
|
@ -53,6 +53,7 @@ impl MpsFilterFactory<FieldFilter> for FieldFilterMaybeFactory {
|
||||||
let compare_operator = assert_comparison_operator(tokens)?;
|
let compare_operator = assert_comparison_operator(tokens)?;
|
||||||
if check_is_type(&tokens[0]) {
|
if check_is_type(&tokens[0]) {
|
||||||
let value = VariableOrValue::Value(assert_type(tokens)?);
|
let value = VariableOrValue::Value(assert_type(tokens)?);
|
||||||
|
assert_empty(tokens)?;
|
||||||
Ok(FieldFilter {
|
Ok(FieldFilter {
|
||||||
field_name: field,
|
field_name: field,
|
||||||
field_errors: error_f,
|
field_errors: error_f,
|
||||||
|
@ -69,6 +70,7 @@ impl MpsFilterFactory<FieldFilter> for FieldFilterMaybeFactory {
|
||||||
MpsToken::Name("variable_name".into()),
|
MpsToken::Name("variable_name".into()),
|
||||||
tokens,
|
tokens,
|
||||||
)?);
|
)?);
|
||||||
|
assert_empty(tokens)?;
|
||||||
Ok(FieldFilter {
|
Ok(FieldFilter {
|
||||||
field_name: field,
|
field_name: field,
|
||||||
field_errors: error_f,
|
field_errors: error_f,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::VecDeque;
|
||||||
use std::fmt::{Debug, Display, Error, Formatter};
|
use std::fmt::{Debug, Display, Error, Formatter};
|
||||||
|
|
||||||
use super::field_filter::{FieldFilterErrorHandling, VariableOrValue};
|
use super::field_filter::{FieldFilterErrorHandling, VariableOrValue};
|
||||||
use crate::lang::utility::{assert_name, assert_token, assert_token_raw, check_name};
|
use crate::lang::utility::{assert_name, assert_token, assert_token_raw, check_name, assert_empty};
|
||||||
use crate::lang::MpsLanguageDictionary;
|
use crate::lang::MpsLanguageDictionary;
|
||||||
use crate::lang::MpsTypePrimitive;
|
use crate::lang::MpsTypePrimitive;
|
||||||
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
|
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
|
||||||
|
@ -72,11 +72,11 @@ pub struct FieldLikeFilterFactory;
|
||||||
impl MpsFilterFactory<FieldLikeFilter> for FieldLikeFilterFactory {
|
impl MpsFilterFactory<FieldLikeFilter> for FieldLikeFilterFactory {
|
||||||
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
||||||
let tokens_len = tokens.len();
|
let tokens_len = tokens.len();
|
||||||
(tokens_len == 3 // field like variable
|
(tokens_len >= 3 // field like variable
|
||||||
&& tokens[0].is_name()
|
&& tokens[0].is_name()
|
||||||
&& check_name("like", tokens[1])
|
&& check_name("like", tokens[1])
|
||||||
&& (tokens[2].is_name() || tokens[2].is_literal()))
|
&& (tokens[2].is_name() || tokens[2].is_literal()))
|
||||||
|| (tokens_len == 4 // field? like variable OR field! like variable
|
|| (tokens_len >= 4 // field? like variable OR field! like variable
|
||||||
&& tokens[0].is_name()
|
&& tokens[0].is_name()
|
||||||
&& (tokens[1].is_interrogation() || tokens[1].is_exclamation())
|
&& (tokens[1].is_interrogation() || tokens[1].is_exclamation())
|
||||||
&& check_name("like", tokens[2])
|
&& check_name("like", tokens[2])
|
||||||
|
@ -116,6 +116,7 @@ impl MpsFilterFactory<FieldLikeFilter> for FieldLikeFilterFactory {
|
||||||
tokens,
|
tokens,
|
||||||
)?;
|
)?;
|
||||||
let value = VariableOrValue::Value(MpsTypePrimitive::String(literal));
|
let value = VariableOrValue::Value(MpsTypePrimitive::String(literal));
|
||||||
|
assert_empty(tokens)?;
|
||||||
Ok(FieldLikeFilter {
|
Ok(FieldLikeFilter {
|
||||||
field_name: field,
|
field_name: field,
|
||||||
field_errors: error_handling,
|
field_errors: error_handling,
|
||||||
|
@ -130,6 +131,7 @@ impl MpsFilterFactory<FieldLikeFilter> for FieldLikeFilterFactory {
|
||||||
MpsToken::Name("variable_name".into()),
|
MpsToken::Name("variable_name".into()),
|
||||||
tokens,
|
tokens,
|
||||||
)?);
|
)?);
|
||||||
|
assert_empty(tokens)?;
|
||||||
Ok(FieldLikeFilter {
|
Ok(FieldLikeFilter {
|
||||||
field_name: field,
|
field_name: field,
|
||||||
field_errors: FieldFilterErrorHandling::Error,
|
field_errors: FieldFilterErrorHandling::Error,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::fmt::{Debug, Display, Error, Formatter};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use super::field_filter::{FieldFilterErrorHandling, VariableOrValue};
|
use super::field_filter::{FieldFilterErrorHandling, VariableOrValue};
|
||||||
use crate::lang::utility::{assert_name, assert_token, assert_token_raw, check_name};
|
use crate::lang::utility::{assert_name, assert_token, assert_token_raw, check_name, assert_empty};
|
||||||
use crate::lang::MpsLanguageDictionary;
|
use crate::lang::MpsLanguageDictionary;
|
||||||
use crate::lang::MpsTypePrimitive;
|
use crate::lang::MpsTypePrimitive;
|
||||||
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
|
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
|
||||||
|
@ -83,11 +83,11 @@ pub struct FieldRegexFilterFactory;
|
||||||
impl MpsFilterFactory<FieldRegexFilter> for FieldRegexFilterFactory {
|
impl MpsFilterFactory<FieldRegexFilter> for FieldRegexFilterFactory {
|
||||||
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
|
||||||
let tokens_len = tokens.len();
|
let tokens_len = tokens.len();
|
||||||
(tokens_len == 3 // field like variable
|
(tokens_len >= 3 // field like variable
|
||||||
&& tokens[0].is_name()
|
&& tokens[0].is_name()
|
||||||
&& check_name("matches", tokens[1])
|
&& check_name("matches", tokens[1])
|
||||||
&& (tokens[2].is_name() || tokens[2].is_literal()))
|
&& (tokens[2].is_name() || tokens[2].is_literal()))
|
||||||
|| (tokens_len == 4 // field? like variable OR field! like variable
|
|| (tokens_len >= 4 // field? like variable OR field! like variable
|
||||||
&& tokens[0].is_name()
|
&& tokens[0].is_name()
|
||||||
&& (tokens[1].is_interrogation() || tokens[1].is_exclamation())
|
&& (tokens[1].is_interrogation() || tokens[1].is_exclamation())
|
||||||
&& check_name("matches", tokens[2])
|
&& check_name("matches", tokens[2])
|
||||||
|
@ -133,6 +133,7 @@ impl MpsFilterFactory<FieldRegexFilter> for FieldRegexFilterFactory {
|
||||||
})?;
|
})?;
|
||||||
let compiled_cache = (literal.clone(), regex_c);
|
let compiled_cache = (literal.clone(), regex_c);
|
||||||
let value = VariableOrValue::Value(MpsTypePrimitive::String(literal));
|
let value = VariableOrValue::Value(MpsTypePrimitive::String(literal));
|
||||||
|
assert_empty(tokens)?;
|
||||||
Ok(FieldRegexFilter {
|
Ok(FieldRegexFilter {
|
||||||
field_name: field,
|
field_name: field,
|
||||||
field_errors: error_handling,
|
field_errors: error_handling,
|
||||||
|
@ -148,6 +149,7 @@ impl MpsFilterFactory<FieldRegexFilter> for FieldRegexFilterFactory {
|
||||||
MpsToken::Name("variable_name".into()),
|
MpsToken::Name("variable_name".into()),
|
||||||
tokens,
|
tokens,
|
||||||
)?);
|
)?);
|
||||||
|
assert_empty(tokens)?;
|
||||||
Ok(FieldRegexFilter {
|
Ok(FieldRegexFilter {
|
||||||
field_name: field,
|
field_name: field,
|
||||||
field_errors: FieldFilterErrorHandling::Error,
|
field_errors: FieldFilterErrorHandling::Error,
|
||||||
|
|
Loading…
Reference in a new issue