mirror of
https://github.com/danog/parser.git
synced 2024-11-26 20:04:57 +01:00
parser/lexer: implement all assignment ops
This commit is contained in:
parent
5a0fe5beb2
commit
27d5705f85
@ -149,6 +149,10 @@ impl Lexer {
|
||||
self.skip(2);
|
||||
TokenKind::BooleanAnd
|
||||
}
|
||||
[b'&', b'=', ..] => {
|
||||
self.skip(2);
|
||||
TokenKind::AmpersandEquals
|
||||
}
|
||||
[b'&', ..] => {
|
||||
self.next();
|
||||
TokenKind::Ampersand
|
||||
@ -363,6 +367,10 @@ impl Lexer {
|
||||
self.next();
|
||||
TokenKind::Slash
|
||||
}
|
||||
[b'*', b'*', b'=', ..] => {
|
||||
self.skip(3);
|
||||
TokenKind::PowEquals
|
||||
}
|
||||
[b'*', b'*', ..] => {
|
||||
self.skip(2);
|
||||
TokenKind::Pow
|
||||
@ -379,10 +387,18 @@ impl Lexer {
|
||||
self.skip(2);
|
||||
TokenKind::Pipe
|
||||
}
|
||||
[b'|', b'=', ..] => {
|
||||
self.skip(2);
|
||||
TokenKind::PipeEquals
|
||||
}
|
||||
[b'|', ..] => {
|
||||
self.next();
|
||||
TokenKind::Pipe
|
||||
}
|
||||
[b'^', b'=', ..] => {
|
||||
self.skip(2);
|
||||
TokenKind::CaretEquals
|
||||
}
|
||||
[b'^', ..] => {
|
||||
self.next();
|
||||
TokenKind::Caret
|
||||
@ -458,6 +474,10 @@ impl Lexer {
|
||||
self.next();
|
||||
TokenKind::Plus
|
||||
}
|
||||
[b'%', b'=', ..] => {
|
||||
self.skip(2);
|
||||
TokenKind::PercentEquals
|
||||
}
|
||||
[b'%', ..] => {
|
||||
self.next();
|
||||
TokenKind::Percent
|
||||
@ -484,6 +504,11 @@ impl Lexer {
|
||||
|
||||
todo!("heredocs & nowdocs");
|
||||
}
|
||||
[b'<', b'<', b'=', ..] => {
|
||||
self.skip(3);
|
||||
|
||||
TokenKind::LeftShiftEquals
|
||||
}
|
||||
[b'<', b'<', ..] => {
|
||||
self.skip(2);
|
||||
TokenKind::LeftShift
|
||||
@ -504,6 +529,10 @@ impl Lexer {
|
||||
self.next();
|
||||
TokenKind::LessThan
|
||||
}
|
||||
[b'>', b'>', b'=', ..] => {
|
||||
self.skip(3);
|
||||
TokenKind::RightShiftEquals
|
||||
}
|
||||
[b'>', b'>', ..] => {
|
||||
self.skip(2);
|
||||
TokenKind::RightShift
|
||||
|
@ -18,6 +18,7 @@ pub enum TokenKind {
|
||||
Global,
|
||||
Abstract,
|
||||
Ampersand,
|
||||
AmpersandEquals,
|
||||
And,
|
||||
AndEqual,
|
||||
Array,
|
||||
@ -40,6 +41,7 @@ pub enum TokenKind {
|
||||
Break,
|
||||
Callable,
|
||||
Caret,
|
||||
CaretEquals,
|
||||
Case,
|
||||
Catch,
|
||||
Class,
|
||||
@ -117,7 +119,9 @@ pub enum TokenKind {
|
||||
LeftBracket,
|
||||
LeftParen,
|
||||
LeftShift,
|
||||
LeftShiftEquals,
|
||||
RightShift,
|
||||
RightShiftEquals,
|
||||
LessThan,
|
||||
LessThanEquals,
|
||||
Match,
|
||||
@ -130,7 +134,9 @@ pub enum TokenKind {
|
||||
UnsetCast,
|
||||
OpenTag(OpenTagKind),
|
||||
Percent,
|
||||
PercentEquals,
|
||||
Pipe,
|
||||
PipeEquals,
|
||||
Plus,
|
||||
PlusEquals,
|
||||
Pow,
|
||||
@ -215,6 +221,7 @@ impl Display for TokenKind {
|
||||
Self::Break => "break",
|
||||
Self::Callable => "callable",
|
||||
Self::Caret => "^",
|
||||
Self::CaretEquals => "^=",
|
||||
Self::Case => "case",
|
||||
Self::Catch => "catch",
|
||||
Self::Class => "class",
|
||||
@ -297,6 +304,9 @@ impl Display for TokenKind {
|
||||
Self::LeftBracket => "[",
|
||||
Self::LeftParen => "(",
|
||||
Self::LeftShift => "<<",
|
||||
Self::LeftShiftEquals => "<<=",
|
||||
Self::RightShift => ">>",
|
||||
Self::RightShiftEquals => ">>=",
|
||||
Self::LessThan => "<",
|
||||
Self::LessThanEquals => "<=",
|
||||
Self::Match => "match",
|
||||
@ -310,7 +320,9 @@ impl Display for TokenKind {
|
||||
OpenTagKind::Full => "<?php",
|
||||
},
|
||||
Self::Percent => "%",
|
||||
Self::PercentEquals => "%=",
|
||||
Self::Pipe => "|",
|
||||
Self::PipeEquals => "|=",
|
||||
Self::Plus => "+",
|
||||
Self::PlusEquals => "+=",
|
||||
Self::Pow => "**",
|
||||
|
@ -650,6 +650,13 @@ pub enum InfixOp {
|
||||
LogicalOr,
|
||||
LogicalXor,
|
||||
Spaceship,
|
||||
PowAssign,
|
||||
ModAssign,
|
||||
BitwiseAndAssign,
|
||||
BitwiseOrAssign,
|
||||
BitwiseXorAssign,
|
||||
LeftShiftAssign,
|
||||
RightShiftAssign,
|
||||
}
|
||||
|
||||
impl From<TokenKind> for InfixOp {
|
||||
@ -689,6 +696,13 @@ impl From<TokenKind> for InfixOp {
|
||||
TokenKind::LogicalAnd => Self::LogicalAnd,
|
||||
TokenKind::LogicalOr => Self::LogicalOr,
|
||||
TokenKind::LogicalXor => Self::LogicalXor,
|
||||
TokenKind::PowEquals => Self::PowAssign,
|
||||
TokenKind::PercentEquals => Self::ModAssign,
|
||||
TokenKind::AmpersandEquals => Self::BitwiseAndAssign,
|
||||
TokenKind::PipeEquals => Self::BitwiseOrAssign,
|
||||
TokenKind::CaretEquals => Self::BitwiseXorAssign,
|
||||
TokenKind::LeftShiftEquals => Self::LeftShiftAssign,
|
||||
TokenKind::RightShiftEquals => Self::RightShiftAssign,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -2257,6 +2257,13 @@ fn is_infix(t: &TokenKind) -> bool {
|
||||
matches!(
|
||||
t,
|
||||
TokenKind::Pow
|
||||
| TokenKind::RightShiftEquals
|
||||
| TokenKind::LeftShiftEquals
|
||||
| TokenKind::CaretEquals
|
||||
| TokenKind::AmpersandEquals
|
||||
| TokenKind::PipeEquals
|
||||
| TokenKind::PercentEquals
|
||||
| TokenKind::PowEquals
|
||||
| TokenKind::LogicalAnd
|
||||
| TokenKind::LogicalOr
|
||||
| TokenKind::LogicalXor
|
||||
@ -4499,6 +4506,174 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assign() {
|
||||
assert_ast(
|
||||
"<?php $a = 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::Assign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_assign() {
|
||||
assert_ast(
|
||||
"<?php $a += 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::AddAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sub_assign() {
|
||||
assert_ast(
|
||||
"<?php $a -= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::SubAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mul_assign() {
|
||||
assert_ast(
|
||||
"<?php $a *= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::MulAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pow_assign() {
|
||||
assert_ast(
|
||||
"<?php $a **= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::PowAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn div_assign() {
|
||||
assert_ast(
|
||||
"<?php $a /= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::DivAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concat_assign() {
|
||||
assert_ast(
|
||||
"<?php $a .= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::ConcatAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mod_assign() {
|
||||
assert_ast(
|
||||
"<?php $a %= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::ModAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bit_and_assign() {
|
||||
assert_ast(
|
||||
"<?php $a &= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::BitwiseAndAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bit_or_assign() {
|
||||
assert_ast(
|
||||
"<?php $a |= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::BitwiseOrAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bit_xor_assign() {
|
||||
assert_ast(
|
||||
"<?php $a ^= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::BitwiseXorAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn left_shift_assign() {
|
||||
assert_ast(
|
||||
"<?php $a <<= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::LeftShiftAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn right_shift_assign() {
|
||||
assert_ast(
|
||||
"<?php $a >>= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::RightShiftAssign,
|
||||
rhs: Box::new(Expression::Int { i: 1 }),
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn null_coalese_assign() {
|
||||
assert_ast(
|
||||
"<?php $a ??= 1;",
|
||||
&[expr!(Expression::Infix {
|
||||
lhs: Box::new(Expression::Variable { name: "a".into() }),
|
||||
op: InfixOp::CoalesceAssign,
|
||||
rhs: 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();
|
||||
|
@ -66,7 +66,8 @@ impl Precedence {
|
||||
Coalesce => Self::NullCoalesce,
|
||||
Question => Self::Ternary,
|
||||
Equals | PlusEquals | MinusEquals | AsteriskEqual | PowEquals | SlashEquals
|
||||
| DotEquals | AndEqual | CoalesceEqual => Self::Assignment,
|
||||
| DotEquals | AndEqual | CoalesceEqual | PercentEquals | AmpersandEquals
|
||||
| PipeEquals | CaretEquals | LeftShiftEquals | RightShiftEquals => Self::Assignment,
|
||||
Yield => Self::Yield,
|
||||
LogicalAnd => Self::KeyAnd,
|
||||
LogicalOr => Self::KeyOr,
|
||||
|
Loading…
Reference in New Issue
Block a user