1
0

Implement lexing for boolean values

This commit is contained in:
Jeff 2024-08-07 10:41:27 -04:00
parent a60df0274c
commit 692f1145cd
5 changed files with 86 additions and 17 deletions

View File

@ -35,6 +35,7 @@ pub enum Statement {
// Expressions // Expressions
Add(Box<Node>, Box<Node>), Add(Box<Node>, Box<Node>),
BuiltInValue(Box<Node>),
PropertyAccess(Box<Node>, Box<Node>), PropertyAccess(Box<Node>, Box<Node>),
List(Vec<Node>), List(Vec<Node>),
Multiply(Box<Node>, Box<Node>), Multiply(Box<Node>, Box<Node>),
@ -50,6 +51,7 @@ impl Statement {
match self { match self {
Statement::Add(left, _) => left.statement.expected_type(variables), Statement::Add(left, _) => left.statement.expected_type(variables),
Statement::Assign(_, _) => None, Statement::Assign(_, _) => None,
Statement::BuiltInValue(reserved) => reserved.statement.expected_type(variables),
Statement::Constant(value) => Some(value.r#type(variables)), Statement::Constant(value) => Some(value.r#type(variables)),
Statement::Identifier(identifier) => variables Statement::Identifier(identifier) => variables
.get(identifier) .get(identifier)
@ -58,8 +60,7 @@ impl Statement {
Statement::Multiply(left, _) => left.statement.expected_type(variables), Statement::Multiply(left, _) => left.statement.expected_type(variables),
Statement::PropertyAccess(_, _) => None, Statement::PropertyAccess(_, _) => None,
Statement::ReservedIdentifier(reserved) => match reserved { Statement::ReservedIdentifier(reserved) => match reserved {
ReservedIdentifier::IsEven => Some(Type::Boolean), ReservedIdentifier::IsEven | ReservedIdentifier::IsOdd => Some(Type::Boolean),
ReservedIdentifier::IsOdd => Some(Type::Boolean),
ReservedIdentifier::Length => Some(Type::Integer), ReservedIdentifier::Length => Some(Type::Integer),
}, },
} }
@ -69,23 +70,24 @@ impl Statement {
impl Display for Statement { impl Display for Statement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Statement::Assign(left, right) => write!(f, "{} = {}", left, right), Statement::Assign(left, right) => write!(f, "{left} = {right}"),
Statement::Add(left, right) => write!(f, "{} + {}", left, right), Statement::Add(left, right) => write!(f, "{left} + {right}"),
Statement::PropertyAccess(left, right) => write!(f, "{}.{}", left, right), Statement::BuiltInValue(reserved) => write!(f, "{reserved}"),
Statement::PropertyAccess(left, right) => write!(f, "{left}.{right}"),
Statement::List(nodes) => { Statement::List(nodes) => {
write!(f, "[")?; write!(f, "[")?;
for (i, node) in nodes.iter().enumerate() { for (i, node) in nodes.iter().enumerate() {
if i > 0 { if i > 0 {
write!(f, ", ")?; write!(f, ", ")?;
} }
write!(f, "{}", node)?; write!(f, "{node}")?;
} }
write!(f, "]") write!(f, "]")
} }
Statement::Multiply(left, right) => write!(f, "{} * {}", left, right), Statement::Multiply(left, right) => write!(f, "{left} * {right}"),
Statement::Constant(value) => write!(f, "{}", value), Statement::Constant(value) => write!(f, "{value}"),
Statement::Identifier(identifier) => write!(f, "{}", identifier), Statement::Identifier(identifier) => write!(f, "{identifier}"),
Statement::ReservedIdentifier(identifier) => write!(f, "{}", identifier), Statement::ReservedIdentifier(identifier) => write!(f, "{identifier}"),
} }
} }
} }

View File

