Fix indexing parsing.
This commit is contained in:
parent
c7aea45d4b
commit
04df4d2547
@ -9,6 +9,7 @@ Bug fixes
|
|||||||
|
|
||||||
* Self-contained `AST` now works properly with `Engine::call_fn`.
|
* Self-contained `AST` now works properly with `Engine::call_fn`.
|
||||||
* Missing `to_int` from `Decimal` is added.
|
* Missing `to_int` from `Decimal` is added.
|
||||||
|
* Parsing of index expressions is relaxed and many cases no longer result in an index-type error to allow for custom indexers.
|
||||||
|
|
||||||
Deprecated API's
|
Deprecated API's
|
||||||
----------------
|
----------------
|
||||||
|
@ -799,6 +799,8 @@ impl Expr {
|
|||||||
match token {
|
match token {
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Token::Period => return true,
|
Token::Period => return true,
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
Token::LeftBracket => return true,
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -823,15 +825,9 @@ impl Expr {
|
|||||||
| Self::Index(..)
|
| Self::Index(..)
|
||||||
| Self::Array(..)
|
| Self::Array(..)
|
||||||
| Self::Map(..)
|
| Self::Map(..)
|
||||||
| Self::Custom(..) => match token {
|
| Self::Custom(..) => false,
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
Token::LeftBracket => true,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
|
|
||||||
Self::Variable(..) => match token {
|
Self::Variable(..) => match token {
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
Token::LeftBracket => true,
|
|
||||||
Token::LeftParen => true,
|
Token::LeftParen => true,
|
||||||
Token::Unit => true,
|
Token::Unit => true,
|
||||||
Token::Bang => true,
|
Token::Bang => true,
|
||||||
@ -840,8 +836,6 @@ impl Expr {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Self::Property(..) => match token {
|
Self::Property(..) => match token {
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
Token::LeftBracket => true,
|
|
||||||
Token::LeftParen => true,
|
Token::LeftParen => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
|
153
src/parser.rs
153
src/parser.rs
@ -631,6 +631,7 @@ impl Engine {
|
|||||||
state: &mut ParseState,
|
state: &mut ParseState,
|
||||||
lib: &mut FnLib,
|
lib: &mut FnLib,
|
||||||
lhs: Expr,
|
lhs: Expr,
|
||||||
|
chained: bool,
|
||||||
settings: ParseSettings,
|
settings: ParseSettings,
|
||||||
) -> ParseResult<Expr> {
|
) -> ParseResult<Expr> {
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
@ -640,113 +641,100 @@ impl Engine {
|
|||||||
|
|
||||||
let idx_expr = self.parse_expr(input, state, lib, settings.level_up())?;
|
let idx_expr = self.parse_expr(input, state, lib, settings.level_up())?;
|
||||||
|
|
||||||
// Check type of indexing - must be integer or string
|
// Check types of indexing that cannot be overridden
|
||||||
match idx_expr {
|
// - arrays, maps, strings, bit-fields
|
||||||
Expr::IntegerConstant(.., pos) => match lhs {
|
match lhs {
|
||||||
Expr::IntegerConstant(..)
|
_ if chained => (),
|
||||||
| Expr::Array(..)
|
|
||||||
| Expr::StringConstant(..)
|
|
||||||
| Expr::InterpolatedString(..) => (),
|
|
||||||
|
|
||||||
Expr::Map(..) => {
|
Expr::Map(..) => match idx_expr {
|
||||||
|
// lhs[int]
|
||||||
|
Expr::IntegerConstant(..) => {
|
||||||
return Err(PERR::MalformedIndexExpr(
|
return Err(PERR::MalformedIndexExpr(
|
||||||
"Object map access expects string index, not a number".into(),
|
"Object map expects string index, not a number".into(),
|
||||||
)
|
|
||||||
.into_err(pos))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
Expr::FloatConstant(..) => {
|
|
||||||
return Err(PERR::MalformedIndexExpr(
|
|
||||||
"Only arrays, object maps and strings can be indexed".into(),
|
|
||||||
)
|
|
||||||
.into_err(lhs.start_position()))
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr::CharConstant(..)
|
|
||||||
| Expr::And(..)
|
|
||||||
| Expr::Or(..)
|
|
||||||
| Expr::BoolConstant(..)
|
|
||||||
| Expr::Unit(..) => {
|
|
||||||
return Err(PERR::MalformedIndexExpr(
|
|
||||||
"Only arrays, object maps and strings can be indexed".into(),
|
|
||||||
)
|
|
||||||
.into_err(lhs.start_position()))
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => (),
|
|
||||||
},
|
|
||||||
|
|
||||||
// lhs[string]
|
|
||||||
Expr::StringConstant(..) | Expr::InterpolatedString(..) => match lhs {
|
|
||||||
Expr::Map(..) => (),
|
|
||||||
|
|
||||||
Expr::Array(..) | Expr::StringConstant(..) | Expr::InterpolatedString(..) => {
|
|
||||||
return Err(PERR::MalformedIndexExpr(
|
|
||||||
"Array or string expects numeric index, not a string".into(),
|
|
||||||
)
|
)
|
||||||
.into_err(idx_expr.start_position()))
|
.into_err(idx_expr.start_position()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
// lhs[string]
|
||||||
Expr::FloatConstant(..) => {
|
Expr::StringConstant(..) | Expr::InterpolatedString(..) => (),
|
||||||
return Err(PERR::MalformedIndexExpr(
|
|
||||||
"Only arrays, object maps and strings can be indexed".into(),
|
|
||||||
)
|
|
||||||
.into_err(lhs.start_position()))
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr::CharConstant(..)
|
|
||||||
| Expr::And(..)
|
|
||||||
| Expr::Or(..)
|
|
||||||
| Expr::BoolConstant(..)
|
|
||||||
| Expr::Unit(..) => {
|
|
||||||
return Err(PERR::MalformedIndexExpr(
|
|
||||||
"Only arrays, object maps and strings can be indexed".into(),
|
|
||||||
)
|
|
||||||
.into_err(lhs.start_position()))
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => (),
|
|
||||||
},
|
|
||||||
|
|
||||||
// lhs[float]
|
// lhs[float]
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
x @ Expr::FloatConstant(..) => {
|
Expr::FloatConstant(..) => {
|
||||||
return Err(PERR::MalformedIndexExpr(
|
return Err(PERR::MalformedIndexExpr(
|
||||||
"Array access expects integer index, not a float".into(),
|
"Object map expects string index, not a float".into(),
|
||||||
)
|
)
|
||||||
.into_err(x.start_position()))
|
.into_err(idx_expr.start_position()))
|
||||||
}
|
}
|
||||||
// lhs[char]
|
// lhs[char]
|
||||||
x @ Expr::CharConstant(..) => {
|
Expr::CharConstant(..) => {
|
||||||
return Err(PERR::MalformedIndexExpr(
|
return Err(PERR::MalformedIndexExpr(
|
||||||
"Array access expects integer index, not a character".into(),
|
"Object map expects string index, not a character".into(),
|
||||||
)
|
)
|
||||||
.into_err(x.start_position()))
|
.into_err(idx_expr.start_position()))
|
||||||
}
|
}
|
||||||
// lhs[()]
|
// lhs[()]
|
||||||
x @ Expr::Unit(..) => {
|
Expr::Unit(..) => {
|
||||||
return Err(PERR::MalformedIndexExpr(
|
return Err(PERR::MalformedIndexExpr(
|
||||||
"Array access expects integer index, not ()".into(),
|
"Object map expects string index, not ()".into(),
|
||||||
)
|
)
|
||||||
.into_err(x.start_position()))
|
.into_err(idx_expr.start_position()))
|
||||||
}
|
}
|
||||||
// lhs[??? && ???], lhs[??? || ???]
|
// lhs[??? && ???], lhs[??? || ???], lhs[true], lhs[false]
|
||||||
x @ Expr::And(..) | x @ Expr::Or(..) => {
|
Expr::And(..) | Expr::Or(..) | Expr::BoolConstant(..) => {
|
||||||
return Err(PERR::MalformedIndexExpr(
|
return Err(PERR::MalformedIndexExpr(
|
||||||
"Array access expects integer index, not a boolean".into(),
|
"Object map expects string index, not a boolean".into(),
|
||||||
)
|
)
|
||||||
.into_err(x.start_position()))
|
.into_err(idx_expr.start_position()))
|
||||||
}
|
}
|
||||||
// lhs[true], lhs[false]
|
_ => (),
|
||||||
x @ Expr::BoolConstant(..) => {
|
},
|
||||||
|
|
||||||
|
Expr::IntegerConstant(..)
|
||||||
|
| Expr::Array(..)
|
||||||
|
| Expr::StringConstant(..)
|
||||||
|
| Expr::InterpolatedString(..) => match idx_expr {
|
||||||
|
// lhs[int]
|
||||||
|
Expr::IntegerConstant(..) => (),
|
||||||
|
|
||||||
|
// lhs[string]
|
||||||
|
Expr::StringConstant(..) | Expr::InterpolatedString(..) => {
|
||||||
return Err(PERR::MalformedIndexExpr(
|
return Err(PERR::MalformedIndexExpr(
|
||||||
"Array access expects integer index, not a boolean".into(),
|
"Array, string or bit-field expects numeric index, not a string".into(),
|
||||||
)
|
)
|
||||||
.into_err(x.start_position()))
|
.into_err(idx_expr.start_position()))
|
||||||
}
|
}
|
||||||
// All other expressions
|
// lhs[float]
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
Expr::FloatConstant(..) => {
|
||||||
|
return Err(PERR::MalformedIndexExpr(
|
||||||
|
"Array, string or bit-field expects integer index, not a float".into(),
|
||||||
|
)
|
||||||
|
.into_err(idx_expr.start_position()))
|
||||||
|
}
|
||||||
|
// lhs[char]
|
||||||
|
Expr::CharConstant(..) => {
|
||||||
|
return Err(PERR::MalformedIndexExpr(
|
||||||
|
"Array, string or bit-field expects integer index, not a character".into(),
|
||||||
|
)
|
||||||
|
.into_err(idx_expr.start_position()))
|
||||||
|
}
|
||||||
|
// lhs[()]
|
||||||
|
Expr::Unit(..) => {
|
||||||
|
return Err(PERR::MalformedIndexExpr(
|
||||||
|
"Array, string or bit-field expects integer index, not ()".into(),
|
||||||
|
)
|
||||||
|
.into_err(idx_expr.start_position()))
|
||||||
|
}
|
||||||
|
// lhs[??? && ???], lhs[??? || ???], lhs[true], lhs[false]
|
||||||
|
Expr::And(..) | Expr::Or(..) | Expr::BoolConstant(..) => {
|
||||||
|
return Err(PERR::MalformedIndexExpr(
|
||||||
|
"Array, string or bit-field expects integer index, not a boolean".into(),
|
||||||
|
)
|
||||||
|
.into_err(idx_expr.start_position()))
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,6 +755,7 @@ impl Engine {
|
|||||||
state,
|
state,
|
||||||
lib,
|
lib,
|
||||||
idx_expr,
|
idx_expr,
|
||||||
|
true,
|
||||||
settings.level_up(),
|
settings.level_up(),
|
||||||
)?;
|
)?;
|
||||||
// Indexing binds to right
|
// Indexing binds to right
|
||||||
@ -1628,7 +1617,7 @@ impl Engine {
|
|||||||
// Indexing
|
// Indexing
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
(expr, Token::LeftBracket) => {
|
(expr, Token::LeftBracket) => {
|
||||||
self.parse_index_chain(input, state, lib, expr, settings.level_up())?
|
self.parse_index_chain(input, state, lib, expr, false, settings.level_up())?
|
||||||
}
|
}
|
||||||
// Property access
|
// Property access
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
Loading…
Reference in New Issue
Block a user