Actually just three programming languages in a trenchcoat
1use super::*;
2use crate::{Parser, Spanned};
3use source_span::Span;
4use trilogy_scanner::{Token, TokenType};
5
6/// The optional message portion of an assert statement.
7///
8/// ```trilogy
9/// #- assert -# "msg" as #- expression -#
10/// ```
11#[derive(Clone, Debug, PrettyPrintSExpr)]
12pub struct AssertMessage {
13 pub message: Expression,
14 pub r#as: Token,
15}
16
17/// An assert statement.
18///
19/// ```trilogy
20/// assert "msg" as expression
21/// ```
22#[derive(Clone, Debug, PrettyPrintSExpr)]
23pub struct AssertStatement {
24 pub assert: Token,
25 pub message: Option<AssertMessage>,
26 pub assertion: Expression,
27}
28
29impl AssertStatement {
30 pub(crate) fn parse(parser: &mut Parser) -> SyntaxResult<Self> {
31 let assert = parser.expect(TokenType::KwAssert).unwrap();
32 let message_or_assertion = Expression::parse(parser)?;
33 if let Ok(r#as) = parser.expect(TokenType::KwAs) {
34 let assertion = Expression::parse(parser)?;
35 return Ok(Self {
36 assert,
37 message: Some(AssertMessage {
38 message: message_or_assertion,
39 r#as,
40 }),
41 assertion,
42 });
43 }
44 Ok(Self {
45 assert,
46 message: None,
47 assertion: message_or_assertion,
48 })
49 }
50}
51
52impl Spanned for AssertStatement {
53 fn span(&self) -> Span {
54 self.assert.span.union(self.assertion.span())
55 }
56}
57
58#[cfg(test)]
59mod test {
60 use super::*;
61
62 test_parse!(assert_true: "assert true" => AssertStatement::parse => "(AssertStatement _ () (Expression::Boolean _))");
63 test_parse!(assert_expression: "assert if x then false else true" => AssertStatement::parse => "(AssertStatement _ () (Expression::IfElse _))");
64 test_parse!(assert_with_message: "assert \"message\" as true" => AssertStatement::parse => "(AssertStatement _ (AssertMessage _ _) (Expression::Boolean _))");
65 test_parse_error!(assert_without_expr: "assert" => AssertStatement::parse);
66 test_parse_error!(assert_invalid_expr: "assert + 5" => AssertStatement::parse);
67}