Catch more invalid LHS for assignments.
This commit is contained in:
parent
024133ae2d
commit
473e40e8a4
@ -199,7 +199,7 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// xxx.lhs[idx_expr]
|
// xxx.lhs[idx_expr]
|
||||||
Expr::Index(lhs, idx_expr) => {
|
Expr::Index(lhs, idx_expr, idx_pos) => {
|
||||||
let idx = self.eval_index_value(scope, idx_expr)?;
|
let idx = self.eval_index_value(scope, idx_expr)?;
|
||||||
|
|
||||||
let (lhs_value, _) = match lhs.as_ref() {
|
let (lhs_value, _) = match lhs.as_ref() {
|
||||||
@ -213,11 +213,12 @@ impl Engine<'_> {
|
|||||||
expr => return Err(EvalAltResult::ErrorDotExpr(expr.position())),
|
expr => return Err(EvalAltResult::ErrorDotExpr(expr.position())),
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::get_indexed_value(lhs_value, idx, idx_expr.position()).map(|(v, _)| v)
|
Self::get_indexed_value(lhs_value, idx, idx_expr.position(), *idx_pos)
|
||||||
|
.map(|(v, _)| v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// xxx.lhs.rhs
|
// xxx.lhs.rhs
|
||||||
Expr::Dot(lhs, rhs) => match lhs.as_ref() {
|
Expr::Dot(lhs, rhs, _) => match lhs.as_ref() {
|
||||||
// xxx.id.rhs
|
// xxx.id.rhs
|
||||||
Expr::Identifier(id, pos) => {
|
Expr::Identifier(id, pos) => {
|
||||||
let get_fn_name = format!("get${}", id);
|
let get_fn_name = format!("get${}", id);
|
||||||
@ -226,7 +227,7 @@ impl Engine<'_> {
|
|||||||
.and_then(|mut v| self.get_dot_val_helper(scope, v.as_mut(), rhs))
|
.and_then(|mut v| self.get_dot_val_helper(scope, v.as_mut(), rhs))
|
||||||
}
|
}
|
||||||
// xxx.lhs[idx_expr].rhs
|
// xxx.lhs[idx_expr].rhs
|
||||||
Expr::Index(lhs, idx_expr) => {
|
Expr::Index(lhs, idx_expr, idx_pos) => {
|
||||||
let idx = self.eval_index_value(scope, idx_expr)?;
|
let idx = self.eval_index_value(scope, idx_expr)?;
|
||||||
|
|
||||||
let (lhs_value, _) = match lhs.as_ref() {
|
let (lhs_value, _) = match lhs.as_ref() {
|
||||||
@ -240,7 +241,7 @@ impl Engine<'_> {
|
|||||||
expr => return Err(EvalAltResult::ErrorDotExpr(expr.position())),
|
expr => return Err(EvalAltResult::ErrorDotExpr(expr.position())),
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::get_indexed_value(lhs_value, idx, idx_expr.position()).and_then(
|
Self::get_indexed_value(lhs_value, idx, idx_expr.position(), *idx_pos).and_then(
|
||||||
|(mut value, _)| self.get_dot_val_helper(scope, value.as_mut(), rhs),
|
|(mut value, _)| self.get_dot_val_helper(scope, value.as_mut(), rhs),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -282,7 +283,8 @@ impl Engine<'_> {
|
|||||||
fn get_indexed_value(
|
fn get_indexed_value(
|
||||||
val: Dynamic,
|
val: Dynamic,
|
||||||
idx: i64,
|
idx: i64,
|
||||||
pos: Position,
|
val_pos: Position,
|
||||||
|
idx_pos: Position,
|
||||||
) -> Result<(Dynamic, IndexSourceType), EvalAltResult> {
|
) -> Result<(Dynamic, IndexSourceType), EvalAltResult> {
|
||||||
if val.is::<Array>() {
|
if val.is::<Array>() {
|
||||||
// val_array[idx]
|
// val_array[idx]
|
||||||
@ -292,9 +294,9 @@ impl Engine<'_> {
|
|||||||
arr.get(idx as usize)
|
arr.get(idx as usize)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|v| (v, IndexSourceType::Array))
|
.map(|v| (v, IndexSourceType::Array))
|
||||||
.ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), idx, pos))
|
.ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), idx, val_pos))
|
||||||
} else {
|
} else {
|
||||||
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx, pos))
|
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx, val_pos))
|
||||||
}
|
}
|
||||||
} else if val.is::<String>() {
|
} else if val.is::<String>() {
|
||||||
// val_string[idx]
|
// val_string[idx]
|
||||||
@ -304,17 +306,19 @@ impl Engine<'_> {
|
|||||||
s.chars()
|
s.chars()
|
||||||
.nth(idx as usize)
|
.nth(idx as usize)
|
||||||
.map(|ch| (ch.into_dynamic(), IndexSourceType::String))
|
.map(|ch| (ch.into_dynamic(), IndexSourceType::String))
|
||||||
.ok_or_else(|| EvalAltResult::ErrorStringBounds(s.chars().count(), idx, pos))
|
.ok_or_else(|| {
|
||||||
|
EvalAltResult::ErrorStringBounds(s.chars().count(), idx, val_pos)
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(EvalAltResult::ErrorStringBounds(
|
Err(EvalAltResult::ErrorStringBounds(
|
||||||
s.chars().count(),
|
s.chars().count(),
|
||||||
idx,
|
idx,
|
||||||
pos,
|
val_pos,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Error - cannot be indexed
|
// Error - cannot be indexed
|
||||||
Err(EvalAltResult::ErrorIndexingType(pos))
|
Err(EvalAltResult::ErrorIndexingType(idx_pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,6 +328,7 @@ impl Engine<'_> {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
lhs: &'a Expr,
|
lhs: &'a Expr,
|
||||||
idx_expr: &Expr,
|
idx_expr: &Expr,
|
||||||
|
idx_pos: Position,
|
||||||
) -> Result<(IndexSourceType, Option<(&'a str, usize)>, usize, Dynamic), EvalAltResult> {
|
) -> Result<(IndexSourceType, Option<(&'a str, usize)>, usize, Dynamic), EvalAltResult> {
|
||||||
let idx = self.eval_index_value(scope, idx_expr)?;
|
let idx = self.eval_index_value(scope, idx_expr)?;
|
||||||
|
|
||||||
@ -332,7 +337,7 @@ impl Engine<'_> {
|
|||||||
Expr::Identifier(id, _) => Self::search_scope(
|
Expr::Identifier(id, _) => Self::search_scope(
|
||||||
scope,
|
scope,
|
||||||
&id,
|
&id,
|
||||||
|val| Self::get_indexed_value(val, idx, idx_expr.position()),
|
|val| Self::get_indexed_value(val, idx, idx_expr.position(), idx_pos),
|
||||||
lhs.position(),
|
lhs.position(),
|
||||||
)
|
)
|
||||||
.map(|(src_idx, (val, src_type))| {
|
.map(|(src_idx, (val, src_type))| {
|
||||||
@ -340,7 +345,12 @@ impl Engine<'_> {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
// (expr)[idx_expr]
|
// (expr)[idx_expr]
|
||||||
expr => Self::get_indexed_value(self.eval_expr(scope, expr)?, idx, idx_expr.position())
|
expr => Self::get_indexed_value(
|
||||||
|
self.eval_expr(scope, expr)?,
|
||||||
|
idx,
|
||||||
|
idx_expr.position(),
|
||||||
|
idx_pos,
|
||||||
|
)
|
||||||
.map(|(val, _)| (IndexSourceType::Expression, None, idx as usize, val)),
|
.map(|(val, _)| (IndexSourceType::Expression, None, idx as usize, val)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,9 +422,9 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lhs[idx_expr].???
|
// lhs[idx_expr].???
|
||||||
Expr::Index(lhs, idx_expr) => {
|
Expr::Index(lhs, idx_expr, idx_pos) => {
|
||||||
let (src_type, src, idx, mut target) =
|
let (src_type, src, idx, mut target) =
|
||||||
self.eval_index_expr(scope, lhs, idx_expr)?;
|
self.eval_index_expr(scope, lhs, idx_expr, *idx_pos)?;
|
||||||
let value = self.get_dot_val_helper(scope, target.as_mut(), dot_rhs);
|
let value = self.get_dot_val_helper(scope, target.as_mut(), dot_rhs);
|
||||||
|
|
||||||
// In case the expression mutated `target`, we need to reassign it because
|
// In case the expression mutated `target`, we need to reassign it because
|
||||||
@ -457,7 +467,7 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// xxx.lhs.rhs
|
// xxx.lhs.rhs
|
||||||
Expr::Dot(lhs, rhs) => match lhs.as_ref() {
|
Expr::Dot(lhs, rhs, _) => match lhs.as_ref() {
|
||||||
Expr::Identifier(id, pos) => {
|
Expr::Identifier(id, pos) => {
|
||||||
let get_fn_name = format!("get${}", id);
|
let get_fn_name = format!("get${}", id);
|
||||||
|
|
||||||
@ -502,9 +512,9 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lhs[idx_expr].???
|
// lhs[idx_expr].???
|
||||||
Expr::Index(lhs, idx_expr) => {
|
Expr::Index(lhs, idx_expr, idx_pos) => {
|
||||||
let (src_type, src, idx, mut target) =
|
let (src_type, src, idx, mut target) =
|
||||||
self.eval_index_expr(scope, lhs, idx_expr)?;
|
self.eval_index_expr(scope, lhs, idx_expr, *idx_pos)?;
|
||||||
let value = self.set_dot_val_helper(target.as_mut(), dot_rhs, source_val);
|
let value = self.set_dot_val_helper(target.as_mut(), dot_rhs, source_val);
|
||||||
|
|
||||||
// In case the expression mutated `target`, we need to reassign it because
|
// In case the expression mutated `target`, we need to reassign it because
|
||||||
@ -534,12 +544,12 @@ impl Engine<'_> {
|
|||||||
Expr::Identifier(id, pos) => {
|
Expr::Identifier(id, pos) => {
|
||||||
Self::search_scope(scope, id, Ok, *pos).map(|(_, val)| val)
|
Self::search_scope(scope, id, Ok, *pos).map(|(_, val)| val)
|
||||||
}
|
}
|
||||||
Expr::Index(lhs, idx_expr) => self
|
Expr::Index(lhs, idx_expr, idx_pos) => self
|
||||||
.eval_index_expr(scope, lhs, idx_expr)
|
.eval_index_expr(scope, lhs, idx_expr, *idx_pos)
|
||||||
.map(|(_, _, _, x)| x),
|
.map(|(_, _, _, x)| x),
|
||||||
|
|
||||||
// lhs = rhs
|
// lhs = rhs
|
||||||
Expr::Assignment(lhs, rhs) => {
|
Expr::Assignment(lhs, rhs, _) => {
|
||||||
let rhs_val = self.eval_expr(scope, rhs)?;
|
let rhs_val = self.eval_expr(scope, rhs)?;
|
||||||
|
|
||||||
match lhs.as_ref() {
|
match lhs.as_ref() {
|
||||||
@ -554,9 +564,9 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// idx_lhs[idx_expr] = rhs
|
// idx_lhs[idx_expr] = rhs
|
||||||
Expr::Index(idx_lhs, idx_expr) => {
|
Expr::Index(idx_lhs, idx_expr, idx_pos) => {
|
||||||
let (src_type, src, idx, _) =
|
let (src_type, src, idx, _) =
|
||||||
self.eval_index_expr(scope, idx_lhs, idx_expr)?;
|
self.eval_index_expr(scope, idx_lhs, idx_expr, *idx_pos)?;
|
||||||
|
|
||||||
if let Some((id, src_idx)) = src {
|
if let Some((id, src_idx)) = src {
|
||||||
Ok(Self::update_indexed_variable_in_scope(
|
Ok(Self::update_indexed_variable_in_scope(
|
||||||
@ -570,7 +580,7 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dot_lhs.dot_rhs = rhs
|
// dot_lhs.dot_rhs = rhs
|
||||||
Expr::Dot(dot_lhs, dot_rhs) => {
|
Expr::Dot(dot_lhs, dot_rhs, _) => {
|
||||||
self.set_dot_val(scope, dot_lhs, dot_rhs, rhs_val)
|
self.set_dot_val(scope, dot_lhs, dot_rhs, rhs_val)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,7 +589,7 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Dot(lhs, rhs) => self.get_dot_val(scope, lhs, rhs),
|
Expr::Dot(lhs, rhs, _) => self.get_dot_val(scope, lhs, rhs),
|
||||||
|
|
||||||
Expr::Array(contents, _) => {
|
Expr::Array(contents, _) => {
|
||||||
let mut arr = Vec::new();
|
let mut arr = Vec::new();
|
||||||
|
204
src/parser.rs
204
src/parser.rs
@ -130,9 +130,9 @@ pub enum Expr {
|
|||||||
CharConstant(char, Position),
|
CharConstant(char, Position),
|
||||||
StringConstant(String, Position),
|
StringConstant(String, Position),
|
||||||
FunctionCall(String, Vec<Expr>, Option<Dynamic>, Position),
|
FunctionCall(String, Vec<Expr>, Option<Dynamic>, Position),
|
||||||
Assignment(Box<Expr>, Box<Expr>),
|
Assignment(Box<Expr>, Box<Expr>, Position),
|
||||||
Dot(Box<Expr>, Box<Expr>),
|
Dot(Box<Expr>, Box<Expr>, Position),
|
||||||
Index(Box<Expr>, Box<Expr>),
|
Index(Box<Expr>, Box<Expr>, Position),
|
||||||
Array(Vec<Expr>, Position),
|
Array(Vec<Expr>, Position),
|
||||||
And(Box<Expr>, Box<Expr>),
|
And(Box<Expr>, Box<Expr>),
|
||||||
Or(Box<Expr>, Box<Expr>),
|
Or(Box<Expr>, Box<Expr>),
|
||||||
@ -155,9 +155,9 @@ impl Expr {
|
|||||||
| Expr::False(pos)
|
| Expr::False(pos)
|
||||||
| Expr::Unit(pos) => *pos,
|
| Expr::Unit(pos) => *pos,
|
||||||
|
|
||||||
Expr::Index(e, _)
|
Expr::Index(e, _, _)
|
||||||
| Expr::Assignment(e, _)
|
| Expr::Assignment(e, _, _)
|
||||||
| Expr::Dot(e, _)
|
| Expr::Dot(e, _, _)
|
||||||
| Expr::And(e, _)
|
| Expr::And(e, _)
|
||||||
| Expr::Or(e, _) => e.position(),
|
| Expr::Or(e, _) => e.position(),
|
||||||
}
|
}
|
||||||
@ -1103,11 +1103,12 @@ fn parse_call_expr<'a>(
|
|||||||
fn parse_index_expr<'a>(
|
fn parse_index_expr<'a>(
|
||||||
lhs: Box<Expr>,
|
lhs: Box<Expr>,
|
||||||
input: &mut Peekable<TokenIterator<'a>>,
|
input: &mut Peekable<TokenIterator<'a>>,
|
||||||
|
pos: Position,
|
||||||
) -> Result<Expr, ParseError> {
|
) -> Result<Expr, ParseError> {
|
||||||
parse_expr(input).and_then(|idx_expr| match input.peek() {
|
parse_expr(input).and_then(|idx_expr| match input.peek() {
|
||||||
Some(&(Token::RightBracket, _)) => {
|
Some(&(Token::RightBracket, _)) => {
|
||||||
input.next();
|
input.next();
|
||||||
return Ok(Expr::Index(lhs, Box::new(idx_expr)));
|
return Ok(Expr::Index(lhs, Box::new(idx_expr), pos));
|
||||||
}
|
}
|
||||||
Some(&(_, pos)) => {
|
Some(&(_, pos)) => {
|
||||||
return Err(ParseError::new(
|
return Err(ParseError::new(
|
||||||
@ -1134,9 +1135,9 @@ fn parse_ident_expr<'a>(
|
|||||||
input.next();
|
input.next();
|
||||||
parse_call_expr(id, input, begin)
|
parse_call_expr(id, input, begin)
|
||||||
}
|
}
|
||||||
Some(&(Token::LeftBracket, _)) => {
|
Some(&(Token::LeftBracket, pos)) => {
|
||||||
input.next();
|
input.next();
|
||||||
parse_index_expr(Box::new(Expr::Identifier(id, begin)), input)
|
parse_index_expr(Box::new(Expr::Identifier(id, begin)), input, pos)
|
||||||
}
|
}
|
||||||
Some(_) => Ok(Expr::Identifier(id, begin)),
|
Some(_) => Ok(Expr::Identifier(id, begin)),
|
||||||
None => Ok(Expr::Identifier(id, Position::eof())),
|
None => Ok(Expr::Identifier(id, Position::eof())),
|
||||||
@ -1225,9 +1226,9 @@ fn parse_primary<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, Pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tail processing all possible indexing
|
// Tail processing all possible indexing
|
||||||
while let Some(&(Token::LeftBracket, _)) = input.peek() {
|
while let Some(&(Token::LeftBracket, pos)) = input.peek() {
|
||||||
input.next();
|
input.next();
|
||||||
root_expr = parse_index_expr(Box::new(root_expr), input)?;
|
root_expr = parse_index_expr(Box::new(root_expr), input, pos)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(root_expr)
|
Ok(root_expr)
|
||||||
@ -1263,18 +1264,39 @@ fn parse_unary<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, Pars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_assignment(lhs: Expr, rhs: Expr) -> Result<Expr, ParseError> {
|
fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result<Expr, ParseError> {
|
||||||
match lhs {
|
fn all_identifiers(expr: &Expr) -> (bool, Position) {
|
||||||
// Only assignments to a variable, and index erxpression and a dot expression is valid LHS
|
match expr {
|
||||||
Expr::Identifier(_, _) | Expr::Index(_, _) | Expr::Dot(_, _) => {
|
// variable
|
||||||
Ok(Expr::Assignment(Box::new(lhs), Box::new(rhs)))
|
Expr::Identifier(_, pos) => (true, *pos),
|
||||||
|
// indexing
|
||||||
|
Expr::Index(lhs, _, idx_pos) => match lhs.as_ref() {
|
||||||
|
// variable[x]
|
||||||
|
&Expr::Identifier(_, pos) => (true, pos),
|
||||||
|
// all other indexing is invalid
|
||||||
|
_ => (false, *idx_pos),
|
||||||
|
},
|
||||||
|
// variable.prop.prop.prop...
|
||||||
|
Expr::Dot(lhs, rhs, _) => match lhs.as_ref() {
|
||||||
|
// variable.prop
|
||||||
|
&Expr::Identifier(_, pos) => {
|
||||||
|
let r = all_identifiers(rhs);
|
||||||
|
(r.0, if r.0 { pos } else { r.1 })
|
||||||
|
}
|
||||||
|
// all other property access is invalid
|
||||||
|
_ => (false, lhs.position()),
|
||||||
|
},
|
||||||
|
// everything else is invalid
|
||||||
|
_ => (false, expr.position()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// All other LHS cannot be assigned to
|
let r = all_identifiers(&lhs);
|
||||||
_ => Err(ParseError::new(
|
|
||||||
PERR::AssignmentToInvalidLHS,
|
if r.0 {
|
||||||
lhs.position(),
|
Ok(Expr::Assignment(Box::new(lhs), Box::new(rhs), pos))
|
||||||
)),
|
} else {
|
||||||
|
Err(ParseError::new(PERR::AssignmentToInvalidLHS, r.1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1322,32 +1344,24 @@ fn parse_binary_op<'a>(
|
|||||||
}
|
}
|
||||||
Token::Divide => Expr::FunctionCall("/".into(), vec![current_lhs, rhs], None, pos),
|
Token::Divide => Expr::FunctionCall("/".into(), vec![current_lhs, rhs], None, pos),
|
||||||
|
|
||||||
Token::Equals => parse_assignment(current_lhs, rhs)?,
|
Token::Equals => parse_assignment(current_lhs, rhs, pos)?,
|
||||||
Token::PlusAssign => {
|
Token::PlusAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("+".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"+".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::MinusAssign => {
|
Token::MinusAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("-".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"-".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::Period => Expr::Dot(Box::new(current_lhs), Box::new(rhs)),
|
Token::Period => Expr::Dot(Box::new(current_lhs), Box::new(rhs), pos),
|
||||||
|
|
||||||
// Comparison operators default to false when passed invalid operands
|
// Comparison operators default to false when passed invalid operands
|
||||||
Token::EqualsTo => Expr::FunctionCall(
|
Token::EqualsTo => Expr::FunctionCall(
|
||||||
@ -1392,63 +1406,43 @@ fn parse_binary_op<'a>(
|
|||||||
Token::XOr => Expr::FunctionCall("^".into(), vec![current_lhs, rhs], None, pos),
|
Token::XOr => Expr::FunctionCall("^".into(), vec![current_lhs, rhs], None, pos),
|
||||||
Token::OrAssign => {
|
Token::OrAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("|".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"|".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::AndAssign => {
|
Token::AndAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("&".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"&".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::XOrAssign => {
|
Token::XOrAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("^".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"^".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::MultiplyAssign => {
|
Token::MultiplyAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("*".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"*".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::DivideAssign => {
|
Token::DivideAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("/".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"/".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::Pipe => Expr::FunctionCall("|".into(), vec![current_lhs, rhs], None, pos),
|
Token::Pipe => Expr::FunctionCall("|".into(), vec![current_lhs, rhs], None, pos),
|
||||||
Token::LeftShift => {
|
Token::LeftShift => {
|
||||||
@ -1459,27 +1453,19 @@ fn parse_binary_op<'a>(
|
|||||||
}
|
}
|
||||||
Token::LeftShiftAssign => {
|
Token::LeftShiftAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("<<".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"<<".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::RightShiftAssign => {
|
Token::RightShiftAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall(">>".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
">>".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::Ampersand => {
|
Token::Ampersand => {
|
||||||
Expr::FunctionCall("&".into(), vec![current_lhs, rhs], None, pos)
|
Expr::FunctionCall("&".into(), vec![current_lhs, rhs], None, pos)
|
||||||
@ -1487,28 +1473,20 @@ fn parse_binary_op<'a>(
|
|||||||
Token::Modulo => Expr::FunctionCall("%".into(), vec![current_lhs, rhs], None, pos),
|
Token::Modulo => Expr::FunctionCall("%".into(), vec![current_lhs, rhs], None, pos),
|
||||||
Token::ModuloAssign => {
|
Token::ModuloAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("%".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"%".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::PowerOf => Expr::FunctionCall("~".into(), vec![current_lhs, rhs], None, pos),
|
Token::PowerOf => Expr::FunctionCall("~".into(), vec![current_lhs, rhs], None, pos),
|
||||||
Token::PowerOfAssign => {
|
Token::PowerOfAssign => {
|
||||||
let lhs_copy = current_lhs.clone();
|
let lhs_copy = current_lhs.clone();
|
||||||
Expr::Assignment(
|
parse_assignment(
|
||||||
Box::new(current_lhs),
|
current_lhs,
|
||||||
Box::new(Expr::FunctionCall(
|
Expr::FunctionCall("~".into(), vec![lhs_copy, rhs], None, pos),
|
||||||
"~".into(),
|
|
||||||
vec![lhs_copy, rhs],
|
|
||||||
None,
|
|
||||||
pos,
|
pos,
|
||||||
)),
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
token => {
|
token => {
|
||||||
return Err(ParseError::new(
|
return Err(ParseError::new(
|
||||||
@ -1605,8 +1583,8 @@ fn parse_var<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Stmt, ParseE
|
|||||||
match input.peek() {
|
match input.peek() {
|
||||||
Some(&(Token::Equals, _)) => {
|
Some(&(Token::Equals, _)) => {
|
||||||
input.next();
|
input.next();
|
||||||
let initializer = parse_expr(input)?;
|
let init_value = parse_expr(input)?;
|
||||||
Ok(Stmt::Let(name, Some(Box::new(initializer)), pos))
|
Ok(Stmt::Let(name, Some(Box::new(init_value)), pos))
|
||||||
}
|
}
|
||||||
_ => Ok(Stmt::Let(name, None, pos)),
|
_ => Ok(Stmt::Let(name, None, pos)),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user