aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/error.rs1
-rw-r--r--src/interpret/value.rs4
-rw-r--r--src/parse/ast/expression.rs117
-rw-r--r--src/parse/ast/nodes.rs176
-rw-r--r--src/parse/ast/statement.rs22
-rw-r--r--src/parse/parser.rs266
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,
})
}
}