Fix lexing and parsing errors

This commit is contained in:
Jeff 2024-05-20 17:15:05 -04:00
parent 9c77ae2410
commit aadb51e1f1
5 changed files with 49 additions and 51 deletions

View File

@ -15,6 +15,10 @@ impl Block {
Self { statements }
}
pub fn first_statement(&self) -> &Statement {
self.statements.first().unwrap()
}
pub fn last_statement(&self) -> &Statement {
self.statements.last().unwrap()
}

View File

@ -52,8 +52,8 @@ impl AbstractNode for IfElse {
.check(&actual)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.if_block.item.last_statement().position(),
expected_position: self.if_expression.position(),
actual_position: else_block.item.last_statement().position(),
expected_position: self.if_block.item.first_statement().position(),
})?;
}
} else {
@ -89,9 +89,9 @@ impl AbstractNode for IfElse {
Ok(())
}
fn run(self, context: &mut Context, _clear_variables: bool) -> Result<Action, RuntimeError> {
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
let if_position = self.if_expression.position();
let action = self.if_expression.run(context, _clear_variables)?;
let action = self.if_expression.run(context, _manage_memory)?;
let value = if let Action::Return(value) = action {
value
} else {
@ -102,11 +102,11 @@ impl AbstractNode for IfElse {
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
if *if_boolean {
self.if_block.item.run(context, _clear_variables)
self.if_block.item.run(context, _manage_memory)
} else {
for (expression, block) in self.else_ifs {
let expression_position = expression.position();
let action = expression.run(context, _clear_variables)?;
let action = expression.run(context, _manage_memory)?;
let value = if let Action::Return(value) = action {
value
} else {
@ -117,7 +117,7 @@ impl AbstractNode for IfElse {
if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() {
if *else_if_boolean {
return block.item.run(context, _clear_variables);
return block.item.run(context, _manage_memory);
}
} else {
return Err(RuntimeError::ValidationFailure(
@ -130,7 +130,7 @@ impl AbstractNode for IfElse {
}
if let Some(else_statement) = self.else_block {
else_statement.item.run(context, _clear_variables)
else_statement.item.run(context, _manage_memory)
} else {
Ok(Action::None)
}

View File

@ -32,10 +32,10 @@ impl AbstractNode for While {
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
self.expression.validate(_context, _manage_memory)?;
self.expression.validate(_context, false)?;
for statement in &self.statements {
statement.validate(_context, _manage_memory)?;
statement.validate(_context, false)?;
}
Ok(())
@ -44,10 +44,7 @@ impl AbstractNode for While {
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
let get_boolean = || -> Result<Value, RuntimeError> {
let expression_position = self.expression.position();
let action = self
.expression
.clone()
.run(&mut _context.clone(), _manage_memory)?;
let action = self.expression.clone().run(&mut _context.clone(), false)?;
if let Action::Return(value) = action {
Ok(value)
@ -60,9 +57,7 @@ impl AbstractNode for While {
while let ValueInner::Boolean(true) = get_boolean()?.inner().as_ref() {
for statement in &self.statements {
let action = statement
.clone()
.run(&mut _context.clone(), _manage_memory)?;
let action = statement.clone().run(&mut _context.clone(), false)?;
match action {
Action::Return(_) => {}

View File

@ -254,7 +254,30 @@ pub fn lexer<'src>() -> impl Parser<
delimited_string('`'),
));
let identifier = text::ident().map(|text: &str| Token::Identifier(text));
let identifier_and_keyword = text::ident().map(|text: &str| match text {
"any" => Token::Keyword(Keyword::Any),
"async" => Token::Keyword(Keyword::Async),
"bool" => Token::Keyword(Keyword::Bool),
"break" => Token::Keyword(Keyword::Break),
"else" => Token::Keyword(Keyword::Else),
"float" => Token::Keyword(Keyword::Float),
"fn" => Token::Keyword(Keyword::Fn),
"int" => Token::Keyword(Keyword::Int),
"if" => Token::Keyword(Keyword::If),
"list" => Token::Keyword(Keyword::List),
"map" => Token::Keyword(Keyword::Map),
"none" => Token::Keyword(Keyword::None),
"range" => Token::Keyword(Keyword::Range),
"struct" => Token::Keyword(Keyword::Struct),
"str" => Token::Keyword(Keyword::Str),
"type" => Token::Keyword(Keyword::Type),
"loop" => Token::Keyword(Keyword::Loop),
"while" => Token::Keyword(Keyword::While),
"READ_LINE" => Token::Keyword(Keyword::ReadLine),
"SLEEP" => Token::Keyword(Keyword::Sleep),
"WRITE_LINE" => Token::Keyword(Keyword::WriteLine),
_ => Token::Identifier(text),
});
let operator = choice((
// logic
@ -302,31 +325,6 @@ pub fn lexer<'src>() -> impl Parser<
))
.map(Token::Control);
let keyword = choice((
just("any").to(Keyword::Any),
just("async").to(Keyword::Async),
just("bool").to(Keyword::Bool),
just("break").to(Keyword::Break),
just("else").to(Keyword::Else),
just("float").to(Keyword::Float),
just("fn").to(Keyword::Fn),
just("int").to(Keyword::Int),
just("if").to(Keyword::If),
just("list").to(Keyword::List),
just("map").to(Keyword::Map),
just("none").to(Keyword::None),
just("range").to(Keyword::Range),
just("struct").to(Keyword::Struct),
just("str").to(Keyword::Str),
just("type").to(Keyword::Type),
just("loop").to(Keyword::Loop),
just("while").to(Keyword::While),
just("READ_LINE").to(Keyword::ReadLine),
just("SLEEP").to(Keyword::Sleep),
just("WRITE_LINE").to(Keyword::WriteLine),
))
.map(Token::Keyword);
choice((
line_comment,
multi_line_comment,
@ -334,8 +332,7 @@ pub fn lexer<'src>() -> impl Parser<
float,
integer,
string,
keyword,
identifier,
identifier_and_keyword,
control,
operator,
))

View File

@ -4,15 +4,17 @@ while count <= 15 {
divides_by_3 = count % 3 == 0
divides_by_5 = count % 5 == 0
if divides_by_3 && divides_by_5 {
io.write_line('fizzbuzz')
output = if divides_by_3 && divides_by_5 {
'fizzbuzz'
} else if divides_by_3 {
io.write_line('fizz')
'fizz'
} else if divides_by_5 {
io.write_line('buzz')
} else {
io.write_line(count)
'buzz'
} else {
string.new(count)
}
io.write_line(output)
count += 1
}