use crate::parser::{InfixParselet, Parser, ParserError, ParserResult, PREC_CALL};
use crate::types::{Call, Expression, ExpressionKind, Pattern, Token};
#[derive(Debug, Clone)]
pub struct MemberParselet;
impl MemberParselet {
fn expect_typeless_variable_pattern(
&self,
expression: Box<Expression>,
) -> Result<Option<String>, ParserError> {
match expression.kind {
ExpressionKind::Pattern(Pattern::Variable(variable_pattern)) => {
Ok(variable_pattern.name)
}
_ => Err(ParserError::ExpectedPattern),
}
}
}
impl InfixParselet for MemberParselet {
fn parse(&self, parser: &mut Parser, left: Box<Expression>, token: Token) -> ParserResult {
parser.advance();
let right = parser.parse_expression(PREC_CALL)?;
let name_opt = self.expect_typeless_variable_pattern(Box::new(right))?;
let signature = Some(left.expect_pattern()?);
if let Some(name) = name_opt {
Ok(Expression {
kind: ExpressionKind::Call(Call { name, signature }),
start_pos: token.start_pos,
end_pos: token.end_pos,
})
} else {
Err(ParserError::ExpectedPattern)
}
}
fn get_precedence(&self) -> usize {
PREC_CALL
}
}
#[cfg(test)]
mod tests {
use crate::lexer::Lexer;
use crate::parser::Parser;
use crate::types::{Call, Expression, ExpressionKind, Pattern, VariablePattern};
#[test]
fn parses_getter_into_call() {
let instance = "person";
let member = "favoriteColor";
assert_eq!(
Ok(vec![Expression {
kind: ExpressionKind::Call(Call {
name: member.to_string(),
signature: Some(Pattern::Variable(VariablePattern {
name: Some(instance.to_string()),
type_id: None,
})),
}),
start_pos: 0,
end_pos: instance.len() + member.len(),
}]),
{
let mut parser = Parser::new();
let mut lexer = Lexer::new();
let text = format!("{}.{}", instance, member);
lexer.add_text(text);
parser.add_tokens("person.favoriteColor".to_string(), lexer.parse());
parser.parse()
},
);
}
}