Add parsing for unit struct defintions
This commit is contained in:
parent
87455ed792
commit
7e7448fe52
@ -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}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)?;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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]";
|
||||
|
@ -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)? {
|
||||
|
Loading…
Reference in New Issue
Block a user