Merge pull request #99 from ryangjchandler/feature/prefix-casts

This commit is contained in:
Ryan Chandler 2022-09-16 14:39:20 +01:00 committed by GitHub
commit 37029e4e41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 25 deletions

View File

@ -394,23 +394,42 @@ impl Lexer {
[b'(', ..] => {
self.next();
if self.try_read(b"string)") {
self.skip(8);
TokenKind::StringCast
} else if self.try_read(b"object)") {
self.skip(8);
TokenKind::ObjectCast
} else if self.try_read(b"bool)") {
self.skip(6);
TokenKind::BoolCast
} else if self.try_read(b"int)") {
self.skip(5);
if self.try_read(b"int)") {
self.skip(4);
TokenKind::IntCast
} else if self.try_read(b"integer)") {
self.skip(8);
TokenKind::IntegerCast
} else if self.try_read(b"bool)") {
self.skip(5);
TokenKind::BoolCast
} else if self.try_read(b"boolean)") {
self.skip(8);
TokenKind::BooleanCast
} else if self.try_read(b"float)") {
self.skip(6);
TokenKind::FloatCast
} else if self.try_read(b"double)") {
self.skip(7);
TokenKind::DoubleCast
} else if self.try_read(b"real)") {
self.skip(5);
TokenKind::RealCast
} else if self.try_read(b"string)") {
self.skip(7);
TokenKind::StringCast
} else if self.try_read(b"binary)") {
self.skip(7);
TokenKind::BinaryCast
} else if self.try_read(b"array)") {
self.skip(6);
TokenKind::ArrayCast
} else if self.try_read(b"object)") {
self.skip(7);
TokenKind::ObjectCast
} else if self.try_read(b"unset)") {
self.skip(6);
TokenKind::UnsetCast
} else {
TokenKind::LeftParen
}
@ -900,9 +919,25 @@ mod tests {
#[test]
fn casts() {
use TokenKind::*;
assert_tokens(
"<?php (object) (string)",
&[open!(), TokenKind::ObjectCast, TokenKind::StringCast],
"<?php (int) (integer) (bool) (boolean) (float) (double) (real) (string) (binary) (array) (object) (unset)",
&[
open!(),
IntCast,
IntegerCast,
BoolCast,
BooleanCast,
FloatCast,
DoubleCast,
RealCast,
StringCast,
BinaryCast,
ArrayCast,
ObjectCast,
UnsetCast
],
);
}

View File

@ -31,6 +31,7 @@ pub enum TokenKind {
BangEquals,
BangDoubleEquals,
BoolCast,
BooleanCast,
BooleanAnd,
BooleanOr,
Break,
@ -66,6 +67,8 @@ pub enum TokenKind {
DotEquals,
DoubleArrow,
DoubleCast,
RealCast,
FloatCast,
DoubleColon,
DoubleEquals,
Echo,
@ -105,6 +108,7 @@ pub enum TokenKind {
Instanceof,
Int(i64),
IntCast,
IntegerCast,
Interface,
LeftBrace,
LeftBracket,
@ -120,6 +124,7 @@ pub enum TokenKind {
New,
Null,
ObjectCast,
UnsetCast,
OpenTag(OpenTagKind),
Percent,
Pipe,
@ -144,6 +149,7 @@ pub enum TokenKind {
SlashEquals,
Static,
StringCast,
BinaryCast,
Switch,
Throw,
Trait,
@ -180,6 +186,7 @@ impl Display for TokenKind {
Self::Readonly => "readonly",
Self::AsteriskEqual => "*=",
Self::ObjectCast => "(object)",
Self::UnsetCast => "(unset)",
Self::Abstract => "abstract",
Self::Ampersand => "&",
Self::And => "&&",
@ -193,6 +200,7 @@ impl Display for TokenKind {
Self::Attribute => "#[",
Self::Bang => "!",
Self::BoolCast => "(bool)",
Self::BooleanCast => "(boolean)",
Self::BooleanAnd => "&&",
Self::BooleanOr => "||",
Self::Break => "break",
@ -218,6 +226,7 @@ impl Display for TokenKind {
}
Self::Continue => "continue",
Self::IntCast => "(int)",
Self::IntegerCast => "(integer)",
Self::CurlyOpen => "{$",
Self::Declare => "declare",
Self::Decrement => "--",
@ -234,7 +243,9 @@ impl Display for TokenKind {
Self::Dot => ".",
Self::DotEquals => ".=",
Self::DoubleArrow => "=>",
Self::DoubleCast => "(float)",
Self::DoubleCast => "(double)",
Self::RealCast => "(real)",
Self::FloatCast => "(float)",
Self::DoubleColon => "::",
Self::DoubleEquals => "==",
Self::Echo => "echo",
@ -313,6 +324,7 @@ impl Display for TokenKind {
Self::SlashEquals => "/=",
Self::Static => "static",
Self::StringCast => "(string)",
Self::BinaryCast => "(binary)",
Self::Switch => "switch",
Self::Throw => "throw",
Self::Trait => "trait",

View File

@ -347,23 +347,28 @@ pub struct DeclareItem {
pub value: Expression,
}
// See https://www.php.net/manual/en/language.types.type-juggling.php#language.types.typecasting for more info.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum CastKind {
String,
Object,
Bool,
Int,
Double,
Bool,
Float,
String,
Array,
Object,
Unset,
}
impl From<TokenKind> for CastKind {
fn from(kind: TokenKind) -> Self {
match kind {
TokenKind::StringCast => Self::String,
TokenKind::StringCast | TokenKind::BinaryCast => Self::String,
TokenKind::ObjectCast => Self::Object,
TokenKind::BoolCast => Self::Bool,
TokenKind::IntCast => Self::Int,
TokenKind::DoubleCast => Self::Double,
TokenKind::BoolCast | TokenKind::BooleanCast => Self::Bool,
TokenKind::IntCast | TokenKind::IntegerCast => Self::Int,
TokenKind::FloatCast | TokenKind::DoubleCast | TokenKind::RealCast => Self::Float,
TokenKind::UnsetCast => Self::Unset,
TokenKind::ArrayCast => Self::Array,
_ => unreachable!(),
}
}

View File

@ -2180,10 +2180,17 @@ fn is_prefix(op: &TokenKind) -> bool {
TokenKind::Bang
| TokenKind::Minus
| TokenKind::StringCast
| TokenKind::BinaryCast
| TokenKind::ObjectCast
| TokenKind::BoolCast
| TokenKind::BooleanCast
| TokenKind::IntCast
| TokenKind::IntegerCast
| TokenKind::FloatCast
| TokenKind::DoubleCast
| TokenKind::RealCast
| TokenKind::UnsetCast
| TokenKind::ArrayCast
| TokenKind::At
)
}
@ -2197,10 +2204,17 @@ fn prefix(op: &TokenKind, rhs: Expression) -> Expression {
value: Box::new(rhs),
},
TokenKind::StringCast
| TokenKind::BinaryCast
| TokenKind::ObjectCast
| TokenKind::BoolCast
| TokenKind::BooleanCast
| TokenKind::IntCast
| TokenKind::DoubleCast => Expression::Cast {
| TokenKind::IntegerCast
| TokenKind::FloatCast
| TokenKind::DoubleCast
| TokenKind::RealCast
| TokenKind::UnsetCast
| TokenKind::ArrayCast => Expression::Cast {
kind: op.into(),
value: Box::new(rhs),
},