From a4980b8dbf1394c2b302f1de7c72d2264426b86e Mon Sep 17 00:00:00 2001 From: Mel Date: Wed, 20 Oct 2021 22:15:08 +0200 Subject: Statement parsing. --- src/parse/ast/expression.rs | 127 ++++++++++++++++++++++++++++++++++++++++++++ src/parse/ast/mod.rs | 21 ++++++++ src/parse/ast/statement.rs | 39 ++++++++++++++ src/parse/ast/value.rs | 106 ++++++++++++++++++++++++++++++++++++ 4 files changed, 293 insertions(+) create mode 100644 src/parse/ast/expression.rs create mode 100644 src/parse/ast/mod.rs create mode 100644 src/parse/ast/statement.rs create mode 100644 src/parse/ast/value.rs (limited to 'src/parse/ast') diff --git a/src/parse/ast/expression.rs b/src/parse/ast/expression.rs new file mode 100644 index 0000000..8563492 --- /dev/null +++ b/src/parse/ast/expression.rs @@ -0,0 +1,127 @@ +use std::fmt::{self, Display, Formatter}; + +use super::value::{ + BinaryOperator, Block, ConditionalBlock, FnHeader, Identifier, Literal, UnaryOperator, +}; + +#[derive(Debug)] +pub enum Expression { + Binary { + left: Box, + op: BinaryOperator, + right: Box, + }, + Unary { + op: UnaryOperator, + right: Box, + }, + Group(Box), + Block(Box), + Fn { + header: FnHeader, + body: Box, + }, + If { + conditionals: Vec, + else_block: Option>, + }, + Literal(Literal), + Identifier(Identifier), +} + +impl Display for Expression { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + self.nested_fmt(f, 0) + } +} + +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 } => { + writeln!(f, "{}Binary:", pad)?; + writeln!(f, "{}- Left:", pad)?; + left.nested_fmt(f, depth + 1)?; + writeln!(f, "{}- Operator: {:?}", pad, op)?; + writeln!(f, "{}- Right:", pad)?; + right.nested_fmt(f, depth + 1)?; + } + Expression::Unary { op, right } => { + writeln!(f, "{}Unary:", pad)?; + writeln!(f, "{}- Operator: {:?}", pad, op)?; + writeln!(f, "{}- Right:", pad)?; + right.nested_fmt(f, depth + 1)?; + } + Expression::Group(node) => { + writeln!(f, "{}Group:", pad)?; + node.nested_fmt(f, depth + 1)?; + } + Expression::Block(block) => { + Self::block_fmt(f, block, depth + 1)?; + } + Expression::Fn { header, body } => { + write!(f, "{}Fn (", pad)?; + + // Write self receiver + if header.has_self_receiver { + write!(f, "self, ")?; + } + + // Write parameters + for p in header.parameters.iter() { + write!( + f, + "{}: {}, ", + p.identifier, + p.type_constraint.as_ref().unwrap_or(&"_".into()) + )?; + } + + // Write return type + writeln!( + f, + ") -> {}:", + header.return_type.as_ref().unwrap_or(&"_".into()) + )?; + Self::block_fmt(f, body, depth + 1)?; + } + Expression::Literal(literal) => { + writeln!(f, "{}Literal: {:?}", pad, literal)?; + } + Expression::Identifier(identifier) => { + writeln!(f, "{}Identifier: {:?}", pad, identifier)?; + } + Expression::If { conditionals, else_block } => { + writeln!(f, "{}If:", pad)?; + for (i, c) in 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) = else_block { + writeln!(f, "{}- Else:", pad)?; + Self::block_fmt(f, e, depth + 1)?; + } + }, + } + + Ok(()) + } + + fn block_fmt(f: &mut Formatter<'_>, block: &Block, depth: usize) -> fmt::Result { + let pad = " ".repeat(depth); + writeln!(f, "{}Block:", pad)?; + for (i, statement) in block.statements.iter().enumerate() { + writeln!(f, "{}- {}:", pad, i)?; + statement.nested_fmt(f, depth + 1)?; + } + if let Some(tail_expression) = &block.tail_expression { + writeln!(f, "{}- Tail:", pad)?; + tail_expression.nested_fmt(f, depth + 1)?; + } + + Ok(()) + } +} diff --git a/src/parse/ast/mod.rs b/src/parse/ast/mod.rs new file mode 100644 index 0000000..257675f --- /dev/null +++ b/src/parse/ast/mod.rs @@ -0,0 +1,21 @@ +use std::fmt::Display; + +use self::statement::Statement; + +pub mod expression; +pub mod statement; +pub mod value; + +#[derive(Debug)] +pub struct Program { + pub statements: Vec, +} + +impl Display for Program { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for statement in self.statements.iter() { + writeln!(f, "{}", statement)?; + } + Ok(()) + } +} diff --git a/src/parse/ast/statement.rs b/src/parse/ast/statement.rs new file mode 100644 index 0000000..eec589e --- /dev/null +++ b/src/parse/ast/statement.rs @@ -0,0 +1,39 @@ +use std::fmt::Display; + +use super::expression::Expression; + +#[derive(Debug)] +pub enum Statement { + Expression(Expression), + Print(Expression), + Return(Expression), +} + +impl Display for Statement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.nested_fmt(f, 0) + } +} + +impl Statement { + pub(crate) fn nested_fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + depth: usize, + ) -> std::fmt::Result { + let pad = " ".repeat(depth); + match self { + Statement::Expression(expression) => expression.nested_fmt(f, depth)?, + Statement::Print(expression) => { + writeln!(f, "{}Print:", pad)?; + expression.nested_fmt(f, depth + 1)?; + } + Statement::Return(expression) => { + writeln!(f, "{}Return:", pad)?; + expression.nested_fmt(f, depth + 1)?; + } + } + + Ok(()) + } +} diff --git a/src/parse/ast/value.rs b/src/parse/ast/value.rs new file mode 100644 index 0000000..263cb58 --- /dev/null +++ b/src/parse/ast/value.rs @@ -0,0 +1,106 @@ +use crate::lex::token::{Token, TokenVariant::*}; + +use super::{expression::Expression, statement::Statement}; + +#[derive(Debug)] +pub enum BinaryOperator { + Plus, + Minus, + Star, + Slash, + Eq, + Neq, + Gt, + Gte, + Lt, + Lte, + Assign, + ConstAssign, + Dot, +} + +impl BinaryOperator { + pub fn from_token(token: Token) -> Self { + match token.variant { + 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, + Assign => Self::Assign, + ConstAssign => Self::ConstAssign, + Dot => Self::Dot, + _ => panic!("Can't create binary operator from '{:?}'.", token.variant) + } + } +} + +#[derive(Debug)] +pub enum UnaryOperator { + Plus, + Minus, + Not, +} + +impl UnaryOperator { + pub fn from_token(token: Token) -> Self { + match token.variant { + OpPlus => Self::Plus, + OpMinus => Self::Minus, + OpNot => Self::Not, + _ => panic!("Can't create unary operator from '{:?}'.", token.variant) + } + } +} + +#[derive(Debug)] +pub enum Literal { + Int(u32), + Float(f32), + Str(String), +} + +impl Literal { + pub fn from_token(token: Token) -> Self { + match token.variant { + Int(int) => Self::Int(int), + Float(float) => Self::Float(float), + Str(string) => Self::Str(string), + _ => panic!("Can't create literal from '{:?}'.", token.variant) + } + } +} + +pub type Identifier = String; + +// If the contraint is None the type will have to be inferred +// during analysis. +#[derive(Debug)] +pub struct TypedIdentifier { + pub identifier: Identifier, + pub type_constraint: Option, +} + +#[derive(Debug)] +pub struct FnHeader { + pub has_self_receiver: bool, + pub parameters: Vec, + pub return_type: Option, +} + +#[derive(Debug)] +pub struct Block { + pub statements: Vec, + pub tail_expression: Option, +} + +#[derive(Debug)] +pub struct ConditionalBlock { + pub condition: Expression, + pub block: Block, +} -- cgit 1.4.1