diff --git a/src/abstract_tree/loop.rs b/src/abstract_tree/loop.rs index 7bbadf5..8172615 100644 --- a/src/abstract_tree/loop.rs +++ b/src/abstract_tree/loop.rs @@ -4,11 +4,17 @@ use crate::{ Value, }; -use super::{AbstractTree, Block, Type}; +use super::{AbstractTree, Statement, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Loop<'src> { - block: Block<'src>, + statements: Vec>, +} + +impl<'src> Loop<'src> { + pub fn new(statements: Vec>) -> Self { + Self { statements } + } } impl<'src> AbstractTree for Loop<'src> { diff --git a/src/lexer.rs b/src/lexer.rs index cb7b7e5..80d3bda 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -123,6 +123,7 @@ pub fn lexer<'src>() -> impl Parser< just("map").padded(), just("range").padded(), just("str").padded(), + just("loop").padded(), )) .map(Token::Keyword); diff --git a/src/parser.rs b/src/parser.rs index 1ae899c..d7b7a44 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -7,6 +7,15 @@ use crate::{abstract_tree::*, error::Error, lexer::Token}; type ParserInput<'tokens, 'src> = SpannedInput, SimpleSpan, &'tokens [(Token<'src>, SimpleSpan)]>; +pub fn parse<'tokens, 'src: 'tokens>( + tokens: &'tokens [(Token<'src>, SimpleSpan)], +) -> Result, SimpleSpan)>, Error<'tokens>> { + parser() + .parse(tokens.spanned((0..0).into())) + .into_result() + .map_err(|error| Error::Parse(error)) +} + fn parser<'tokens, 'src: 'tokens>() -> impl Parser< 'tokens, ParserInput<'tokens, 'src>, @@ -158,7 +167,18 @@ fn parser<'tokens, 'src: 'tokens>() -> impl Parser< .map(|statements| Statement::Block(Block::new(statements))) .boxed(); - choice((assignment, expression_statement, block)) + let r#loop = statement + .clone() + .separated_by(just(Token::Control(";")).or_not()) + .collect() + .delimited_by( + just(Token::Keyword("loop")).then(just(Token::Control("{"))), + just(Token::Control("}")), + ) + .map(|statements| Statement::Loop(Loop::new(statements))) + .boxed(); + + choice((assignment, expression_statement, block, r#loop)) }); statement @@ -167,21 +187,20 @@ fn parser<'tokens, 'src: 'tokens>() -> impl Parser< .collect() } -pub fn parse<'tokens, 'src: 'tokens>( - tokens: &'tokens [(Token<'src>, SimpleSpan)], -) -> Result, SimpleSpan)>, Error<'tokens>> { - parser() - .parse(tokens.spanned((0..0).into())) - .into_result() - .map_err(|error| Error::Parse(error)) -} - #[cfg(test)] mod tests { use crate::{abstract_tree::Logic, lexer::lex}; use super::*; + #[test] + fn r#loop() { + assert_eq!( + parse(&lex("loop {}").unwrap()).unwrap()[0].0, + Statement::Loop(Loop::new(vec![])) + ); + } + #[test] fn block() { assert_eq!(