use nom::{
bytes::complete::tag,
sequence::{delimited, pair, terminated},
Parser,
};
use crate::parser::{
expression::{parse_expression, parse_identifier},
ws1,
};
use super::{ws0, Expression, ParseResult};
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Statement {
LetStatement {
identifier: String,
expression: Expression,
},
}
fn parse_let_statement(input: &str) -> ParseResult<Statement> {
pair(
delimited(tag("let"), ws1(parse_identifier), tag("=")),
terminated(ws0(parse_expression), tag(";")),
)
.map(|(identifier, expression)| Statement::LetStatement {
identifier,
expression,
})
.parse(input)
}
pub(crate) fn parse_statement(input: &str) -> ParseResult<Statement> {
parse_let_statement(input)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parser::*;
macro_rules! assert_parse {
($input:expr, $expected:expr) => {
let (rest, result) = parse_statement($input).unwrap();
assert_eq!(rest, "");
assert_eq!(result, $expected);
};
}
#[test]
fn test_parse_let_statement() {
assert_parse!(
"let x = 42;",
Statement::LetStatement {
identifier: "x".into(),
expression: Expression::Number("42".into())
}
);
assert_parse!(
"let foo = 42n;",
Statement::LetStatement {
identifier: "foo".into(),
expression: Expression::BigInt("42".into())
}
);
assert_parse!(
"let bar = \"hello\";",
Statement::LetStatement {
identifier: "bar".into(),
expression: Expression::String(StringLiteral {
value: "hello".into(),
interpolations: vec![]
})
}
);
assert_parse!(
"let baz = bar;",
Statement::LetStatement {
identifier: "baz".into(),
expression: Expression::Identifier("bar".into())
}
);
}
}