Skip to content

Commit

Permalink
🚧 WIP
Browse files Browse the repository at this point in the history
semver: chore
  • Loading branch information
Somfic committed Nov 1, 2024
1 parent fdb5b4e commit 4f4db62
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 85 deletions.
102 changes: 65 additions & 37 deletions src/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ pub enum Symbol<'de> {
}

#[derive(Debug, Clone)]
pub enum Statement<'de> {
pub struct Statement<'de> {
pub value: StatementValue<'de>,
pub span: miette::SourceSpan,
}

#[derive(Debug, Clone)]
pub enum StatementValue<'de> {
Block(Vec<Statement<'de>>),
Expression(Expression<'de>),
Assignment {
Expand All @@ -27,7 +33,6 @@ pub enum Statement<'de> {
Function {
header: FunctionHeader<'de>,
body: Expression<'de>,
explicit_return_type: Option<Type<'de>>,
},
Trait {
name: Cow<'de, str>,
Expand All @@ -47,40 +52,6 @@ pub struct Expression<'de> {
pub span: miette::SourceSpan,
}

impl<'de> Expression<'de> {
pub fn at(span: miette::SourceSpan, value: ExpressionValue<'de>) -> Self {
Self { value, span }
}

pub fn at_multiple(
spans: Vec<impl Into<miette::SourceSpan>>,
value: ExpressionValue<'de>,
) -> Expression<'de> {
let spans = spans.into_iter().map(|s| s.into()).collect::<Vec<_>>();

let start = spans
.iter()
.min_by_key(|s| s.offset())
.map(|s| s.offset())
.unwrap_or(0);

// Go through all the spans and find the one with the highest end offset
let end = spans
.iter()
.max_by_key(|s| s.offset() + s.len())
.map(|s| s.offset() + s.len())
.unwrap_or(0);

let span = miette::SourceSpan::new(start.into(), end - start);

Expression::at(span, value)
}

pub fn label(&self, text: impl Into<String>) -> miette::LabeledSpan {
miette::LabeledSpan::at(self.span, text.into())
}
}

#[derive(Debug, Clone)]
pub enum ExpressionValue<'de> {
Primitive(Primitive<'de>),
Expand Down Expand Up @@ -113,6 +84,7 @@ pub enum ExpressionValue<'de> {
pub struct FunctionHeader<'de> {
pub name: Cow<'de, str>,
pub parameters: Vec<ParameterDeclaration<'de>>,
pub explicit_return_type: Option<Type<'de>>,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -168,7 +140,13 @@ pub enum UnaryOperator {
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Type<'de> {
pub struct Type<'de> {
pub value: TypeValue<'de>,
pub span: SourceSpan,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TypeValue<'de> {
Unit,
Boolean,
Integer,
Expand All @@ -179,3 +157,53 @@ pub enum Type<'de> {
Collection(Box<Type<'de>>),
Set(Box<Type<'de>>),
}

pub trait Spannable<'de>: Sized {
type Value;

fn at(span: miette::SourceSpan, value: Self::Value) -> Self;

fn at_multiple(spans: Vec<impl Into<miette::SourceSpan>>, value: Self::Value) -> Self {
let spans = spans.into_iter().map(|s| s.into()).collect::<Vec<_>>();

let start = spans
.iter()
.min_by_key(|s| s.offset())
.map(|s| s.offset())
.unwrap_or(0);

let end = spans
.iter()
.max_by_key(|s| s.offset() + s.len())
.map(|s| s.offset() + s.len())
.unwrap_or(0);

let span = miette::SourceSpan::new(start.into(), end - start);

Self::at(span, value)
}
}

impl<'de> Spannable<'de> for Expression<'de> {
type Value = ExpressionValue<'de>;

fn at(span: miette::SourceSpan, value: Self::Value) -> Self {
Self { value, span }
}
}

impl<'de> Spannable<'de> for Statement<'de> {
type Value = StatementValue<'de>;

fn at(span: miette::SourceSpan, value: Self::Value) -> Self {
Self { value, span }
}
}

impl<'de> Spannable<'de> for Type<'de> {
type Value = TypeValue<'de>;

fn at(span: miette::SourceSpan, value: Self::Value) -> Self {
Self { value, span }
}
}
2 changes: 1 addition & 1 deletion src/parser/expression/binary.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::parser::{
ast::{BinaryOperator, Expression, ExpressionValue},
ast::{BinaryOperator, Expression, ExpressionValue, Spannable},
lookup::BindingPower,
Parser,
};
Expand Down
2 changes: 1 addition & 1 deletion src/parser/expression/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use miette::Result;