@ -40,6 +40,9 @@ impl Analyzer {
self.analyze_node(right)?; self.analyze_node(right)?;
} }
Statement::BuiltInValue(node) => {
self.analyze_node(node)?;
}
Statement::Constant(_) => {} Statement::Constant(_) => {}
Statement::Identifier(_) => { Statement::Identifier(_) => {
return Err(AnalyzerError::UnexpectedIdentifier { return Err(AnalyzerError::UnexpectedIdentifier {

View File

@ -57,7 +57,7 @@ impl<'a> Lexer<'a> {
let (token, span) = if let Some(c) = self.peek_char() { let (token, span) = if let Some(c) = self.peek_char() {
match c { match c {
'0'..='9' => self.lex_number()?, '0'..='9' => self.lex_number()?,
'a'..='z' | 'A'..='Z' => self.lex_identifier()?, 'a'..='z' | 'A'..='Z' => self.lex_alphabetical()?,
'+' => { '+' => {
self.position += 1; self.position += 1;
(Token::Plus, (self.position - 1, self.position)) (Token::Plus, (self.position - 1, self.position))
@ -124,6 +124,19 @@ impl<'a> Lexer<'a> {
self.source[self.position..].chars().nth(1) 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. /// Lex an integer or float token.
fn lex_number(&mut self) -> Result<(Token, Span), LexError> { fn lex_number(&mut self) -> Result<(Token, Span), LexError> {
let start_pos = self.position; let start_pos = self.position;
@ -167,7 +180,7 @@ impl<'a> Lexer<'a> {
} }
/// Lex an identifier token. /// 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; let start_pos = self.position;
while let Some(c) = self.peek_char() { while let Some(c) = self.peek_char() {
@ -180,6 +193,8 @@ impl<'a> Lexer<'a> {
let string = &self.source[start_pos..self.position]; let string = &self.source[start_pos..self.position];
let token = match string { let token = match string {
"true" => Token::Boolean(true),
"false" => Token::Boolean(false),
"is_even" => Token::ReservedIdentifier(ReservedIdentifier::IsEven), "is_even" => Token::ReservedIdentifier(ReservedIdentifier::IsEven),
"is_odd" => Token::ReservedIdentifier(ReservedIdentifier::IsOdd), "is_odd" => Token::ReservedIdentifier(ReservedIdentifier::IsOdd),
"length" => Token::ReservedIdentifier(ReservedIdentifier::Length), "length" => Token::ReservedIdentifier(ReservedIdentifier::Length),
@ -212,6 +227,26 @@ impl From<ParseIntError> for LexError {
mod tests { mod tests {
use super::*; 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] #[test]
fn integer_property_access() { fn integer_property_access() {
let input = "42.is_even"; let input = "42.is_even";

View File

@ -6,6 +6,7 @@ use crate::Identifier;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Token { pub enum Token {
Boolean(bool),
Comma, Comma,
Dot, Dot,
Eof, Eof,
@ -24,8 +25,11 @@ pub enum Token {
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ReservedIdentifier { pub enum ReservedIdentifier {
// Number properties
IsEven, IsEven,
IsOdd, IsOdd,
// List properties
Length, Length,
} }

View File

@ -42,6 +42,7 @@ impl Vm {
variables: &mut HashMap<Identifier, Value>, variables: &mut HashMap<Identifier, Value>,
) -> Result<Option<Value>, VmError> { ) -> Result<Option<Value>, VmError> {
match node.statement { match node.statement {
Statement::BuiltInValue(node) => self.run_node(*node, variables),
Statement::Constant(value) => Ok(Some(value.clone())), Statement::Constant(value) => Ok(Some(value.clone())),
Statement::Identifier(_) => Ok(None), Statement::Identifier(_) => Ok(None),
Statement::ReservedIdentifier(_) => 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 // Anaylsis Failures
// These should be prevented by running the analyzer before the VM // These should be prevented by running the analyzer before the VM
ExpectedIdentifier { position: Span }, ExpectedIdentifier {
ExpectedIdentifierOrInteger { position: Span }, position: Span,
ExpectedInteger { position: Span }, },
ExpectedList { position: Span }, ExpectedIdentifierOrInteger {
ExpectedValue { position: Span }, position: Span,
},
ExpectedInteger {
position: Span,
},
ExpectedList {
position: Span,
},
ExpectedDifferentReservedIdentifier {
position: Span,
expected: Vec<ReservedIdentifier>,
},
ExpectedValue {
position: Span,
},
} }
impl From<ParseError> for VmError { impl From<ParseError> for VmError {