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 } Self { statements }
} }
pub fn first_statement(&self) -> &Statement {
self.statements.first().unwrap()
}
pub fn last_statement(&self) -> &Statement { pub fn last_statement(&self) -> &Statement {
self.statements.last().unwrap() self.statements.last().unwrap()
} }

View File

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

View File

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

View File

@ -254,7 +254,30 @@ pub fn lexer<'src>() -> impl Parser<
delimited_string('`'), 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(( let operator = choice((
// logic // logic
@ -302,31 +325,6 @@ pub fn lexer<'src>() -> impl Parser<
)) ))
.map(Token::Control); .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(( choice((
line_comment, line_comment,
multi_line_comment, multi_line_comment,
@ -334,8 +332,7 @@ pub fn lexer<'src>() -> impl Parser<
float, float,
integer, integer,
string, string,
keyword, identifier_and_keyword,
identifier,
control, control,
operator, operator,
)) ))

View File

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