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
|
// 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.
|
// statement to return None. This is analagous to the semicolon or unit type in Rust.
|
||||||
Nil(Box<Node<Statement>>),
|
Nil(Box<Node<Statement>>),
|
||||||
|
|
||||||
|
// Type definitions
|
||||||
|
StructDefinition(StructDefinition),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Statement {
|
impl Statement {
|
||||||
@ -186,6 +189,7 @@ impl Statement {
|
|||||||
UnaryOperator::Negate => Some(operand.inner.expected_type(context)?),
|
UnaryOperator::Negate => Some(operand.inner.expected_type(context)?),
|
||||||
UnaryOperator::Not => Some(Type::Boolean),
|
UnaryOperator::Not => Some(Type::Boolean),
|
||||||
},
|
},
|
||||||
|
Statement::StructDefinition(_) => None,
|
||||||
Statement::While { .. } => None,
|
Statement::While { .. } => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,6 +395,9 @@ impl Display for Statement {
|
|||||||
|
|
||||||
write!(f, "{operator}{operand}")
|
write!(f, "{operator}{operand}")
|
||||||
}
|
}
|
||||||
|
Statement::StructDefinition(struct_definition) => {
|
||||||
|
write!(f, "{struct_definition}")
|
||||||
|
}
|
||||||
Statement::While { condition, body } => {
|
Statement::While { condition, body } => {
|
||||||
write!(f, "while {condition} {body}")
|
write!(f, "while {condition} {body}")
|
||||||
}
|
}
|
||||||
@ -432,3 +439,16 @@ pub enum UnaryOperator {
|
|||||||
Negate,
|
Negate,
|
||||||
Not,
|
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) => {
|
Statement::Nil(node) => {
|
||||||
self.analyze_statement(node)?;
|
self.analyze_statement(node)?;
|
||||||
}
|
}
|
||||||
|
Statement::StructDefinition(_) => {}
|
||||||
Statement::UnaryOperation { operator, operand } => {
|
Statement::UnaryOperation { operator, operand } => {
|
||||||
self.analyze_statement(operand)?;
|
self.analyze_statement(operand)?;
|
||||||
|
|
||||||
|
@ -14,7 +14,9 @@ pub mod r#type;
|
|||||||
pub mod value;
|
pub mod value;
|
||||||
pub mod vm;
|
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 analyzer::{analyze, Analyzer, AnalyzerError};
|
||||||
pub use built_in_function::{BuiltInFunction, BuiltInFunctionError};
|
pub use built_in_function::{BuiltInFunction, BuiltInFunctionError};
|
||||||
pub use context::{Context, VariableData};
|
pub use context::{Context, VariableData};
|
||||||
@ -24,7 +26,7 @@ pub use lexer::{lex, LexError, Lexer};
|
|||||||
pub use parser::{parse, ParseError, Parser};
|
pub use parser::{parse, ParseError, Parser};
|
||||||
pub use r#type::Type;
|
pub use r#type::Type;
|
||||||
pub use token::{Token, TokenKind, TokenOwned};
|
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 use vm::{run, run_with_context, Vm, VmError};
|
||||||
|
|
||||||
pub type Span = (usize, usize);
|
pub type Span = (usize, usize);
|
||||||
|
@ -13,7 +13,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractSyntaxTree, BinaryOperator, BuiltInFunction, DustError, Identifier, LexError, Lexer,
|
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.
|
/// Parses the input into an abstract syntax tree.
|
||||||
@ -572,20 +572,26 @@ impl<'src> Parser<'src> {
|
|||||||
left_position,
|
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) => {
|
(Token::While, left_position) => {
|
||||||
self.next_token()?;
|
self.next_token()?;
|
||||||
|
|
||||||
let condition = self.parse_statement(0)?;
|
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 = self.parse_block()?;
|
||||||
let body_end = body.position.1;
|
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> {
|
fn parse_block(&mut self) -> Result<Node<Statement>, ParseError> {
|
||||||
let left_start = self.current.1 .0;
|
let left_start = self.current.1 .0;
|
||||||
|
|
||||||
@ -890,10 +912,28 @@ impl Display for ParseError {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{abstract_tree::BinaryOperator, Identifier, UnaryOperator};
|
use crate::{abstract_tree::BinaryOperator, Identifier, StructDefinition, UnaryOperator};
|
||||||
|
|
||||||
use super::*;
|
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]
|
#[test]
|
||||||
fn list_index_nested() {
|
fn list_index_nested() {
|
||||||
let input = "[1, [2], 3][1][0]";
|
let input = "[1, [2], 3][1][0]";
|
||||||
|
@ -11,8 +11,8 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parse, value::ValueInner, AbstractSyntaxTree, Analyzer, BinaryOperator, BuiltInFunctionError,
|
parse, value::ValueInner, AbstractSyntaxTree, Analyzer, BinaryOperator, BuiltInFunctionError,
|
||||||
Context, DustError, Identifier, Node, ParseError, Span, Statement, UnaryOperator, Value,
|
Context, DustError, Identifier, Node, ParseError, Span, Statement, StructDefinition, Type,
|
||||||
ValueError,
|
UnaryOperator, Value, ValueError,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Run the source code and return the result.
|
/// Run the source code and return the result.
|
||||||
@ -576,6 +576,17 @@ impl Vm {
|
|||||||
|
|
||||||
Ok(None)
|
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 } => {
|
Statement::UnaryOperation { operator, operand } => {
|
||||||
let position = operand.position;
|
let position = operand.position;
|
||||||
let value = if let Some(value) = self.run_statement(*operand)? {
|
let value = if let Some(value) = self.run_statement(*operand)? {
|
||||||
|
Loading…
Reference in New Issue
Block a user