Begin fixing map property parsing
This commit is contained in:
parent
f62cb13089
commit
a61c1756f2
@ -596,11 +596,17 @@ impl<'src> Parser<'src> {
|
||||
|
||||
fn parse_infix(&mut self, left: Node<Statement>) -> Result<Node<Statement>, ParseError> {
|
||||
let left_start = left.position.0;
|
||||
let operator_precedence = self.current.0.precedence()
|
||||
- if self.current.0.is_right_associative() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
if let Token::Dot = &self.current.0 {
|
||||
self.next_token()?;
|
||||
|
||||
let right = self.parse_statement(0)?;
|
||||
let right = self.parse_statement(operator_precedence)?;
|
||||
let right_end = right.position.1;
|
||||
|
||||
if let Statement::BuiltInFunctionCall {
|
||||
@ -679,12 +685,6 @@ impl<'src> Parser<'src> {
|
||||
});
|
||||
}
|
||||
};
|
||||
let operator_precedence = self.current.0.precedence()
|
||||
- if self.current.0.is_right_associative() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
self.next_token()?;
|
||||
|
||||
@ -845,6 +845,59 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn map_property_nested() {
|
||||
let input = "{ x = { y = 42 } }.x.y";
|
||||
|
||||
assert_eq!(
|
||||
parse(input),
|
||||
Ok(AbstractSyntaxTree {
|
||||
nodes: [Node {
|
||||
inner: Statement::PropertyAccess(
|
||||
Box::new(Node {
|
||||
inner: Statement::Map(vec![(
|
||||
Node {
|
||||
inner: Statement::Identifier(Identifier::new("x")),
|
||||
position: (2, 3)
|
||||
},
|
||||
Node {
|
||||
inner: Statement::Map(vec![(
|
||||
Node {
|
||||
inner: Statement::Identifier(Identifier::new("y")),
|
||||
position: (8, 9)
|
||||
},
|
||||
Node {
|
||||
inner: Statement::Constant(Value::integer(42)),
|
||||
position: (12, 14)
|
||||
}
|
||||
)]),
|
||||
position: (6, 16)
|
||||
}
|
||||
)]),
|
||||
position: (0, 18)
|
||||
}),
|
||||
Box::new(Node {
|
||||
inner: Statement::PropertyAccess(
|
||||
Box::new(Node {
|
||||
inner: Statement::Identifier(Identifier::new("x")),
|
||||
position: (19, 20)
|
||||
}),
|
||||
Box::new(Node {
|
||||
inner: Statement::Identifier(Identifier::new("y")),
|
||||
|
||||
position: (21, 22)
|
||||
})
|
||||
),
|
||||
position: (19, 22)
|
||||
})
|
||||
),
|
||||
position: (0, 22)
|
||||
}]
|
||||
.into()
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn range() {
|
||||
let input = "0..42";
|
||||
|
@ -153,6 +153,14 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_string(&self) -> Option<&String> {
|
||||
if let ValueInner::String(string) = self.inner().as_ref() {
|
||||
Some(string)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&self, other: &Value) -> Result<Value, ValueError> {
|
||||
match (self.inner().as_ref(), other.inner().as_ref()) {
|
||||
(ValueInner::Float(left), ValueInner::Float(right)) => Ok(Value::float(left + right)),
|
||||
|
@ -495,12 +495,22 @@ impl Vm {
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(map), Statement::Identifier(identifier)) =
|
||||
(left_value.as_map(), &right.inner)
|
||||
{
|
||||
let value = map.get(identifier).cloned();
|
||||
if let Some(map) = left_value.as_map() {
|
||||
if let Statement::Identifier(identifier) = right.inner {
|
||||
let value = map.get(&identifier).cloned();
|
||||
|
||||
return Ok(value);
|
||||
return Ok(value);
|
||||
}
|
||||
|
||||
if let Some(value) = self.run_statement(*right)? {
|
||||
if let Some(string) = value.as_string() {
|
||||
let identifier = Identifier::new(string);
|
||||
|
||||
let value = map.get(&identifier).cloned();
|
||||
|
||||
return Ok(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(VmError::ExpectedIdentifierIntegerOrRange {
|
||||
@ -701,6 +711,27 @@ impl Display for VmError {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn map_property() {
|
||||
let input = "{ x = 42 }.x";
|
||||
|
||||
assert_eq!(run(input), Ok(Some(Value::integer(42))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_property_nested() {
|
||||
let input = "{ x = { y = 42 } }.x.y";
|
||||
|
||||
assert_eq!(run(input), Ok(Some(Value::integer(42))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_property_access_expression() {
|
||||
let input = "{ foobar = 42 }.('foo' + 'bar')";
|
||||
|
||||
assert_eq!(run(input), Ok(Some(Value::integer(42))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_index_range() {
|
||||
let input = "[1, 2, 3, 4, 5].1..3";
|
||||
|
Loading…
Reference in New Issue
Block a user