diff options
| author | Mel <einebeere@gmail.com> | 2021-12-14 00:08:13 +0100 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2021-12-28 21:46:39 +0100 |
| commit | e621f13a226d297d5368f4c294a8549a93843934 (patch) | |
| tree | 4079d2bb1a9f08e8411395e4d0ba8c87f063980c /src | |
| parent | 9d331e92045ca9098ab5f2139c80ea33e89e8ca3 (diff) | |
| download | rabbithole-e621f13a226d297d5368f4c294a8549a93843934.tar.zst rabbithole-e621f13a226d297d5368f4c294a8549a93843934.zip | |
AST restructure
Diffstat (limited to 'src')
| -rw-r--r-- | src/error.rs | 1 | ||||
| -rw-r--r-- | src/interpret/value.rs | 4 | ||||
| -rw-r--r-- | src/parse/ast/expression.rs | 117 | ||||
| -rw-r--r-- | src/parse/ast/nodes.rs | 176 | ||||
| -rw-r--r-- | src/parse/ast/statement.rs | 22 | ||||
| -rw-r--r-- | src/parse/parser.rs | 266 |
6 files changed, 380 insertions, 206 deletions
diff --git a/src/error.rs b/src/error.rs index 7493681..227a4b0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,7 @@ use crate::{interpret::walker::WalkerError, lex::token::Location, parse::parser::ParserError}; use colored::Colorize; use std::fmt::Display; + pub struct RHError { pub at: ErrorLocation, pub kind: RHErrorKind, diff --git a/src/interpret/value.rs b/src/interpret/value.rs index 6d46a0d..d9543da 100644 --- a/src/interpret/value.rs +++ b/src/interpret/value.rs @@ -1,5 +1,5 @@ use crate::{ - parse::ast::nodes::{FnNode, Identifier}, + parse::ast::nodes::{FnExpression, Identifier}, types::{bag::TypeBag, Type}, }; use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc}; @@ -104,7 +104,7 @@ impl Display for Value { #[derive(Clone, Debug)] pub struct FnValue { - pub node: FnNode, + pub node: FnExpression, pub scope: ScopeChain, } diff --git a/src/parse/ast/expression.rs b/src/parse/ast/expression.rs index d119a71..e883aaa 100644 --- a/src/parse/ast/expression.rs +++ b/src/parse/ast/expression.rs @@ -1,34 +1,45 @@ use std::fmt::{self, Display, Formatter}; -use crate::parse::ast::nodes::StrPart; +use crate::lex::token::Location; use super::nodes::{ - ArrayAccessNode, ArrayNode, BinaryOperator, BlockNode, CallNode, FnNode, Identifier, IfNode, - LoopNode, MemberAccessNode, SimpleLiteral, StrNode, UnaryOperator, + ArrayAccessExpression, ArrayExpression, BinaryOperatorNode, BlockExpression, CallExpression, + FnExpression, Identifier, IfExpression, LoopExpression, MemberAccessExpression, + SimpleLiteralNode, StrExpression, StrPartKind, UnaryOperatorNode, }; #[derive(Debug, Clone)] -pub enum Expression { +pub struct Expression { + // TODO: Sometimes this location is duplicated for no reason, + // i.e. in the UnaryExpression, since the token for the UnaryOperatorNode + // will be the same as the location for the expression... + // Can we do something about it or is some duplication fine? + pub at: Location, + pub kind: ExpressionKind, +} + +#[derive(Debug, Clone)] +pub enum ExpressionKind { Binary { left: Box<Expression>, - op: BinaryOperator, + op: BinaryOperatorNode, right: Box<Expression>, }, Unary { - op: UnaryOperator, + op: UnaryOperatorNode, right: Box<Expression>, }, - Call(Box<CallNode>), - ArrayAccess(Box<ArrayAccessNode>), - MemberAccess(Box<MemberAccessNode>), + Call(Box<CallExpression>), + ArrayAccess(Box<ArrayAccessExpression>), + MemberAccess(Box<MemberAccessExpression>), Group(Box<Expression>), - Block(Box<BlockNode>), - If(Box<IfNode>), - Loop(Box<LoopNode>), - StrLiteral(Box<StrNode>), - FnLiteral(Box<FnNode>), - ArrayLiteral(ArrayNode), - SimpleLiteral(SimpleLiteral), + Block(Box<BlockExpression>), + If(Box<IfExpression>), + Loop(Box<LoopExpression>), + StrLiteral(Box<StrExpression>), + FnLiteral(Box<FnExpression>), + ArrayLiteral(ArrayExpression), + SimpleLiteral(SimpleLiteralNode), Identifier(Identifier), } @@ -41,8 +52,8 @@ impl Display for Expression { impl Expression { pub(crate) fn nested_fmt(&self, f: &mut Formatter<'_>, depth: usize) -> fmt::Result { let pad = " ".repeat(depth); - match self { - Expression::Binary { left, op, right } => { + match self.kind { + ExpressionKind::Binary { left, op, right } => { writeln!(f, "{}Binary:", pad)?; writeln!(f, "{}- Left:", pad)?; left.nested_fmt(f, depth + 1)?; @@ -50,63 +61,63 @@ impl Expression { writeln!(f, "{}- Right:", pad)?; right.nested_fmt(f, depth + 1)?; } - Expression::Unary { op, right } => { + ExpressionKind::Unary { op, right } => { writeln!(f, "{}Unary:", pad)?; writeln!(f, "{}- Operator: {:?}", pad, op)?; writeln!(f, "{}- Right:", pad)?; right.nested_fmt(f, depth + 1)?; } - Expression::Call(node) => { + ExpressionKind::Call(expr) => { writeln!(f, "{}Function Call:", pad)?; writeln!(f, "{}- Called:", pad)?; - node.called.nested_fmt(f, depth + 1)?; - for (i, e) in node.arguments.iter().enumerate() { + expr.called.nested_fmt(f, depth + 1)?; + for (i, e) in expr.arguments.iter().enumerate() { writeln!(f, "{}- Argument {}:", pad, i)?; e.nested_fmt(f, depth + 1)?; } } - Expression::ArrayAccess(node) => { + ExpressionKind::ArrayAccess(expr) => { writeln!(f, "{}Array Access:", pad)?; writeln!(f, "{}- Array:", pad)?; - node.array.nested_fmt(f, depth + 1)?; + expr.array.nested_fmt(f, depth + 1)?; writeln!(f, "{}- Index:", pad)?; - node.index.nested_fmt(f, depth + 1)?; + expr.index.nested_fmt(f, depth + 1)?; } - Expression::MemberAccess(node) => { + ExpressionKind::MemberAccess(expr) => { writeln!(f, "{}Member Access:", pad)?; writeln!(f, "{}- Object:", pad)?; - node.object.nested_fmt(f, depth + 1)?; - writeln!(f, "{}- Member Name: {}", pad, node.member_name)?; + expr.object.nested_fmt(f, depth + 1)?; + writeln!(f, "{}- Member Name: {}", pad, expr.member_name)?; } - Expression::Group(node) => { + ExpressionKind::Group(expr) => { writeln!(f, "{}Group:", pad)?; - node.nested_fmt(f, depth + 1)?; + expr.nested_fmt(f, depth + 1)?; } - Expression::Block(block) => { - Self::block_fmt(f, block, depth + 1)?; + ExpressionKind::Block(expr) => { + Self::block_fmt(f, &expr, depth + 1)?; } - Expression::StrLiteral(node) => { + ExpressionKind::StrLiteral(expr) => { writeln!(f, "{}Str:", pad)?; - for (i, statement) in node.parts.iter().enumerate() { + for (i, statement) in expr.parts.iter().enumerate() { writeln!(f, "{}- {}:", pad, i)?; - match statement { - StrPart::Literal(literal) => { + match statement.kind { + StrPartKind::Literal(literal) => { writeln!(f, "{}{}", " ".repeat(depth + 1), literal.clone()) } - StrPart::Embed(block) => block.nested_fmt(f, depth + 1), + StrPartKind::Embed(block) => block.nested_fmt(f, depth + 1), }?; } } - Expression::FnLiteral(node) => { + ExpressionKind::FnLiteral(expr) => { write!(f, "{}Fn (", pad)?; // Write self receiver - if node.header.has_self_receiver { + if expr.header.has_self_receiver { write!(f, "self, ")?; } // Write parameters - for p in node.header.parameters.iter() { + for p in expr.header.parameters.iter() { write!( f, "{}: {}, ", @@ -119,52 +130,52 @@ impl Expression { writeln!( f, ") -> {}:", - node.header.return_type.as_ref().unwrap_or(&"_".into()) + expr.header.return_type.as_ref().unwrap_or(&"_".into()) )?; - Self::block_fmt(f, &node.body, depth + 1)?; + Self::block_fmt(f, &expr.body, depth + 1)?; } - Expression::ArrayLiteral(node) => { + ExpressionKind::ArrayLiteral(expr) => { writeln!(f, "{}Array Literal:", pad)?; - for (i, c) in node.elements.iter().enumerate() { + for (i, c) in expr.elements.iter().enumerate() { writeln!(f, "{}- Element {}:", pad, i)?; c.nested_fmt(f, depth + 1)?; } } - Expression::SimpleLiteral(literal) => { + ExpressionKind::SimpleLiteral(literal) => { writeln!(f, "{}Literal: {:?}", pad, literal)?; } - Expression::Identifier(identifier) => { + ExpressionKind::Identifier(identifier) => { writeln!(f, "{}Identifier: {:?}", pad, identifier)?; } - Expression::If(node) => { + ExpressionKind::If(expr) => { writeln!(f, "{}If:", pad)?; - for (i, c) in node.conditionals.iter().enumerate() { + for (i, c) in expr.conditionals.iter().enumerate() { writeln!(f, "{}- Condition {}:", pad, i)?; c.condition.nested_fmt(f, depth + 1)?; writeln!(f, "{}- Body {}:", pad, i)?; Self::block_fmt(f, &c.block, depth + 1)?; } - if let Some(e) = &node.else_block { + if let Some(e) = &expr.else_block { writeln!(f, "{}- Else:", pad)?; Self::block_fmt(f, e, depth + 1)?; } } - Expression::Loop(node) => { + ExpressionKind::Loop(expr) => { writeln!(f, "{}Loop:", pad)?; - if let Some(loop_condition) = &node.condition { + if let Some(loop_condition) = &expr.condition { writeln!(f, "{}- Condition:", pad)?; loop_condition.nested_fmt(f, depth + 1)?; } writeln!(f, "{}- Body:", pad)?; - Self::block_fmt(f, &node.body, depth + 1)?; + Self::block_fmt(f, &expr.body, depth + 1)?; } } Ok(()) } - fn block_fmt(f: &mut Formatter<'_>, block: &BlockNode, depth: usize) -> fmt::Result { + fn block_fmt(f: &mut Formatter<'_>, block: &BlockExpression, depth: usize) -> fmt::Result { let pad = " ".repeat(depth); writeln!(f, "{}Block:", pad)?; for (i, statement) in block.statements.iter().enumerate() { diff --git a/src/parse/ast/nodes.rs b/src/parse/ast/nodes.rs index 16d0eaa..4eff251 100644 --- a/src/parse/ast/nodes.rs +++ b/src/parse/ast/nodes.rs @@ -1,9 +1,23 @@ -use crate::lex::token::{Token, TokenKind::*}; +//! Nodes are parts of an expression, but aren't expressions themselves. +//! Example: A BinaryExpression is made out of two expressions and an operator node, +//! because an operator can't be an expression by itself. +//! +//! Nodes can also contain nested expressions. +//! This module also contains the actual expression structs for this reason, +//! although this might be changed later? + +use crate::lex::token::{Location, Token, TokenKind::*}; use super::{expression::Expression, statement::Statement}; +#[derive(Debug, Clone)] +pub struct BinaryOperatorNode { + pub at: Location, + pub kind: BinaryOperatorKind, +} + #[derive(Debug, Clone, Copy)] -pub enum BinaryOperator { +pub enum BinaryOperatorKind { Plus, Minus, Star, @@ -21,140 +35,196 @@ pub enum BinaryOperator { Dot, } -impl BinaryOperator { +impl BinaryOperatorNode { pub fn from_token(token: Token) -> Self { - match token.kind { - OpPlus => Self::Plus, - OpMinus => Self::Minus, - OpStar => Self::Star, - OpSlash => Self::Slash, - OpEq => Self::Eq, - OpNeq => Self::Neq, - OpLt => Self::Lt, - OpGt => Self::Gt, - OpLte => Self::Lte, - OpGte => Self::Gte, - OpAnd => Self::And, - OpOr => Self::Or, - Assign => Self::Assign, - ConstAssign => Self::ConstAssign, - Dot => Self::Dot, + use BinaryOperatorKind as Kind; + + let kind = match token.kind { + OpPlus => Kind::Plus, + OpMinus => Kind::Minus, + OpStar => Kind::Star, + OpSlash => Kind::Slash, + OpEq => Kind::Eq, + OpNeq => Kind::Neq, + OpLt => Kind::Lt, + OpGt => Kind::Gt, + OpLte => Kind::Lte, + OpGte => Kind::Gte, + OpAnd => Kind::And, + OpOr => Kind::Or, + Assign => Kind::Assign, + ConstAssign => Kind::ConstAssign, + Dot => Kind::Dot, _ => panic!("Can't create binary operator from '{:?}'.", token.kind), + }; + + Self { + at: token.location, + kind, } } } +#[derive(Debug, Clone)] +pub struct UnaryOperatorNode { + pub at: Location, + pub kind: UnaryOperatorKind, +} + #[derive(Debug, Clone, Copy)] -pub enum UnaryOperator { +pub enum UnaryOperatorKind { Minus, Not, } -impl UnaryOperator { +impl UnaryOperatorNode { pub fn from_token(token: Token) -> Self { - match token.kind { - OpMinus => Self::Minus, - OpNot => Self::Not, + use UnaryOperatorKind as Kind; + + let kind = match token.kind { + OpMinus => Kind::Minus, + OpNot => Kind::Not, _ => panic!("Can't create unary operator from '{:?}'.", token.kind), + }; + + Self { + at: token.location, + kind, } } } #[derive(Debug, Clone)] -pub enum SimpleLiteral { +pub struct SimpleLiteralNode { + pub at: Location, + pub kind: SimpleLiteralKind, +} + +#[derive(Debug, Clone)] +pub enum SimpleLiteralKind { Int(u32), Float(f32), Bool(bool), } -impl SimpleLiteral { +impl SimpleLiteralNode { pub fn from_token(token: Token) -> Self { - match token.kind { - Int(int) => Self::Int(int), - Float(float) => Self::Float(float), - KeywordTrue => Self::Bool(true), - KeywordFalse => Self::Bool(false), + use SimpleLiteralKind as Kind; + + let kind = match token.kind { + Int(int) => Kind::Int(int), + Float(float) => Kind::Float(float), + KeywordTrue => Kind::Bool(true), + KeywordFalse => Kind::Bool(false), _ => panic!("Can't create literal from '{:?}'.", token.kind), + }; + + Self { + at: token.location, + kind, } } } pub type Identifier = String; -// If the contraint is None the type will have to be inferred +// If the constraint is None the type will have to be inferred // during analysis. #[derive(Debug, Clone)] -pub struct TypedIdentifier { +pub struct TypedIdentifierNode { + // TODO: Add locations to other parts, not just the start of the identifier. + // i.e. make an IdentifierNode or something like that. + pub at: Location, pub identifier: Identifier, pub type_constraint: Option<Identifier>, } #[derive(Debug, Clone)] -pub struct CallNode { +pub struct CallExpression { + // TODO: Ditto. + pub at: Location, pub called: Expression, pub arguments: Vec<Expression>, } #[derive(Debug, Clone)] -pub struct ArrayAccessNode { +pub struct ArrayAccessExpression { + pub at: Location, pub array: Expression, pub index: Expression, } #[derive(Debug, Clone)] -pub struct MemberAccessNode { +pub struct MemberAccessExpression { + // TODO: Ditto. + pub at: Location, pub object: Expression, pub member_name: Identifier, } #[derive(Debug, Clone)] -pub struct StrNode { - pub parts: Vec<StrPart>, +pub struct StrExpression { + pub at: Location, + pub parts: Vec<StrPartNode>, +} + +#[derive(Debug, Clone)] +pub struct StrPartNode { + pub at: Location, + pub kind: StrPartKind, } #[derive(Debug, Clone)] -pub enum StrPart { +pub enum StrPartKind { Literal(String), Embed(Expression), } #[derive(Debug, Clone)] -pub struct FnNode { - pub header: FnHeader, - pub body: BlockNode, +pub struct FnExpression { + pub at: Location, + pub header: FnHeaderNode, + pub body: BlockExpression, } #[derive(Debug, Clone)] -pub struct FnHeader { +pub struct FnHeaderNode { + // TODO: ditto... + pub at: Location, pub has_self_receiver: bool, - pub parameters: Vec<TypedIdentifier>, + pub parameters: Vec<TypedIdentifierNode>, pub return_type: Option<Identifier>, } #[derive(Debug, Clone)] -pub struct ArrayNode { +pub struct ArrayExpression { + pub at: Location, pub elements: Vec<Expression>, } #[derive(Debug, Clone)] -pub struct IfNode { - pub conditionals: Vec<ConditionalBlock>, - pub else_block: Option<BlockNode>, +pub struct IfExpression { + pub at: Location, + pub conditionals: Vec<ConditionalBlockNode>, + pub else_block: Option<BlockExpression>, } #[derive(Debug, Clone)] -pub struct LoopNode { +pub struct LoopExpression { + pub at: Location, pub condition: Option<Expression>, - pub body: BlockNode, + pub body: BlockExpression, } #[derive(Debug, Clone)] -pub struct BlockNode { +pub struct BlockExpression { + pub at: Location, pub statements: Vec<Statement>, pub tail_expression: Option<Expression>, } #[derive(Debug, Clone)] -pub struct ConditionalBlock { +pub struct ConditionalBlockNode { + pub at: Location, pub condition: Expression, - pub block: BlockNode, + pub block: BlockExpression, } diff --git a/src/parse/ast/statement.rs b/src/parse/ast/statement.rs index 99ee0e0..7eb9978 100644 --- a/src/parse/ast/statement.rs +++ b/src/parse/ast/statement.rs @@ -1,9 +1,17 @@ use std::fmt::Display; +use crate::lex::token::Location; + use super::expression::Expression; #[derive(Debug, Clone)] -pub enum Statement { +pub struct Statement { + pub at: Location, + pub kind: StatementKind, +} + +#[derive(Debug, Clone)] +pub enum StatementKind { Expression(Expression), Print(Expression), Break(Option<Expression>), @@ -24,17 +32,17 @@ impl Statement { depth: usize, ) -> std::fmt::Result { let pad = " ".repeat(depth); - match self { - Statement::Expression(expression) => expression.nested_fmt(f, depth)?, - Statement::Print(expression) => { + match self.kind { + StatementKind::Expression(expression) => expression.nested_fmt(f, depth)?, + StatementKind::Print(expression) => { writeln!(f, "{}Print:", pad)?; expression.nested_fmt(f, depth + 1)?; } - Statement::Return(expression) => { + StatementKind::Return(expression) => { writeln!(f, "{}Return:", pad)?; expression.nested_fmt(f, depth + 1)?; } - Statement::Break(expression) => { + StatementKind::Break(expression) => { if let Some(returned_on_break) = expression { writeln!(f, "{}Break:", pad)?; returned_on_break.nested_fmt(f, depth + 1)?; @@ -42,7 +50,7 @@ impl Statement { writeln!(f, "{}Break", pad)?; } } - Statement::Continue => { + StatementKind::Continue => { writeln!(f, "{}Continue", pad)?; } } diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 76bbab7..4363bbb 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,15 +1,18 @@ use thiserror::Error; -use super::ast::expression::Expression; -use super::ast::nodes::{ArrayNode, LoopNode, StrNode, UnaryOperator}; -use super::ast::statement::Statement; +use super::ast::expression::{Expression, ExpressionKind}; +use super::ast::nodes::{ + ArrayExpression, BinaryOperatorNode, FnHeaderNode, LoopExpression, SimpleLiteralNode, + StrExpression, StrPartKind, StrPartNode, TypedIdentifierNode, UnaryOperatorNode, +}; +use super::ast::statement::{Statement, StatementKind}; use super::ast::Program; use crate::error::{ErrorLocation, RHError, RHErrorKind}; use crate::lex::lexer::Lexer; use crate::lex::token::TokenKind::{self, *}; use crate::parse::ast::nodes::{ - ArrayAccessNode, BinaryOperator, BlockNode, CallNode, ConditionalBlock, FnHeader, FnNode, - IfNode, MemberAccessNode, SimpleLiteral, StrPart, TypedIdentifier, + ArrayAccessExpression, BlockExpression, CallExpression, ConditionalBlockNode, FnExpression, + IfExpression, MemberAccessExpression, }; use crate::{check, consume, consume_if, inner, lex::token::Token, merge_token_names}; use std::iter::Peekable; @@ -47,14 +50,17 @@ impl<T: Iterator<Item = Token>> Parser<T> { } fn return_statement(&mut self) -> Result<Statement, RHError> { - consume!(self, KeywordReturn)?; + let return_token = consume!(self, KeywordReturn)?; let expression = self.expression()?; consume!(self, SemiColon)?; - Ok(Statement::Return(expression)) + Ok(Statement { + at: return_token.location, + kind: StatementKind::Return(expression), + }) } fn break_statement(&mut self) -> Result<Statement, RHError> { - consume!(self, KeywordBreak)?; + let break_token = consume!(self, KeywordBreak)?; let returned_on_break = if consume_if!(self, SemiColon).is_none() { let expression = self.expression()?; consume!(self, SemiColon)?; @@ -62,26 +68,38 @@ impl<T: Iterator<Item = Token>> Parser<T> { } else { None }; - Ok(Statement::Break(returned_on_break)) + Ok(Statement { + at: break_token.location, + kind: StatementKind::Break(returned_on_break), + }) } fn continue_statement(&mut self) -> Result<Statement, RHError> { - consume!(self, KeywordContinue)?; + let continue_token = consume!(self, KeywordContinue)?; consume!(self, SemiColon)?; - Ok(Statement::Continue) + Ok(Statement { + at: continue_token.location, + kind: StatementKind::Continue, + }) } fn print_statement(&mut self) -> Result<Statement, RHError> { - consume!(self, KeywordPrint)?; + let print_token = consume!(self, KeywordPrint)?; let expression = self.expression()?; consume!(self, SemiColon)?; - Ok(Statement::Print(expression)) + Ok(Statement { + at: print_token.location, + kind: StatementKind::Print(expression), + }) } fn expression_statement(&mut self) -> Result<Statement, RHError> { let expression = self.expression()?; consume!(self, SemiColon)?; - Ok(Statement::Expression(expression)) + Ok(Statement { + at: expression.at, + kind: StatementKind::Expression(expression), + }) } pub fn expression(&mut self) -> Result<Expression, RHError> { @@ -95,10 +113,13 @@ impl<T: Iterator<Item = Token>> Parser<T> { if let Some(op) = consume_if!(self, Assign | ConstAssign) { let right = self.assignment_expression()?; - Ok(Expression::Binary { - left: Box::new(left), - op: BinaryOperator::from_token(op), - right: Box::new(right), + Ok(Expression { + at: left.at, + kind: ExpressionKind::Binary { + left: Box::new(left), + op: BinaryOperatorNode::from_token(op), + right: Box::new(right), + }, }) } else { Ok(left) @@ -111,10 +132,13 @@ impl<T: Iterator<Item = Token>> Parser<T> { while let Some(op) = consume_if!(self, OpAnd) { let right = self.and_expression()?; - left = Expression::Binary { - left: Box::new(left), - op: BinaryOperator::from_token(op), - right: Box::new(right), + left = Expression { + at: left.at, + kind: ExpressionKind::Binary { + left: Box::new(left), + op: BinaryOperatorNode::from_token(op), + right: Box::new(right), + }, }; } @@ -127,10 +151,13 @@ impl<T: Iterator<Item = Token>> Parser<T> { while let Some(op) = consume_if!(self, OpOr) { let right = self.equality_expression()?; - left = Expression::Binary { - left: Box::new(left), - op: BinaryOperator::from_token(op), - right: Box::new(right), + left = Expression { + at: left.at, + kind: ExpressionKind::Binary { + left: Box::new(left), + op: BinaryOperatorNode::from_token(op), + right: Box::new(right), + }, }; } @@ -143,10 +170,13 @@ impl<T: Iterator<Item = Token>> Parser<T> { while let Some(op) = consume_if!(self, OpEq | OpNeq) { let right = self.comparison_expression()?; - left = Expression::Binary { - left: Box::new(left), - op: BinaryOperator::from_token(op), - right: Box::new(right), + left = Expression { + at: left.at, + kind: ExpressionKind::Binary { + left: Box::new(left), + op: BinaryOperatorNode::from_token(op), + right: Box::new(right), + }, }; } @@ -159,10 +189,13 @@ impl<T: Iterator<Item = Token>> Parser<T> { while let Some(op) = consume_if!(self, OpGt | OpGte | OpLt | OpLte) { let right = self.term_expression()?; - left = Expression::Binary { - left: Box::new(left), - op: BinaryOperator::from_token(op), - right: Box::new(right), + left = Expression { + at: left.at, + kind: ExpressionKind::Binary { + left: Box::new(left), + op: BinaryOperatorNode::from_token(op), + right: Box::new(right), + }, }; } @@ -175,10 +208,13 @@ impl<T: Iterator<Item = Token>> Parser<T> { while let Some(op) = consume_if!(self, OpPlus | OpMinus) { let right = self.factor_expression()?; - left = Expression::Binary { - left: Box::new(left), - op: BinaryOperator::from_token(op), - right: Box::new(right), + left = Expression { + at: left.at, + kind: ExpressionKind::Binary { + left: Box::new(left), + op: BinaryOperatorNode::from_token(op), + right: Box::new(right), + }, }; } @@ -191,10 +227,13 @@ impl<T: Iterator<Item = Token>> Parser<T> { while let Some(op) = consume_if!(self, OpSlash | OpStar) { let right = self.unary_expression()?; - left = Expression::Binary { - left: Box::new(left), - op: BinaryOperator::from_token(op), - right: Box::new(right), + left = Expression { + at: left.at, + kind: ExpressionKind::Binary { + left: Box::new(left), + op: BinaryOperatorNode::from_token(op), + right: Box::new(right), + }, }; } @@ -203,9 +242,14 @@ impl<T: Iterator<Item = Token>> Parser<T> { fn unary_expression(&mut self) -> Result<Expression, RHError> { let expression = if check!(self, OpPlus | OpMinus | OpNot) { - Expression::Unary { - op: UnaryOperator::from_token(self.tokens.next().unwrap()), - right: Box::new(self.unary_expression()?), + let op_token = self.tokens.next().unwrap(); + + Expression { + at: op_token.location, + kind: ExpressionKind::Unary { + op: UnaryOperatorNode::from_token(op_token), + right: Box::new(self.unary_expression()?), + }, } } else { self.postfix_expression()? @@ -218,7 +262,7 @@ impl<T: Iterator<Item = Token>> Parser<T> { let mut left = self.unit_expression()?; while let Some(token) = consume_if!(self, GroupOpen | ArrayOpen | Dot) { - match token.kind { + let kind = match token.kind { GroupOpen => { let mut arguments = Vec::new(); @@ -231,27 +275,35 @@ impl<T: Iterator<Item = Token>> Parser<T> { } } - left = Expression::Call(Box::new(CallNode { + ExpressionKind::Call(Box::new(CallExpression { + at: token.location, called: left, arguments, - })); + })) } ArrayOpen => { let index = self.expression()?; consume!(self, ArrayClose)?; - left = Expression::ArrayAccess(Box::new(ArrayAccessNode { array: left, index })) + ExpressionKind::ArrayAccess(Box::new(ArrayAccessExpression { + at: token.location, + array: left, + index, + })) } Dot => { let member_name = inner!(consume!(self, Ident(_))?, Ident); - left = Expression::MemberAccess(Box::new(MemberAccessNode { + ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { + at: token.location, object: left, member_name, })) } _ => unreachable!(), - } + }; + + left = Expression { at: left.at, kind }; } Ok(left) @@ -259,24 +311,24 @@ impl<T: Iterator<Item = Token>> Parser<T> { fn unit_expression(&mut self) -> Result<Expression, RHError> { if let Some(token) = self.tokens.peek() { - match token.kind { + let kind = match token.kind { Int(_) | Float(_) | Str(_) | KeywordTrue | KeywordFalse => { let literal = self.tokens.next().unwrap(); - Ok(Expression::SimpleLiteral(SimpleLiteral::from_token( - literal, - ))) + Ok(ExpressionKind::SimpleLiteral( + SimpleLiteralNode::from_token(literal), + )) } - Ident(_) => Ok(Expression::Identifier(inner!( + Ident(_) => Ok(ExpressionKind::Identifier(inner!( self.tokens.next().unwrap(), Ident ))), - StrOpen => Ok(Expression::StrLiteral(Box::new(self.str()?))), - GroupOpen => Ok(Expression::Group(Box::new(self.group()?))), - BlockOpen => Ok(Expression::Block(Box::new(self.generic_block()?))), - ArrayOpen => Ok(Expression::ArrayLiteral(self.array()?)), - KeywordFn => Ok(Expression::FnLiteral(Box::new(self.function()?))), - KeywordIf => Ok(Expression::If(Box::new(self.conditional()?))), - KeywordLoop => Ok(Expression::Loop(Box::new(self.repeating()?))), + StrOpen => Ok(ExpressionKind::StrLiteral(Box::new(self.str()?))), + GroupOpen => Ok(ExpressionKind::Group(Box::new(self.group()?))), + BlockOpen => Ok(ExpressionKind::Block(Box::new(self.generic_block()?))), + ArrayOpen => Ok(ExpressionKind::ArrayLiteral(self.array()?)), + KeywordFn => Ok(ExpressionKind::FnLiteral(Box::new(self.function()?))), + KeywordIf => Ok(ExpressionKind::If(Box::new(self.conditional()?))), + KeywordLoop => Ok(ExpressionKind::Loop(Box::new(self.repeating()?))), _ => Err(parser_error( ErrorLocation::Specific(token.location), ParserError::UnexpectedToken { @@ -298,7 +350,12 @@ impl<T: Iterator<Item = Token>> Parser<T> { ), }, )), - } + }?; + + Ok(Expression { + at: token.location, + kind, + }) } else { Err(parser_error( ErrorLocation::Eof, @@ -317,8 +374,8 @@ impl<T: Iterator<Item = Token>> Parser<T> { Ok(expression) } - fn array(&mut self) -> Result<ArrayNode, RHError> { - consume!(self, ArrayOpen)?; + fn array(&mut self) -> Result<ArrayExpression, RHError> { + let array_token = consume!(self, ArrayOpen)?; let mut elements = Vec::new(); loop { @@ -330,39 +387,48 @@ impl<T: Iterator<Item = Token>> Parser<T> { } consume!(self, ArrayClose)?; - Ok(ArrayNode { elements }) + Ok(ArrayExpression { + at: array_token.location, + elements, + }) } - fn str(&mut self) -> Result<StrNode, RHError> { + fn str(&mut self) -> Result<StrExpression, RHError> { let mut parts = Vec::new(); - consume!(self, StrOpen)?; + let str_token = consume!(self, StrOpen)?; loop { let token = self.tokens.next().expect("Unclosed str."); - let part = match token.kind { - Str(literal) => StrPart::Literal(literal), + let part_kind = match token.kind { + Str(literal) => StrPartKind::Literal(literal), StrEmbed(code) => { let embed_lexer = Lexer::new(&code); let mut embed_parser = Parser::new(embed_lexer); let node = embed_parser.expression()?; - StrPart::Embed(node) + StrPartKind::Embed(node) } StrClose => break, _ => unreachable!(), }; - parts.push(part); + parts.push(StrPartNode { + at: token.location, + kind: part_kind, + }); } - Ok(StrNode { parts }) + Ok(StrExpression { + at: str_token.location, + parts, + }) } - fn function(&mut self) -> Result<FnNode, RHError> { - consume!(self, KeywordFn)?; + fn function(&mut self) -> Result<FnExpression, RHError> { + let fn_token = consume!(self, KeywordFn)?; let header = { let has_self_receiver = if consume_if!(self, KeywordSelf).is_some() { @@ -382,9 +448,10 @@ impl<T: Iterator<Item = Token>> Parser<T> { None }; - parameters.push(TypedIdentifier { + parameters.push(TypedIdentifierNode { identifier: parameter_name, type_constraint, + at: token.location, }); if consume_if!(self, Comma).is_none() { @@ -398,29 +465,36 @@ impl<T: Iterator<Item = Token>> Parser<T> { None }; - FnHeader { + FnHeaderNode { has_self_receiver, parameters, return_type, + at: fn_token.location, } }; let body = self.generic_block()?; - Ok(FnNode { header, body }) + Ok(FnExpression { + header, + body, + // Duplicated ^ + at: fn_token.location, + }) } - fn conditional(&mut self) -> Result<IfNode, RHError> { - consume!(self, KeywordIf)?; + fn conditional(&mut self) -> Result<IfExpression, RHError> { + let if_token = consume!(self, KeywordIf)?; let mut conditionals = Vec::new(); let if_condition = self.expression()?; let if_block = self.generic_block()?; - conditionals.push(ConditionalBlock { + conditionals.push(ConditionalBlockNode { condition: if_condition, block: if_block, + at: if_condition.at, }); // Elifs @@ -428,9 +502,10 @@ impl<T: Iterator<Item = Token>> Parser<T> { let elif_condition = self.expression()?; let elif_block = self.generic_block()?; - conditionals.push(ConditionalBlock { + conditionals.push(ConditionalBlockNode { condition: elif_condition, block: elif_block, + at: elif_condition.at, }); } @@ -440,14 +515,15 @@ impl<T: Iterator<Item = Token>> Parser<T> { None }; - Ok(IfNode { + Ok(IfExpression { conditionals, else_block, + at: if_token.location, }) } - fn repeating(&mut self) -> Result<LoopNode, RHError> { - consume!(self, KeywordLoop)?; + fn repeating(&mut self) -> Result<LoopExpression, RHError> { + let loop_token = consume!(self, KeywordLoop)?; let condition = if consume_if!(self, KeywordIf).is_some() { let expression = self.expression()?; @@ -457,11 +533,15 @@ impl<T: Iterator<Item = Token>> Parser<T> { }; let body = self.generic_block()?; - Ok(LoopNode { body, condition }) + Ok(LoopExpression { + body, + condition, + at: loop_token.location, + }) } - fn generic_block(&mut self) -> Result<BlockNode, RHError> { - consume!(self, BlockOpen)?; + fn generic_block(&mut self) -> Result<BlockExpression, RHError> { + let block_token = consume!(self, BlockOpen)?; let mut statements = Vec::new(); let mut tail_expression = None; @@ -478,7 +558,10 @@ impl<T: Iterator<Item = Token>> Parser<T> { _ => { let expression = self.expression()?; if consume_if!(self, SemiColon).is_some() { - statements.push(Statement::Expression(expression)); + statements.push(Statement { + kind: StatementKind::Expression(expression), + at: expression.at, + }); } else { tail_expression = Some(expression); break; @@ -489,9 +572,10 @@ impl<T: Iterator<Item = Token>> Parser<T> { consume!(self, BlockClose)?; - Ok(BlockNode { + Ok(BlockExpression { statements, tail_expression, + at: block_token.location, }) } } |
