From 692f1145cd11a6949c6a9dc6ea63431c7a09691f Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 7 Aug 2024 10:41:27 -0400 Subject: [PATCH] Implement lexing for boolean values --- dust-lang/src/abstract_tree.rs | 22 ++++++++++--------- dust-lang/src/analyzer.rs | 3 +++ dust-lang/src/lex.rs | 39 ++++++++++++++++++++++++++++++++-- dust-lang/src/token.rs | 4 ++++ dust-lang/src/vm.rs | 35 +++++++++++++++++++++++++----- 5 files changed, 86 insertions(+), 17 deletions(-) diff --git a/dust-lang/src/abstract_tree.rs b/dust-lang/src/abstract_tree.rs index e321bb1..36a155b 100644 --- a/dust-lang/src/abstract_tree.rs +++ b/dust-lang/src/abstract_tree.rs @@ -35,6 +35,7 @@ pub enum Statement { // Expressions Add(Box, Box), + BuiltInValue(Box), PropertyAccess(Box, Box), List(Vec), Multiply(Box, Box), @@ -50,6 +51,7 @@ impl Statement { match self { Statement::Add(left, _) => left.statement.expected_type(variables), Statement::Assign(_, _) => None, + Statement::BuiltInValue(reserved) => reserved.statement.expected_type(variables), Statement::Constant(value) => Some(value.r#type(variables)), Statement::Identifier(identifier) => variables .get(identifier) @@ -58,8 +60,7 @@ impl Statement { Statement::Multiply(left, _) => left.statement.expected_type(variables), Statement::PropertyAccess(_, _) => None, Statement::ReservedIdentifier(reserved) => match reserved { - ReservedIdentifier::IsEven => Some(Type::Boolean), - ReservedIdentifier::IsOdd => Some(Type::Boolean), + ReservedIdentifier::IsEven | ReservedIdentifier::IsOdd => Some(Type::Boolean), ReservedIdentifier::Length => Some(Type::Integer), }, } @@ -69,23 +70,24 @@ impl Statement { impl Display for Statement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Statement::Assign(left, right) => write!(f, "{} = {}", left, right), - Statement::Add(left, right) => write!(f, "{} + {}", left, right), - Statement::PropertyAccess(left, right) => write!(f, "{}.{}", left, right), + Statement::Assign(left, right) => write!(f, "{left} = {right}"), + Statement::Add(left, right) => write!(f, "{left} + {right}"), + Statement::BuiltInValue(reserved) => write!(f, "{reserved}"), + Statement::PropertyAccess(left, right) => write!(f, "{left}.{right}"), Statement::List(nodes) => { write!(f, "[")?; for (i, node) in nodes.iter().enumerate() { if i > 0 { write!(f, ", ")?; } - write!(f, "{}", node)?; + write!(f, "{node}")?; } write!(f, "]") } - Statement::Multiply(left, right) => write!(f, "{} * {}", left, right), - Statement::Constant(value) => write!(f, "{}", value), - Statement::Identifier(identifier) => write!(f, "{}", identifier), - Statement::ReservedIdentifier(identifier) => write!(f, "{}", identifier), + Statement::Multiply(left, right) => write!(f, "{left} * {right}"), + Statement::Constant(value) => write!(f, "{value}"), + Statement::Identifier(identifier) => write!(f, "{identifier}"), + Statement::ReservedIdentifier(identifier) => write!(f, "{identifier}"), } } } diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index 013c368..4eca964 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -40,6 +40,9 @@ impl Analyzer { self.analyze_node(right)?; } + Statement::BuiltInValue(node) => { + self.analyze_node(node)?; + } Statement::Constant(_) => {} Statement::Identifier(_) => { return Err(AnalyzerError::UnexpectedIdentifier { diff --git a/dust-lang/src/lex.rs b/dust-lang/src/lex.rs index a556155..c6a71a8 100644 --- a/dust-lang/src/lex.rs +++ b/dust-lang/src/lex.rs @@ -57,7 +57,7 @@ impl<'a> Lexer<'a> { let (token, span) = if let Some(c) = self.peek_char() { match c { '0'..='9' => self.lex_number()?, - 'a'..='z' | 'A'..='Z' => self.lex_identifier()?, + 'a'..='z' | 'A'..='Z' => self.lex_alphabetical()?, '+' => { self.position += 1; (Token::Plus, (self.position - 1, self.position)) @@ -124,6 +124,19 @@ impl<'a> Lexer<'a> { self.source[self.position..].chars().nth(1) } + fn peek_until_whitespace(&self) -> Option<&str> { + let start = self.position; + let end = self.source[self.position..] + .find(char::is_whitespace) + .map(|i| i + start); + + if let Some(end) = end { + Some(&self.source[start..end]) + } else { + None + } + } + /// Lex an integer or float token. fn lex_number(&mut self) -> Result<(Token, Span), LexError> { let start_pos = self.position; @@ -167,7 +180,7 @@ impl<'a> Lexer<'a> { } /// Lex an identifier token. - fn lex_identifier(&mut self) -> Result<(Token, Span), LexError> { + fn lex_alphabetical(&mut self) -> Result<(Token, Span), LexError> { let start_pos = self.position; while let Some(c) = self.peek_char() { @@ -180,6 +193,8 @@ impl<'a> Lexer<'a> { let string = &self.source[start_pos..self.position]; let token = match string { + "true" => Token::Boolean(true), + "false" => Token::Boolean(false), "is_even" => Token::ReservedIdentifier(ReservedIdentifier::IsEven), "is_odd" => Token::ReservedIdentifier(ReservedIdentifier::IsOdd), "length" => Token::ReservedIdentifier(ReservedIdentifier::Length), @@ -212,6 +227,26 @@ impl From for LexError { mod tests { use super::*; + #[test] + fn r#true() { + let input = "true"; + + assert_eq!( + lex(input), + Ok(vec![(Token::Boolean(true), (0, 4)), (Token::Eof, (4, 4)),]) + ) + } + + #[test] + fn r#false() { + let input = "false"; + + assert_eq!( + lex(input), + Ok(vec![(Token::Boolean(false), (0, 5)), (Token::Eof, (5, 5))]) + ) + } + #[test] fn integer_property_access() { let input = "42.is_even"; diff --git a/dust-lang/src/token.rs b/dust-lang/src/token.rs index ba91423..4725300 100644 --- a/dust-lang/src/token.rs +++ b/dust-lang/src/token.rs @@ -6,6 +6,7 @@ use crate::Identifier; #[derive(Debug, PartialEq, Clone)] pub enum Token { + Boolean(bool), Comma, Dot, Eof, @@ -24,8 +25,11 @@ pub enum Token { #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum ReservedIdentifier { + // Number properties IsEven, IsOdd, + + // List properties Length, } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index edb1917..92d0b43 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -42,6 +42,7 @@ impl Vm { variables: &mut HashMap, ) -> Result, VmError> { match node.statement { + Statement::BuiltInValue(node) => self.run_node(*node, variables), Statement::Constant(value) => Ok(Some(value.clone())), Statement::Identifier(_) => Ok(None), Statement::ReservedIdentifier(_) => Ok(None), @@ -143,6 +144,16 @@ impl Vm { }); } } + _ => { + return Err(VmError::ExpectedDifferentReservedIdentifier { + position: right_span, + expected: vec![ + ReservedIdentifier::IsEven, + ReservedIdentifier::IsOdd, + ReservedIdentifier::Length, + ], + }) + } } } @@ -170,11 +181,25 @@ pub enum VmError { // Anaylsis Failures // These should be prevented by running the analyzer before the VM - ExpectedIdentifier { position: Span }, - ExpectedIdentifierOrInteger { position: Span }, - ExpectedInteger { position: Span }, - ExpectedList { position: Span }, - ExpectedValue { position: Span }, + ExpectedIdentifier { + position: Span, + }, + ExpectedIdentifierOrInteger { + position: Span, + }, + ExpectedInteger { + position: Span, + }, + ExpectedList { + position: Span, + }, + ExpectedDifferentReservedIdentifier { + position: Span, + expected: Vec, + }, + ExpectedValue { + position: Span, + }, } impl From for VmError {