use super::{
ast::{Expression, ExpressionValue},
ast::{Expression, ExpressionValue, Spannable},
Parser,
};
use crate::{lexer::TokenKind, parser::lookup::BindingPower};
Expand Down
2 changes: 1 addition & 1 deletion src/parser/expression/primitive.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
lexer::{TokenKind, TokenValue},
parser::{
ast::{Expression, ExpressionValue, Primitive},
ast::{Expression, ExpressionValue, Primitive, Spannable},
Parser,
},
};
Expand Down
2 changes: 1 addition & 1 deletion src/parser/expression/unary.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
lexer::TokenKind,
parser::{
ast::{Expression, ExpressionValue, UnaryOperator},
ast::{Expression, ExpressionValue, Spannable, UnaryOperator},
lookup::BindingPower,
Parser,
},
Expand Down
8 changes: 4 additions & 4 deletions src/parser/lookup.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{
ast::{Expression, ExpressionValue, Primitive, Statement, Type},
ast::{Expression, ExpressionValue, Primitive, Spannable, Statement, StatementValue, Type},
expression, statement, typing, Parser,
};
use crate::lexer::{TokenKind, TokenValue};
Expand Down Expand Up @@ -287,9 +287,9 @@ fn block<'de>(parser: &mut Parser<'de>) -> Result<Expression<'de>> {
}

let return_value = if last_is_return {
match statements.last() {
Some(Statement::Expression(_)) => match statements.pop() {
Some(Statement::Expression(expression)) => expression,
match statements.last().map(|s| &s.value) {
Some(StatementValue::Expression(_)) => match statements.pop().map(|s| s.value) {
Some(StatementValue::Expression(expression)) => expression,
_ => unreachable!(),
},
_ => Expression::at(
Expand Down
7 changes: 5 additions & 2 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::lexer::Lexer;
use ast::{Statement, Symbol};
use ast::{Spannable, Statement, StatementValue, Symbol};
use lookup::Lookup;
use miette::Result;

Expand Down Expand Up @@ -29,6 +29,9 @@ impl<'de> Parser<'de> {
statements.push(statement::parse(self, false)?);
}

Ok(Symbol::Statement(Statement::Block(statements)))
Ok(Symbol::Statement(Statement::at_multiple(
statements.iter().map(|s| s.span).collect(),
StatementValue::Block(statements),
)))
}
}
66 changes: 37 additions & 29 deletions src/parser/statement.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use super::{
ast::{
EnumMemberDeclaration, FunctionHeader, ParameterDeclaration, Statement,
StructMemberDeclaration,
EnumMemberDeclaration, FunctionHeader, ParameterDeclaration, Spannable, Statement,
StatementValue, StructMemberDeclaration,
},
expression,
lookup::BindingPower,
statement, typing, Parser,
};
use crate::lexer::{TokenKind, TokenValue};
use crate::lexer::{Token, TokenKind, TokenValue};
use miette::{Context, Result};

pub fn parse<'de>(parser: &mut Parser<'de>, optional_semicolon: bool) -> Result<Statement<'de>> {
Expand All @@ -33,30 +33,35 @@ pub fn parse<'de>(parser: &mut Parser<'de>, optional_semicolon: bool) -> Result<
.wrap_err("while parsing a statement")?;

if !optional_semicolon {
parser
let token = parser
.lexer
.expect(
TokenKind::Semicolon,
"expected a semicolon at the end of an expression",
)
.wrap_err(format!("while parsing for {}", token_kind))?;
}

Statement::Expression(expression)
Statement::at_multiple(
vec![expression.span, token.span],
StatementValue::Expression(expression),
)
} else {
Statement::at(expression.span, StatementValue::Expression(expression))
}
}
};

