1
0

Add parsing for unit struct defintions

This commit is contained in:
Jeff 2024-08-13 13:54:16 -04:00
parent 87455ed792
commit 7e7448fe52
5 changed files with 89 additions and 15 deletions

View File

@ -103,6 +103,9 @@ pub enum Statement {
// A statement that always returns None. Created with a semicolon, it causes the preceding
// statement to return None. This is analagous to the semicolon or unit type in Rust.
Nil(Box<Node<Statement>>),
// Type definitions
StructDefinition(StructDefinition),
}
impl Statement {
@ -186,6 +189,7 @@ impl Statement {
UnaryOperator::Negate => Some(operand.inner.expected_type(context)?),
UnaryOperator::Not => Some(Type::Boolean),
},
Statement::StructDefinition(_) => None,
Statement::While { .. } => None,
}
}
@ -391,6 +395,9 @@ impl Display for Statement {
write!(f, "{operator}{operand}")
}
Statement::StructDefinition(struct_definition) => {
write!(f, "{struct_definition}")
}
Statement::While { condition, body } => {
write!(f, "while {condition} {body}")
}
@ -432,3 +439,16 @@ pub enum UnaryOperator {
Negate,
Not,
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum StructDefinition {
Unit { name: Node<Identifier> },
}
impl Display for StructDefinition {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
StructDefinition::Unit { name } => write!(f, "struct {name}"),
}
}
}

View File

@ -420,6 +420,7 @@ impl<'a> Analyzer<'a> {
Statement::Nil(node) => {
self.analyze_statement(node)?;
}
Statement::StructDefinition(_) => {}
Statement::UnaryOperation { operator, operand } => {
self.analyze_statement(operand)?;

View File

@ -14,7 +14,9 @@ pub mod r#type;
pub mod value;
pub mod vm;
pub use abstract_tree::{AbstractSyntaxTree, BinaryOperator, Node, Statement, UnaryOperator};
pub use abstract_tree::{
AbstractSyntaxTree, BinaryOperator, Node, Statement, StructDefinition, UnaryOperator,
};
pub use analyzer::{analyze, Analyzer, AnalyzerError};
pub use built_in_function::{BuiltInFunction, BuiltInFunctionError};
pub use context::{Context, VariableData};
@ -24,7 +26,7 @@ pub use lexer::{lex, LexError, Lexer};
pub use parser::{parse, ParseError, Parser};
pub use r#type::Type;
pub use token::{Token, TokenKind, TokenOwned};
pub use value::{Value, ValueError};
pub use value::{Struct, Value, ValueError};
pub use vm::{run, run_with_context, Vm, VmError};
pub type Span = (usize, usize);

View File

@ -13,7 +13,7 @@ use std::{
use crate::{
AbstractSyntaxTree, BinaryOperator, BuiltInFunction, DustError, Identifier, LexError, Lexer,
Node, Span, Statement, Token, TokenKind, TokenOwned, UnaryOperator, Value,
Node, Span, Statement, StructDefinition, Token, TokenKind, TokenOwned, UnaryOperator, Value,
};
/// Parses the input into an abstract syntax tree.
@ -572,20 +572,26 @@ impl<'src> Parser<'src> {
left_position,
))
}
(Token::Struct, left_position) => {
self.next_token()?;
if let Token::Identifier(_) = self.current.0 {
let name = self.parse_identifier()?;
let name_end = name.position.1;
Ok(Node::new(
Statement::StructDefinition(StructDefinition::Unit { name }),
(left_position.0, name_end),
))
} else {
todo!()
}
}
(Token::While, left_position) => {
self.next_token()?;
let condition = self.parse_statement(0)?;
if let Token::LeftCurlyBrace = self.current.0 {
} else {
return Err(ParseError::ExpectedToken {
expected: TokenKind::LeftCurlyBrace,
actual: self.current.0.to_owned(),
position: self.current.1,
});
}
let body = self.parse_block()?;
let body_end = body.position.1;
@ -772,6 +778,22 @@ impl<'src> Parser<'src> {
}
}
fn parse_identifier(&mut self) -> Result<Node<Identifier>, ParseError> {
let identifier = if let Token::Identifier(text) = &self.current.0 {
Node::new(Identifier::new(text), self.current.1)
} else {
return Err(ParseError::ExpectedToken {
expected: TokenKind::Identifier,
actual: self.current.0.to_owned(),
position: self.current.1,
});
};
self.next_token()?;
Ok(identifier)
}
fn parse_block(&mut self) -> Result<Node<Statement>, ParseError> {
let left_start = self.current.1 .0;
@ -890,10 +912,28 @@ impl Display for ParseError {
#[cfg(test)]
mod tests {
use crate::{abstract_tree::BinaryOperator, Identifier, UnaryOperator};
use crate::{abstract_tree::BinaryOperator, Identifier, StructDefinition, UnaryOperator};
use super::*;
#[test]
fn unit_struct() {
let input = "struct Foo";
assert_eq!(
parse(input),
Ok(AbstractSyntaxTree {
nodes: [Node::new(
Statement::StructDefinition(StructDefinition::Unit {
name: Node::new(Identifier::new("Foo"), (7, 10)),
}),
(0, 10)
)]
.into()
})
);
}
#[test]
fn list_index_nested() {
let input = "[1, [2], 3][1][0]";

View File

@ -11,8 +11,8 @@ use std::{
use crate::{
parse, value::ValueInner, AbstractSyntaxTree, Analyzer, BinaryOperator, BuiltInFunctionError,
Context, DustError, Identifier, Node, ParseError, Span, Statement, UnaryOperator, Value,
ValueError,
Context, DustError, Identifier, Node, ParseError, Span, Statement, StructDefinition, Type,
UnaryOperator, Value, ValueError,
};
/// Run the source code and return the result.
@ -576,6 +576,17 @@ impl Vm {
Ok(None)
}
Statement::StructDefinition(struct_definition) => {
let (type_name, r#type) = match struct_definition {
StructDefinition::Unit { name } => {
(name.inner.clone(), Type::Defined(name.inner.clone()))
}
};
self.context.set_type(type_name, r#type, node.position);
Ok(None)
}
Statement::UnaryOperation { operator, operand } => {
let position = operand.position;
let value = if let Some(value) = self.run_statement(*operand)? {