mirror of
https://github.com/danog/parser.git
synced 2024-11-30 04:29:13 +01:00
Merge pull request #103 from ryangjchandler/feature/yields
This commit is contained in:
commit
c2486d39db
@ -815,6 +815,7 @@ impl Lexer {
|
||||
|
||||
fn identifier_to_keyword(ident: &[u8]) -> Option<TokenKind> {
|
||||
Some(match ident {
|
||||
b"from" => TokenKind::From,
|
||||
b"and" => TokenKind::LogicalAnd,
|
||||
b"or" => TokenKind::LogicalOr,
|
||||
b"xor" => TokenKind::LogicalXor,
|
||||
|
@ -11,6 +11,7 @@ pub enum OpenTagKind {
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum TokenKind {
|
||||
From,
|
||||
Print,
|
||||
Dollar,
|
||||
HaltCompiler,
|
||||
@ -194,6 +195,7 @@ impl Default for Token {
|
||||
impl Display for TokenKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let s = match self {
|
||||
Self::From => "from",
|
||||
Self::Print => "print",
|
||||
Self::BitwiseNot => "~",
|
||||
Self::Dollar => "$",
|
||||
|
@ -557,7 +557,11 @@ pub enum Expression {
|
||||
value: Box<Expression>,
|
||||
},
|
||||
Yield {
|
||||
value: Box<Expression>,
|
||||
key: Option<Box<Self>>,
|
||||
value: Option<Box<Self>>,
|
||||
},
|
||||
YieldFrom {
|
||||
value: Box<Self>,
|
||||
},
|
||||
Negate {
|
||||
value: Box<Self>,
|
||||
|
@ -1473,12 +1473,40 @@ impl Parser {
|
||||
TokenKind::Yield => {
|
||||
self.next();
|
||||
|
||||
let value = self.expression(Precedence::Lowest)?;
|
||||
if self.current.kind == TokenKind::SemiColon {
|
||||
Expression::Yield {
|
||||
key: None,
|
||||
value: None,
|
||||
}
|
||||
} else {
|
||||
let mut from = false;
|
||||
|
||||
// FIXME: Check for presence of => here to allow yielding key and value.
|
||||
if self.current.kind == TokenKind::From {
|
||||
self.next();
|
||||
from = true;
|
||||
}
|
||||
|
||||
Expression::Yield {
|
||||
value: Box::new(value),
|
||||
let mut key = None;
|
||||
let mut value = Box::new(self.expression(if from {
|
||||
Precedence::YieldFrom
|
||||
} else {
|
||||
Precedence::Yield
|
||||
})?);
|
||||
|
||||
if self.current.kind == TokenKind::DoubleArrow && !from {
|
||||
self.next();
|
||||
key = Some(value.clone());
|
||||
value = Box::new(self.expression(Precedence::Yield)?);
|
||||
}
|
||||
|
||||
if from {
|
||||
Expression::YieldFrom { value }
|
||||
} else {
|
||||
Expression::Yield {
|
||||
key,
|
||||
value: Some(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TokenKind::Clone => {
|
||||
@ -4674,6 +4702,49 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_yield() {
|
||||
assert_ast(
|
||||
"<?php yield;",
|
||||
&[expr!(Expression::Yield {
|
||||
key: None,
|
||||
value: None
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_yield() {
|
||||
assert_ast(
|
||||
"<?php yield 1;",
|
||||
&[expr!(Expression::Yield {
|
||||
key: None,
|
||||
value: Some(Box::new(Expression::Int { i: 1 }))
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yield_with_key() {
|
||||
assert_ast(
|
||||
"<?php yield 0 => 1;",
|
||||
&[expr!(Expression::Yield {
|
||||
key: Some(Box::new(Expression::Int { i: 0 })),
|
||||
value: Some(Box::new(Expression::Int { i: 1 }))
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yield_from() {
|
||||
assert_ast(
|
||||
"<?php yield from 1;",
|
||||
&[expr!(Expression::YieldFrom {
|
||||
value: Box::new(Expression::Int { i: 1 })
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_ast(source: &str, expected: &[Statement]) {
|
||||
let mut lexer = Lexer::new(None);
|
||||
let tokens = lexer.tokenize(source).unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user