Continue passing tests and tweaking
This commit is contained in:
parent
81b7888920
commit
486530610b
@ -16,27 +16,6 @@ pub enum Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
pub fn range(range: Range, position: Span) -> Self {
|
|
||||||
Expression::WithoutBlock(Node::new(
|
|
||||||
Box::new(ExpressionWithoutBlock::Range(range)),
|
|
||||||
position,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn call(call_expression: CallExpression, position: Span) -> Self {
|
|
||||||
Expression::WithoutBlock(Node::new(
|
|
||||||
Box::new(ExpressionWithoutBlock::Call(call_expression)),
|
|
||||||
position,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn field_access(field_access: FieldAccess, position: Span) -> Self {
|
|
||||||
Expression::WithoutBlock(Node::new(
|
|
||||||
Box::new(ExpressionWithoutBlock::FieldAccess(field_access)),
|
|
||||||
position,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn operator(operator_expression: OperatorExpression, position: Span) -> Self {
|
pub fn operator(operator_expression: OperatorExpression, position: Span) -> Self {
|
||||||
Expression::WithoutBlock(Node::new(
|
Expression::WithoutBlock(Node::new(
|
||||||
Box::new(ExpressionWithoutBlock::Operator(operator_expression)),
|
Box::new(ExpressionWithoutBlock::Operator(operator_expression)),
|
||||||
@ -44,9 +23,175 @@ impl Expression {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#loop(r#loop: Loop, position: Span) -> Self {
|
pub fn range(start: Expression, end: Expression, position: Span) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Range(Range { start, end })),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call(invoker: Expression, arguments: Vec<Expression>, position: Span) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Call(CallExpression {
|
||||||
|
invoker,
|
||||||
|
arguments,
|
||||||
|
})),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn field_access(container: Expression, field: Node<Identifier>, position: Span) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::FieldAccess(FieldAccess {
|
||||||
|
container,
|
||||||
|
field,
|
||||||
|
})),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tuple_access(tuple: Expression, index: Node<usize>, position: Span) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::TupleAccess(TupleAccess {
|
||||||
|
tuple,
|
||||||
|
index,
|
||||||
|
})),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assignment(assignee: Expression, value: Expression, position: Span) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Operator(
|
||||||
|
OperatorExpression::Assignment { assignee, value },
|
||||||
|
)),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn comparison(
|
||||||
|
left: Expression,
|
||||||
|
operator: Node<ComparisonOperator>,
|
||||||
|
right: Expression,
|
||||||
|
position: Span,
|
||||||
|
) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Operator(
|
||||||
|
OperatorExpression::Comparison {
|
||||||
|
left,
|
||||||
|
operator,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compound_assignment(
|
||||||
|
assignee: Expression,
|
||||||
|
operator: Node<MathOperator>,
|
||||||
|
modifier: Expression,
|
||||||
|
position: Span,
|
||||||
|
) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Operator(
|
||||||
|
OperatorExpression::CompoundAssignment {
|
||||||
|
assignee,
|
||||||
|
operator,
|
||||||
|
modifier,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn math(
|
||||||
|
left: Expression,
|
||||||
|
operator: Node<MathOperator>,
|
||||||
|
right: Expression,
|
||||||
|
position: Span,
|
||||||
|
) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Math {
|
||||||
|
left,
|
||||||
|
operator,
|
||||||
|
right,
|
||||||
|
})),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn negation(expression: Expression, position: Span) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Operator(
|
||||||
|
OperatorExpression::Negation(expression),
|
||||||
|
)),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn not(expression: Expression, position: Span) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Not(
|
||||||
|
expression,
|
||||||
|
))),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn logic(
|
||||||
|
left: Expression,
|
||||||
|
operator: Node<LogicOperator>,
|
||||||
|
right: Expression,
|
||||||
|
position: Span,
|
||||||
|
) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Operator(
|
||||||
|
OperatorExpression::Logic {
|
||||||
|
left,
|
||||||
|
operator,
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error_propagation(expression: Expression, position: Span) -> Self {
|
||||||
|
Expression::WithoutBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithoutBlock::Operator(
|
||||||
|
OperatorExpression::ErrorPropagation(expression),
|
||||||
|
)),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn infinite_loop(block: Node<Block>, position: Span) -> Self {
|
||||||
Expression::WithBlock(Node::new(
|
Expression::WithBlock(Node::new(
|
||||||
Box::new(ExpressionWithBlock::Loop(r#loop)),
|
Box::new(ExpressionWithBlock::Loop(Loop::Infinite { block })),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn while_loop(condition: Expression, block: Node<Block>, position: Span) -> Self {
|
||||||
|
Expression::WithBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithBlock::Loop(Loop::While { condition, block })),
|
||||||
|
position,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn for_loop(
|
||||||
|
identifier: Node<Identifier>,
|
||||||
|
iterator: Expression,
|
||||||
|
block: Node<Block>,
|
||||||
|
position: Span,
|
||||||
|
) -> Self {
|
||||||
|
Expression::WithBlock(Node::new(
|
||||||
|
Box::new(ExpressionWithBlock::Loop(Loop::For {
|
||||||
|
identifier,
|
||||||
|
iterator,
|
||||||
|
block,
|
||||||
|
})),
|
||||||
position,
|
position,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -168,6 +313,7 @@ pub enum ExpressionWithoutBlock {
|
|||||||
FieldAccess(FieldAccess),
|
FieldAccess(FieldAccess),
|
||||||
ListIndex(ListIndex),
|
ListIndex(ListIndex),
|
||||||
Range(Range),
|
Range(Range),
|
||||||
|
TupleAccess(TupleAccess),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for ExpressionWithoutBlock {
|
impl Display for ExpressionWithoutBlock {
|
||||||
@ -183,10 +329,23 @@ impl Display for ExpressionWithoutBlock {
|
|||||||
ExpressionWithoutBlock::FieldAccess(field_access) => write!(f, "{}", field_access),
|
ExpressionWithoutBlock::FieldAccess(field_access) => write!(f, "{}", field_access),
|
||||||
ExpressionWithoutBlock::ListIndex(list_index) => write!(f, "{}", list_index),
|
ExpressionWithoutBlock::ListIndex(list_index) => write!(f, "{}", list_index),
|
||||||
ExpressionWithoutBlock::Range(range) => write!(f, "{}", range),
|
ExpressionWithoutBlock::Range(range) => write!(f, "{}", range),
|
||||||
|
ExpressionWithoutBlock::TupleAccess(tuple_access) => write!(f, "{}", tuple_access),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct TupleAccess {
|
||||||
|
pub tuple: Expression,
|
||||||
|
pub index: Node<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for TupleAccess {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}.{}", self.tuple, self.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct Range {
|
pub struct Range {
|
||||||
pub start: Expression,
|
pub start: Expression,
|
||||||
@ -213,13 +372,13 @@ impl Display for ListIndex {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct CallExpression {
|
pub struct CallExpression {
|
||||||
pub function: Expression,
|
pub invoker: Expression,
|
||||||
pub arguments: Vec<Expression>,
|
pub arguments: Vec<Expression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for CallExpression {
|
impl Display for CallExpression {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "{}(", self.function)?;
|
write!(f, "{}(", self.invoker)?;
|
||||||
|
|
||||||
for (index, argument) in self.arguments.iter().enumerate() {
|
for (index, argument) in self.arguments.iter().enumerate() {
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
@ -342,7 +501,7 @@ pub enum OperatorExpression {
|
|||||||
CompoundAssignment {
|
CompoundAssignment {
|
||||||
assignee: Expression,
|
assignee: Expression,
|
||||||
operator: Node<MathOperator>,
|
operator: Node<MathOperator>,
|
||||||
value: Expression,
|
modifier: Expression,
|
||||||
},
|
},
|
||||||
ErrorPropagation(Expression),
|
ErrorPropagation(Expression),
|
||||||
Negation(Expression),
|
Negation(Expression),
|
||||||
@ -375,7 +534,7 @@ impl Display for OperatorExpression {
|
|||||||
OperatorExpression::CompoundAssignment {
|
OperatorExpression::CompoundAssignment {
|
||||||
assignee,
|
assignee,
|
||||||
operator,
|
operator,
|
||||||
value,
|
modifier: value,
|
||||||
} => write!(f, "{} {}= {}", assignee, operator, value),
|
} => write!(f, "{} {}= {}", assignee, operator, value),
|
||||||
OperatorExpression::ErrorPropagation(expression) => write!(f, "{}?", expression),
|
OperatorExpression::ErrorPropagation(expression) => write!(f, "{}?", expression),
|
||||||
OperatorExpression::Negation(expression) => write!(f, "-{}", expression),
|
OperatorExpression::Negation(expression) => write!(f, "-{}", expression),
|
||||||
@ -552,7 +711,9 @@ impl Display for Block {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum Loop {
|
pub enum Loop {
|
||||||
Infinite(Block),
|
Infinite {
|
||||||
|
block: Node<Block>,
|
||||||
|
},
|
||||||
While {
|
While {
|
||||||
condition: Expression,
|
condition: Expression,
|
||||||
block: Node<Block>,
|
block: Node<Block>,
|
||||||
@ -560,14 +721,14 @@ pub enum Loop {
|
|||||||
For {
|
For {
|
||||||
identifier: Node<Identifier>,
|
identifier: Node<Identifier>,
|
||||||
iterator: Expression,
|
iterator: Expression,
|
||||||
block: Block,
|
block: Node<Block>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Loop {
|
impl Display for Loop {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Loop::Infinite(block) => write!(f, "loop {}", block),
|
Loop::Infinite { block } => write!(f, "loop {}", block),
|
||||||
Loop::While { condition, block } => write!(f, "while {} {}", condition, block),
|
Loop::While { condition, block } => write!(f, "while {} {}", condition, block),
|
||||||
Loop::For {
|
Loop::For {
|
||||||
identifier,
|
identifier,
|
||||||
|
@ -298,10 +298,7 @@ impl<'src> Parser<'src> {
|
|||||||
let operand = self.parse_expression(0)?;
|
let operand = self.parse_expression(0)?;
|
||||||
let position = (operator_start, self.current_position.1);
|
let position = (operator_start, self.current_position.1);
|
||||||
|
|
||||||
Ok(Expression::operator(
|
Ok(Expression::not(operand, position))
|
||||||
OperatorExpression::Not(operand),
|
|
||||||
position,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
Token::Minus => {
|
Token::Minus => {
|
||||||
self.next_token()?;
|
self.next_token()?;
|
||||||
@ -309,10 +306,7 @@ impl<'src> Parser<'src> {
|
|||||||
let operand = self.parse_expression(0)?;
|
let operand = self.parse_expression(0)?;
|
||||||
let position = (operator_start, self.current_position.1);
|
let position = (operator_start, self.current_position.1);
|
||||||
|
|
||||||
Ok(Expression::operator(
|
Ok(Expression::negation(operand, position))
|
||||||
OperatorExpression::Negation(operand),
|
|
||||||
position,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
_ => Err(ParseError::UnexpectedToken {
|
_ => Err(ParseError::UnexpectedToken {
|
||||||
actual: self.current_token.to_owned(),
|
actual: self.current_token.to_owned(),
|
||||||
@ -494,10 +488,7 @@ impl<'src> Parser<'src> {
|
|||||||
let block = self.parse_block()?;
|
let block = self.parse_block()?;
|
||||||
let position = (start_position.0, self.current_position.1);
|
let position = (start_position.0, self.current_position.1);
|
||||||
|
|
||||||
Ok(Expression::r#loop(
|
Ok(Expression::while_loop(condition, block, position))
|
||||||
Loop::While { condition, block },
|
|
||||||
position,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
_ => Err(ParseError::UnexpectedToken {
|
_ => Err(ParseError::UnexpectedToken {
|
||||||
actual: self.current_token.to_owned(),
|
actual: self.current_token.to_owned(),
|
||||||
@ -523,13 +514,7 @@ impl<'src> Parser<'src> {
|
|||||||
let value = self.parse_expression(operator_precedence)?;
|
let value = self.parse_expression(operator_precedence)?;
|
||||||
let position = (left_start, value.position().1);
|
let position = (left_start, value.position().1);
|
||||||
|
|
||||||
return Ok(Expression::operator(
|
return Ok(Expression::assignment(left, value, position));
|
||||||
OperatorExpression::Assignment {
|
|
||||||
assignee: left,
|
|
||||||
value,
|
|
||||||
},
|
|
||||||
position,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Token::PlusEqual | Token::MinusEqual = &self.current_token {
|
if let Token::PlusEqual | Token::MinusEqual = &self.current_token {
|
||||||
@ -549,22 +534,7 @@ impl<'src> Parser<'src> {
|
|||||||
OperatorExpression::CompoundAssignment {
|
OperatorExpression::CompoundAssignment {
|
||||||
assignee: left,
|
assignee: left,
|
||||||
operator,
|
operator,
|
||||||
value,
|
modifier: value,
|
||||||
},
|
|
||||||
position,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Token::Dot = &self.current_token {
|
|
||||||
self.next_token()?;
|
|
||||||
|
|
||||||
let field = self.parse_identifier()?;
|
|
||||||
let position = (left_start, self.current_position.1);
|
|
||||||
|
|
||||||
return Ok(Expression::field_access(
|
|
||||||
FieldAccess {
|
|
||||||
container: left,
|
|
||||||
field,
|
|
||||||
},
|
},
|
||||||
position,
|
position,
|
||||||
));
|
));
|
||||||
@ -576,7 +546,7 @@ impl<'src> Parser<'src> {
|
|||||||
let end = self.parse_expression(operator_precedence)?;
|
let end = self.parse_expression(operator_precedence)?;
|
||||||
let position = (left_start, end.position().1);
|
let position = (left_start, end.position().1);
|
||||||
|
|
||||||
return Ok(Expression::range(Range { start: left, end }, position));
|
return Ok(Expression::range(left, end, position));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Token::Minus | Token::Plus | Token::Star | Token::Slash | Token::Percent =
|
if let Token::Minus | Token::Plus | Token::Star | Token::Slash | Token::Percent =
|
||||||
@ -673,6 +643,27 @@ impl<'src> Parser<'src> {
|
|||||||
log::trace!("Parsing {} as postfix operator", self.current_token);
|
log::trace!("Parsing {} as postfix operator", self.current_token);
|
||||||
|
|
||||||
let expression = match &self.current_token {
|
let expression = match &self.current_token {
|
||||||
|
Token::Dot => {
|
||||||
|
self.next_token()?;
|
||||||
|
|
||||||
|
if let Token::Integer(text) = &self.current_token {
|
||||||
|
let index = text.parse::<usize>().map_err(|error| ParseError::Integer {
|
||||||
|
error,
|
||||||
|
position: self.current_position,
|
||||||
|
})?;
|
||||||
|
let index_node = Node::new(index, self.current_position);
|
||||||
|
let position = (left.position().0, self.current_position.1);
|
||||||
|
|
||||||
|
self.next_token()?;
|
||||||
|
|
||||||
|
Expression::tuple_access(left, index_node, position)
|
||||||
|
} else {
|
||||||
|
let field = self.parse_identifier()?;
|
||||||
|
let position = (left.position().0, self.current_position.1);
|
||||||
|
|
||||||
|
Expression::field_access(left, field, position)
|
||||||
|
}
|
||||||
|
}
|
||||||
Token::LeftCurlyBrace => {
|
Token::LeftCurlyBrace => {
|
||||||
let identifier = if let Some(identifier) = left.as_identifier() {
|
let identifier = if let Some(identifier) = left.as_identifier() {
|
||||||
identifier
|
identifier
|
||||||
@ -681,7 +672,6 @@ impl<'src> Parser<'src> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let name = Node::new(identifier.clone(), left.position());
|
let name = Node::new(identifier.clone(), left.position());
|
||||||
let start_left = self.current_position.0;
|
|
||||||
|
|
||||||
self.next_token()?;
|
self.next_token()?;
|
||||||
|
|
||||||
@ -700,7 +690,7 @@ impl<'src> Parser<'src> {
|
|||||||
self.next_token()?;
|
self.next_token()?;
|
||||||
} else {
|
} else {
|
||||||
return Err(ParseError::ExpectedToken {
|
return Err(ParseError::ExpectedToken {
|
||||||
expected: TokenKind::Equal,
|
expected: TokenKind::Colon,
|
||||||
actual: self.current_token.to_owned(),
|
actual: self.current_token.to_owned(),
|
||||||
position: self.current_position,
|
position: self.current_position,
|
||||||
});
|
});
|
||||||
@ -715,7 +705,7 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let position = (start_left, self.current_position.1);
|
let position = (left.position().0, self.current_position.1);
|
||||||
|
|
||||||
Expression::r#struct(StructExpression::Fields { name, fields }, position)
|
Expression::r#struct(StructExpression::Fields { name, fields }, position)
|
||||||
}
|
}
|
||||||
@ -740,17 +730,9 @@ impl<'src> Parser<'src> {
|
|||||||
|
|
||||||
let position = (left.position().0, self.current_position.1);
|
let position = (left.position().0, self.current_position.1);
|
||||||
|
|
||||||
Expression::call(
|
Expression::call(left, arguments, position)
|
||||||
CallExpression {
|
|
||||||
function: left,
|
|
||||||
arguments,
|
|
||||||
},
|
|
||||||
position,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Token::LeftSquareBrace => {
|
Token::LeftSquareBrace => {
|
||||||
let operator_start = self.current_position.0;
|
|
||||||
|
|
||||||
self.next_token()?;
|
self.next_token()?;
|
||||||
|
|
||||||
let index = self.parse_expression(0)?;
|
let index = self.parse_expression(0)?;
|
||||||
@ -791,7 +773,7 @@ impl<'src> Parser<'src> {
|
|||||||
fn parse_if(&mut self) -> Result<If, ParseError> {
|
fn parse_if(&mut self) -> Result<If, ParseError> {
|
||||||
// Assume that the "if" token has already been consumed
|
// Assume that the "if" token has already been consumed
|
||||||
|
|
||||||
let condition = self.parse_expression(0)?;
|
let condition = self.parse_expression(10)?;
|
||||||
let if_block = self.parse_block()?;
|
let if_block = self.parse_block()?;
|
||||||
|
|
||||||
if let Token::Else = self.current_token {
|
if let Token::Else = self.current_token {
|
||||||
@ -1071,24 +1053,20 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(source),
|
parse(source),
|
||||||
Ok(AbstractSyntaxTree::with_statements([
|
Ok(AbstractSyntaxTree::with_statements([
|
||||||
Statement::Expression(Expression::field_access(
|
Statement::Expression(Expression::tuple_access(
|
||||||
FieldAccess {
|
Expression::call(
|
||||||
container: Expression::call(
|
Expression::identifier(Identifier::new("Foo"), (0, 3)),
|
||||||
CallExpression {
|
vec![
|
||||||
function: Expression::identifier(Identifier::new("Foo"), (0, 0)),
|
Expression::literal(LiteralExpression::Integer(42), (4, 6)),
|
||||||
arguments: vec![
|
Expression::literal(
|
||||||
Expression::literal(LiteralExpression::Integer(42), (0, 0)),
|
LiteralExpression::String("bar".to_string()),
|
||||||
Expression::literal(
|
(8, 13)
|
||||||
LiteralExpression::String("bar".to_string()),
|
),
|
||||||
(0, 0)
|
],
|
||||||
),
|
(0, 15)
|
||||||
],
|
),
|
||||||
},
|
Node::new(0, (15, 16)),
|
||||||
(0, 0)
|
(0, 16)
|
||||||
),
|
|
||||||
field: Node::new(Identifier::new("0"), (0, 0)),
|
|
||||||
},
|
|
||||||
(0, 0)
|
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
);
|
);
|
||||||
@ -1096,7 +1074,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fields_struct_instantiation() {
|
fn fields_struct_instantiation() {
|
||||||
let source = "Foo { a = 42, b = 4.0 }";
|
let source = "Foo { a: 42, b: 4.0 }";
|
||||||
|
let mut tree = AbstractSyntaxTree::new();
|
||||||
|
|
||||||
|
if parse_into(source, &mut tree).is_err() {
|
||||||
|
println!("{:?}", tree);
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(source),
|
parse(source),
|
||||||
@ -1130,19 +1113,19 @@ mod tests {
|
|||||||
Ok(AbstractSyntaxTree::with_statements([
|
Ok(AbstractSyntaxTree::with_statements([
|
||||||
Statement::struct_definition(
|
Statement::struct_definition(
|
||||||
StructDefinition::Fields {
|
StructDefinition::Fields {
|
||||||
name: Node::new(Identifier::new("Foo"), (0, 0)),
|
name: Node::new(Identifier::new("Foo"), (7, 10)),
|
||||||
fields: vec![
|
fields: vec![
|
||||||
(
|
(
|
||||||
Node::new(Identifier::new("a"), (0, 0)),
|
Node::new(Identifier::new("a"), (13, 14)),
|
||||||
Node::new(Type::Integer, (0, 0))
|
Node::new(Type::Integer, (16, 19))
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Node::new(Identifier::new("b"), (0, 0)),
|
Node::new(Identifier::new("b"), (21, 22)),
|
||||||
Node::new(Type::Float, (0, 0))
|
Node::new(Type::Float, (24, 29))
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
(0, 0)
|
(0, 31)
|
||||||
)
|
)
|
||||||
]))
|
]))
|
||||||
);
|
);
|
||||||
@ -1166,13 +1149,11 @@ mod tests {
|
|||||||
(0, 22)
|
(0, 22)
|
||||||
),
|
),
|
||||||
Statement::Expression(Expression::call(
|
Statement::Expression(Expression::call(
|
||||||
CallExpression {
|
Expression::identifier(Identifier::new("Foo"), (23, 26)),
|
||||||
function: Expression::identifier(Identifier::new("Foo"), (23, 26)),
|
vec![
|
||||||
arguments: vec![
|
Expression::literal(LiteralExpression::Integer(1), (27, 28)),
|
||||||
Expression::literal(LiteralExpression::Integer(1), (27, 28)),
|
Expression::literal(LiteralExpression::Float(2.0), (30, 33))
|
||||||
Expression::literal(LiteralExpression::Float(2.0), (30, 33))
|
],
|
||||||
]
|
|
||||||
},
|
|
||||||
(23, 34)
|
(23, 34)
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
@ -1230,25 +1211,25 @@ mod tests {
|
|||||||
ListIndex {
|
ListIndex {
|
||||||
list: Expression::list(
|
list: Expression::list(
|
||||||
ListExpression::Ordered(vec![
|
ListExpression::Ordered(vec![
|
||||||
Expression::literal(LiteralExpression::Integer(1), (0, 0)),
|
Expression::literal(LiteralExpression::Integer(1), (1, 2)),
|
||||||
Expression::list(
|
Expression::list(
|
||||||
ListExpression::Ordered(vec![Expression::literal(
|
ListExpression::Ordered(vec![Expression::literal(
|
||||||
LiteralExpression::Integer(2),
|
LiteralExpression::Integer(2),
|
||||||
(0, 0)
|
(5, 6)
|
||||||
)]),
|
)]),
|
||||||
(0, 0)
|
(4, 7)
|
||||||
),
|
),
|
||||||
Expression::literal(LiteralExpression::Integer(3), (0, 0)),
|
Expression::literal(LiteralExpression::Integer(3), (9, 10)),
|
||||||
]),
|
]),
|
||||||
(0, 0)
|
(0, 11)
|
||||||
),
|
),
|
||||||
index: Expression::literal(LiteralExpression::Integer(1), (0, 0)),
|
index: Expression::literal(LiteralExpression::Integer(1), (12, 13)),
|
||||||
},
|
},
|
||||||
(0, 0)
|
(0, 14)
|
||||||
),
|
),
|
||||||
index: Expression::literal(LiteralExpression::Integer(0), (0, 0)),
|
index: Expression::literal(LiteralExpression::Integer(0), (15, 16)),
|
||||||
},
|
},
|
||||||
(0, 0)
|
(0, 17)
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
);
|
);
|
||||||
@ -1262,10 +1243,8 @@ mod tests {
|
|||||||
parse(source),
|
parse(source),
|
||||||
Ok(AbstractSyntaxTree::with_statements([
|
Ok(AbstractSyntaxTree::with_statements([
|
||||||
Statement::Expression(Expression::range(
|
Statement::Expression(Expression::range(
|
||||||
Range {
|
Expression::literal(LiteralExpression::Integer(0), (0, 1)),
|
||||||
start: Expression::literal(LiteralExpression::Integer(0), (0, 1)),
|
Expression::literal(LiteralExpression::Integer(42), (3, 5)),
|
||||||
end: Expression::literal(LiteralExpression::Integer(42), (3, 5)),
|
|
||||||
},
|
|
||||||
(0, 5)
|
(0, 5)
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
@ -1478,37 +1457,29 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(source),
|
parse(source),
|
||||||
Ok(AbstractSyntaxTree::with_statements([
|
Ok(AbstractSyntaxTree::with_statements([
|
||||||
Statement::Expression(Expression::r#loop(
|
Statement::Expression(Expression::while_loop(
|
||||||
Loop::While {
|
Expression::operator(
|
||||||
condition: Expression::operator(
|
OperatorExpression::Comparison {
|
||||||
OperatorExpression::Comparison {
|
left: Expression::identifier(Identifier::new("x"), (6, 7)),
|
||||||
left: Expression::identifier(Identifier::new("x"), (6, 7)),
|
operator: Node::new(ComparisonOperator::LessThan, (8, 9)),
|
||||||
operator: Node::new(ComparisonOperator::LessThan, (8, 9)),
|
right: Expression::literal(LiteralExpression::Integer(10), (10, 12)),
|
||||||
right: Expression::literal(
|
},
|
||||||
LiteralExpression::Integer(10),
|
(6, 12)
|
||||||
(10, 12)
|
),
|
||||||
|
Node::new(
|
||||||
|
Block::Sync(vec![Statement::Expression(Expression::operator(
|
||||||
|
OperatorExpression::CompoundAssignment {
|
||||||
|
assignee: Expression::identifier(Identifier::new("x"), (15, 16)),
|
||||||
|
operator: Node::new(MathOperator::Add, (17, 19)),
|
||||||
|
modifier: Expression::literal(
|
||||||
|
LiteralExpression::Integer(1),
|
||||||
|
(20, 21)
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
(6, 12)
|
(15, 21)
|
||||||
),
|
))]),
|
||||||
block: Node::new(
|
(13, 23)
|
||||||
Block::Sync(vec![Statement::Expression(Expression::operator(
|
),
|
||||||
OperatorExpression::CompoundAssignment {
|
|
||||||
assignee: Expression::identifier(
|
|
||||||
Identifier::new("x"),
|
|
||||||
(15, 16)
|
|
||||||
),
|
|
||||||
operator: Node::new(MathOperator::Add, (17, 19)),
|
|
||||||
value: Expression::literal(
|
|
||||||
LiteralExpression::Integer(1),
|
|
||||||
(20, 21)
|
|
||||||
),
|
|
||||||
},
|
|
||||||
(15, 21)
|
|
||||||
))]),
|
|
||||||
(13, 23)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
(0, 23)
|
(0, 23)
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
@ -1523,18 +1494,12 @@ mod tests {
|
|||||||
parse(source),
|
parse(source),
|
||||||
Ok(AbstractSyntaxTree::with_statements([
|
Ok(AbstractSyntaxTree::with_statements([
|
||||||
Statement::Expression(Expression::operator(
|
Statement::Expression(Expression::operator(
|
||||||
OperatorExpression::Assignment {
|
OperatorExpression::CompoundAssignment {
|
||||||
assignee: Expression::identifier(Identifier::new("a"), (0, 0)),
|
assignee: Expression::identifier(Identifier::new("a"), (0, 1)),
|
||||||
value: Expression::operator(
|
operator: Node::new(MathOperator::Add, (2, 4)),
|
||||||
OperatorExpression::Math {
|
modifier: Expression::literal(LiteralExpression::Integer(1), (5, 6)),
|
||||||
left: Expression::identifier(Identifier::new("a"), (0, 0)),
|
|
||||||
operator: Node::new(MathOperator::Add, (0, 0)),
|
|
||||||
right: Expression::literal(LiteralExpression::Integer(1), (0, 0)),
|
|
||||||
},
|
|
||||||
(0, 0)
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
(0, 0)
|
(0, 6)
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
)
|
)
|
||||||
@ -1569,13 +1534,13 @@ mod tests {
|
|||||||
Statement::Expression(Expression::block(
|
Statement::Expression(Expression::block(
|
||||||
Block::Sync(vec![Statement::Expression(Expression::operator(
|
Block::Sync(vec![Statement::Expression(Expression::operator(
|
||||||
OperatorExpression::Math {
|
OperatorExpression::Math {
|
||||||
left: Expression::literal(LiteralExpression::Integer(40), (0, 0)),
|
left: Expression::literal(LiteralExpression::Integer(40), (2, 4)),
|
||||||
operator: Node::new(MathOperator::Add, (0, 0)),
|
operator: Node::new(MathOperator::Add, (5, 6)),
|
||||||
right: Expression::literal(LiteralExpression::Integer(2), (0, 0)),
|
right: Expression::literal(LiteralExpression::Integer(2), (7, 8)),
|
||||||
},
|
},
|
||||||
(0, 0)
|
(2, 8)
|
||||||
))]),
|
))]),
|
||||||
(0, 0)
|
(0, 10)
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
)
|
)
|
||||||
@ -1649,10 +1614,10 @@ mod tests {
|
|||||||
Statement::Expression(Expression::operator(
|
Statement::Expression(Expression::operator(
|
||||||
OperatorExpression::Math {
|
OperatorExpression::Math {
|
||||||
left: Expression::literal(LiteralExpression::Integer(42), (0, 2)),
|
left: Expression::literal(LiteralExpression::Integer(42), (0, 2)),
|
||||||
operator: Node::new(MathOperator::Divide, (3, 4)),
|
operator: Node::new(MathOperator::Divide, (3, 5)),
|
||||||
right: Expression::literal(LiteralExpression::Integer(2), (5, 6)),
|
right: Expression::literal(LiteralExpression::Integer(2), (6, 8)),
|
||||||
},
|
},
|
||||||
(0, 6),
|
(0, 8),
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
);
|
);
|
||||||
@ -1687,10 +1652,10 @@ mod tests {
|
|||||||
Statement::Expression(Expression::operator(
|
Statement::Expression(Expression::operator(
|
||||||
OperatorExpression::Comparison {
|
OperatorExpression::Comparison {
|
||||||
left: Expression::literal(LiteralExpression::Integer(1), (0, 1)),
|
left: Expression::literal(LiteralExpression::Integer(1), (0, 1)),
|
||||||
operator: Node::new(ComparisonOperator::LessThanOrEqual, (2, 3)),
|
operator: Node::new(ComparisonOperator::LessThanOrEqual, (2, 4)),
|
||||||
right: Expression::literal(LiteralExpression::Integer(2), (4, 5)),
|
right: Expression::literal(LiteralExpression::Integer(2), (5, 6)),
|
||||||
},
|
},
|
||||||
(0, 5),
|
(0, 6),
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
);
|
);
|
||||||
@ -1706,10 +1671,10 @@ mod tests {
|
|||||||
Statement::Expression(Expression::operator(
|
Statement::Expression(Expression::operator(
|
||||||
OperatorExpression::Comparison {
|
OperatorExpression::Comparison {
|
||||||
left: Expression::literal(LiteralExpression::Integer(1), (0, 1)),
|
left: Expression::literal(LiteralExpression::Integer(1), (0, 1)),
|
||||||
operator: Node::new(ComparisonOperator::GreaterThanOrEqual, (2, 3)),
|
operator: Node::new(ComparisonOperator::GreaterThanOrEqual, (2, 4)),
|
||||||
right: Expression::literal(LiteralExpression::Integer(2), (4, 5)),
|
right: Expression::literal(LiteralExpression::Integer(2), (5, 6)),
|
||||||
},
|
},
|
||||||
(0, 5),
|
(0, 6),
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
);
|
);
|
||||||
@ -1763,7 +1728,7 @@ mod tests {
|
|||||||
Statement::Expression(Expression::operator(
|
Statement::Expression(Expression::operator(
|
||||||
OperatorExpression::Math {
|
OperatorExpression::Math {
|
||||||
left: Expression::literal(LiteralExpression::Integer(42), (0, 2)),
|
left: Expression::literal(LiteralExpression::Integer(42), (0, 2)),
|
||||||
operator: Node::new(MathOperator::Divide, (3, 4)),
|
operator: Node::new(MathOperator::Modulo, (3, 4)),
|
||||||
right: Expression::literal(LiteralExpression::Integer(2), (5, 6)),
|
right: Expression::literal(LiteralExpression::Integer(2), (5, 6)),
|
||||||
},
|
},
|
||||||
(0, 6),
|
(0, 6),
|
||||||
@ -1879,10 +1844,8 @@ mod tests {
|
|||||||
parse(source),
|
parse(source),
|
||||||
Ok(AbstractSyntaxTree::with_statements([
|
Ok(AbstractSyntaxTree::with_statements([
|
||||||
Statement::Expression(Expression::field_access(
|
Statement::Expression(Expression::field_access(
|
||||||
FieldAccess {
|
Expression::identifier(Identifier::new("a"), (0, 1)),
|
||||||
container: Expression::identifier(Identifier::new("a"), (0, 1)),
|
Node::new(Identifier::new("b"), (2, 3)),
|
||||||
field: Node::new(Identifier::new("b"), (2, 3)),
|
|
||||||
},
|
|
||||||
(0, 3)
|
(0, 3)
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
|
@ -238,9 +238,10 @@ impl<'src> Token<'src> {
|
|||||||
|
|
||||||
pub fn precedence(&self) -> u8 {
|
pub fn precedence(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
Token::Dot => 10,
|
Token::Identifier(_) => 10,
|
||||||
Token::LeftParenthesis | Token::LeftSquareBrace => 9,
|
Token::Dot => 9,
|
||||||
Token::Star | Token::Slash | Token::Percent => 8,
|
Token::LeftCurlyBrace | Token::LeftParenthesis | Token::LeftSquareBrace => 8,
|
||||||
|
Token::Star | Token::Slash | Token::Percent => 7,
|
||||||
Token::Minus | Token::Plus => 6,
|
Token::Minus | Token::Plus => 6,
|
||||||
Token::DoubleEqual
|
Token::DoubleEqual
|
||||||
| Token::Less
|
| Token::Less
|
||||||
@ -249,8 +250,8 @@ impl<'src> Token<'src> {
|
|||||||
| Token::GreaterEqual => 5,
|
| Token::GreaterEqual => 5,
|
||||||
Token::DoubleAmpersand => 4,
|
Token::DoubleAmpersand => 4,
|
||||||
Token::DoublePipe => 3,
|
Token::DoublePipe => 3,
|
||||||
Token::Equal | Token::MinusEqual | Token::PlusEqual => 2,
|
Token::DoubleDot => 2,
|
||||||
Token::DoubleDot => 1,
|
Token::Equal | Token::MinusEqual | Token::PlusEqual => 1,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,7 +259,8 @@ impl<'src> Token<'src> {
|
|||||||
pub fn is_left_associative(&self) -> bool {
|
pub fn is_left_associative(&self) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self,
|
self,
|
||||||
Token::DoubleAmpersand
|
Token::Dot
|
||||||
|
| Token::DoubleAmpersand
|
||||||
| Token::DoublePipe
|
| Token::DoublePipe
|
||||||
| Token::Plus
|
| Token::Plus
|
||||||
| Token::Minus
|
| Token::Minus
|
||||||
@ -269,7 +271,7 @@ impl<'src> Token<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_right_associative(&self) -> bool {
|
pub fn is_right_associative(&self) -> bool {
|
||||||
matches!(self, Token::Equal | Token::PlusEqual)
|
matches!(self, Token::Equal | Token::MinusEqual | Token::PlusEqual)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_prefix(&self) -> bool {
|
pub fn is_prefix(&self) -> bool {
|
||||||
@ -277,7 +279,10 @@ impl<'src> Token<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_postfix(&self) -> bool {
|
pub fn is_postfix(&self) -> bool {
|
||||||
matches!(self, Token::LeftParenthesis | Token::LeftSquareBrace)
|
matches!(
|
||||||
|
self,
|
||||||
|
Token::Dot | Token::LeftCurlyBrace | Token::LeftParenthesis | Token::LeftSquareBrace
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user