Ok(statement)
}

pub fn let_<'de>(parser: &mut Parser<'de>) -> Result<Statement<'de>> {
parser
let token = parser
.lexer
.expect(TokenKind::Let, "expected a let keyword")?;
let identifier = parser
.lexer
.expect(TokenKind::Identifier, "expected a variable name")?;
let identifier = match identifier.value {
let name = match identifier.value {
TokenValue::Identifier(identifier) => identifier,
_ => unreachable!(),
};
Expand All @@ -65,22 +70,25 @@ pub fn let_<'de>(parser: &mut Parser<'de>) -> Result<Statement<'de>> {
.expect(TokenKind::Equal, "expected an equal sign")?;
let expression = expression::parse(parser, BindingPower::None)?;

Ok(Statement::Assignment {
name: identifier,
value: expression,
})
Ok(Statement::at_multiple(
vec![token.span, identifier.span],
StatementValue::Assignment {
name,
value: expression,
},
))
}

pub fn struct_<'de>(parser: &mut Parser<'de>) -> Result<Statement<'de>> {
parser
let token = parser
.lexer
.expect(TokenKind::Struct, "expected a struct keyword")?;

let identifier = parser
.lexer
.expect(TokenKind::Identifier, "expected a struct name")?;

let identifier = match identifier.value {
let name = match identifier.value {
TokenValue::Identifier(identifier) => identifier,
_ => unreachable!(),
};
Expand Down Expand Up @@ -123,22 +131,22 @@ pub fn struct_<'de>(parser: &mut Parser<'de>) -> Result<Statement<'de>> {
.lexer
.expect(TokenKind::Semicolon, "expected a semicolon")?;

Ok(Statement::Struct {
name: identifier,
fields,
})
Ok(Statement::at_multiple(
vec![token.span, identifier.span],
StatementValue::Struct { name, fields },
))
}

pub fn enum_<'de>(parser: &mut Parser<'de>) -> Result<Statement<'de>> {
parser
let token = parser
.lexer
.expect(TokenKind::Enum, "expected an enum keyword")?;

let identifier = parser
.lexer
.expect(TokenKind::Identifier, "expected an enum name")?;

let identifier = match identifier.value {
let name = match identifier.value {
TokenValue::Identifier(identifier) => identifier,
_ => unreachable!(),
};
Expand Down Expand Up @@ -177,22 +185,22 @@ pub fn enum_<'de>(parser: &mut Parser<'de>) -> Result<Statement<'de>> {
.lexer
.expect(TokenKind::Semicolon, "expected a semicolon")?;

Ok(Statement::Enum {
name: identifier,
variants,
})
Ok(Statement::at_multiple(
vec![token.span, identifier.span],
StatementValue::Enum { name, variants },
))
}

pub fn function_<'de>(parser: &mut Parser<'de>) -> Result<Statement<'de>> {
parser
let token = parser
.lexer
.expect(TokenKind::Function, "expected a function keyword")?;

let identifier = parser
.lexer
.expect(TokenKind::Identifier, "expected function name")?;

let identifier = match identifier.value {
let name = match identifier.value {
TokenValue::Identifier(identifier) => identifier,
_ => unreachable!(),
};
Expand Down Expand Up @@ -247,13 +255,13 @@ pub fn function_<'de>(parser: &mut Parser<'de>) -> Result<Statement<'de>> {

let body = expression::parse(parser, BindingPower::None)?;

Ok(Statement::Function {
Ok(Statement::at_multiple(vec![], value)::Function {
header: FunctionHeader {
name: identifier,
name,
parameters,
explicit_return_type,
},
body,
explicit_return_type,
})
}

Expand Down
Loading

0 comments on commit 4f4db62

Please sign in to comment.