Add support for grouping statements

This commit is contained in:
Moritz Hölting 2024-04-03 01:09:13 +02:00
parent dc288588c8
commit ced609265c
3 changed files with 67 additions and 0 deletions

View File

@ -123,5 +123,17 @@ fn compile_statement(statement: &Statement) -> Option<Command> {
let content = doccomment.content();
Some(Command::Comment(content.to_string()))
}
Statement::Grouping(group) => {
let statements = group.block().statements();
let commands = statements
.iter()
.filter_map(compile_statement)
.collect::<Vec<_>>();
if commands.is_empty() {
None
} else {
Some(Command::Group(commands))
}
}
}
}

View File

@ -20,6 +20,7 @@ pub enum KeywordKind {
Function,
If,
Else,
Group,
}
impl ToString for KeywordKind {
@ -61,6 +62,7 @@ impl KeywordKind {
Self::Function => "fn",
Self::If => "if",
Self::Else => "else",
Self::Group => "group",
}
}
}

View File

@ -26,6 +26,7 @@ use super::expression::ParenthesizedCondition;
/// Block
/// | LiteralCommand
/// | Conditional
/// | Grouping
/// | DocComment
/// ;
/// ```
@ -35,6 +36,7 @@ pub enum Statement {
Block(Block),
LiteralCommand(CommandLiteral),
Conditional(Conditional),
Grouping(Grouping),
DocComment(DocComment),
}
@ -44,6 +46,7 @@ impl SourceElement for Statement {
Self::Block(block) => block.span(),
Self::LiteralCommand(literal_command) => literal_command.span(),
Self::Conditional(conditional) => conditional.span(),
Self::Grouping(grouping) => grouping.span(),
Self::DocComment(doc_comment) => doc_comment.span(),
}
}
@ -136,6 +139,40 @@ impl SourceElement for Conditional {
}
}
/// Syntax Synopsis:
///
/// ``` ebnf
/// Grouping:
/// 'group' Block
/// ;
/// ````
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
pub struct Grouping {
/// The `group` keyword.
#[get = "pub"]
group_keyword: Keyword,
/// The block of the conditional.
#[get = "pub"]
block: Block,
}
impl Grouping {
/// Dissolves the [`Grouping`] into its components.
#[must_use]
pub fn dissolve(self) -> (Keyword, Block) {
(self.group_keyword, self.block)
}
}
impl SourceElement for Grouping {
fn span(&self) -> Span {
self.group_keyword
.span()
.join(&self.block.span())
.expect("The span of the grouping is invalid.")
}
}
/// Syntax Synopsis:
///
/// ``` ebnf
@ -262,11 +299,27 @@ impl<'a> Parser<'a> {
}
}
// doc comment
Reading::Atomic(Token::DocComment(doc_comment)) => {
self.forward();
Some(Statement::DocComment(doc_comment))
}
// grouping statement
Reading::Atomic(Token::Keyword(group_keyword))
if group_keyword.keyword == KeywordKind::Group =>
{
// eat the group keyword
self.forward();
let block = self.parse_block(handler)?;
Some(Statement::Grouping(Grouping {
group_keyword,
block,
}))
}
// other
unexpected => {
handler.receive(Error::UnexpectedSyntax(UnexpectedSyntax {