php_parser_rs/parser/internal/
variables.rs

1use crate::expected_token_err;
2use crate::lexer::token::TokenKind;
3use crate::parser::ast::variables::BracedVariableVariable;
4use crate::parser::ast::variables::SimpleVariable;
5use crate::parser::ast::variables::Variable;
6use crate::parser::ast::variables::VariableVariable;
7use crate::parser::error::ParseResult;
8use crate::parser::expressions;
9use crate::parser::internal::utils;
10use crate::parser::state::State;
11
12pub fn simple_variable(state: &mut State) -> ParseResult<SimpleVariable> {
13    let current = state.stream.current();
14    if let TokenKind::Variable = &current.kind {
15        let span = current.span;
16        let name = current.value.clone();
17        state.stream.next();
18
19        return Ok(SimpleVariable { span, name });
20    }
21
22    expected_token_err!("a variable", state)
23}
24
25pub fn dynamic_variable(state: &mut State) -> ParseResult<Variable> {
26    let current = state.stream.current();
27    match &current.kind {
28        TokenKind::Variable => {
29            let span = current.span;
30            let name = current.value.clone();
31            state.stream.next();
32
33            Ok(Variable::SimpleVariable(SimpleVariable { span, name }))
34        }
35        TokenKind::DollarLeftBrace => {
36            let start = current.span;
37            state.stream.next();
38
39            let expr = expressions::create(state)?;
40
41            let end = utils::skip_right_brace(state)?;
42
43            Ok(Variable::BracedVariableVariable(BracedVariableVariable {
44                start,
45                variable: Box::new(expr),
46                end,
47            }))
48        }
49        // todo(azjezz): figure out why the lexer does this.
50        TokenKind::Dollar if state.stream.peek().kind == TokenKind::LeftBrace => {
51            let start = current.span;
52            state.stream.next();
53            state.stream.next();
54
55            let expr = expressions::create(state)?;
56
57            let end = utils::skip_right_brace(state)?;
58
59            Ok(Variable::BracedVariableVariable(BracedVariableVariable {
60                start,
61                variable: Box::new(expr),
62                end,
63            }))
64        }
65        TokenKind::Dollar => {
66            let span = current.span;
67            state.stream.next();
68
69            let variable = dynamic_variable(state)?;
70
71            Ok(Variable::VariableVariable(VariableVariable {
72                span,
73                variable: Box::new(variable),
74            }))
75        }
76        _ => {
77            expected_token_err!("a variable", state)
78        }
79    }
80}