Relax requirements for field filters to allow for more useful error msg

This commit is contained in:
NGnius (Graham) 2022-02-24 12:11:26 -05:00
parent ec03746b41
commit 93fd85b0fc
5 changed files with 21 additions and 13 deletions

View file

@ -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(()),

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,