mirror of
https://github.com/danog/parser.git
synced 2024-11-26 20:04:57 +01:00
chore: remove fallback expression parser (#181)
Signed-off-by: azjezz <azjezz@protonmail.com>
This commit is contained in:
parent
00834ed3ff
commit
bd2023c3c4
@ -1514,6 +1514,13 @@ fn identifier_to_keyword(ident: &[u8]) -> Option<TokenKind> {
|
|||||||
b"var" => TokenKind::Var,
|
b"var" => TokenKind::Var,
|
||||||
b"yield" => TokenKind::Yield,
|
b"yield" => TokenKind::Yield,
|
||||||
b"__DIR__" => TokenKind::DirConstant,
|
b"__DIR__" => TokenKind::DirConstant,
|
||||||
|
b"__FILE__" => TokenKind::FileConstant,
|
||||||
|
b"__LINE__" => TokenKind::LineConstant,
|
||||||
|
b"__FUNCTION__" => TokenKind::FunctionConstant,
|
||||||
|
b"__CLASS__" => TokenKind::ClassConstant,
|
||||||
|
b"__METHOD__" => TokenKind::MethodConstant,
|
||||||
|
b"__TRAIT__" => TokenKind::TraitConstant,
|
||||||
|
b"__NAMESPACE__" => TokenKind::NamespaceConstant,
|
||||||
b"while" => TokenKind::While,
|
b"while" => TokenKind::While,
|
||||||
b"insteadof" => TokenKind::Insteadof,
|
b"insteadof" => TokenKind::Insteadof,
|
||||||
b"list" => TokenKind::List,
|
b"list" => TokenKind::List,
|
||||||
|
@ -391,6 +391,7 @@ pub enum Expression {
|
|||||||
Empty,
|
Empty,
|
||||||
VariadicPlaceholder,
|
VariadicPlaceholder,
|
||||||
ErrorSuppress {
|
ErrorSuppress {
|
||||||
|
span: Span,
|
||||||
expr: Box<Self>,
|
expr: Box<Self>,
|
||||||
},
|
},
|
||||||
Increment {
|
Increment {
|
||||||
@ -415,6 +416,7 @@ pub enum Expression {
|
|||||||
rhs: Box<Self>,
|
rhs: Box<Self>,
|
||||||
},
|
},
|
||||||
Include {
|
Include {
|
||||||
|
span: Span,
|
||||||
kind: IncludeKind,
|
kind: IncludeKind,
|
||||||
path: Box<Expression>,
|
path: Box<Expression>,
|
||||||
},
|
},
|
||||||
@ -496,9 +498,11 @@ pub enum Expression {
|
|||||||
},
|
},
|
||||||
Null,
|
Null,
|
||||||
BooleanNot {
|
BooleanNot {
|
||||||
|
span: Span,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
MagicConst {
|
MagicConst {
|
||||||
|
span: Span,
|
||||||
constant: MagicConst,
|
constant: MagicConst,
|
||||||
},
|
},
|
||||||
Ternary {
|
Ternary {
|
||||||
@ -529,24 +533,31 @@ pub enum Expression {
|
|||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
Negate {
|
Negate {
|
||||||
|
span: Span,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
UnaryPlus {
|
UnaryPlus {
|
||||||
|
span: Span,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
BitwiseNot {
|
BitwiseNot {
|
||||||
|
span: Span,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
PreDecrement {
|
PreDecrement {
|
||||||
|
span: Span,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
PreIncrement {
|
PreIncrement {
|
||||||
|
span: Span,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
Print {
|
Print {
|
||||||
|
span: Span,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
Cast {
|
Cast {
|
||||||
|
span: Span,
|
||||||
kind: CastKind,
|
kind: CastKind,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
@ -578,7 +589,14 @@ pub struct MatchArm {
|
|||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
pub enum MagicConst {
|
pub enum MagicConst {
|
||||||
Dir,
|
Directory,
|
||||||
|
File,
|
||||||
|
Line,
|
||||||
|
Class,
|
||||||
|
Function,
|
||||||
|
Method,
|
||||||
|
Namespace,
|
||||||
|
Trait,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
@ -188,7 +188,7 @@ fn create(state: &mut State) -> ParseResult<Expression> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! expressions {
|
macro_rules! expressions {
|
||||||
($(#[before($else:ident), current($( $current:pat_param )|+) $(, peek($( $peek:pat_param )|+))?] $expr:ident($out:expr))+) => {
|
($(#[before($else:ident), current($(|)? $( $current:pat_param )|+) $(, peek($(|)? $( $peek:pat_param )|+))?] $expr:ident($out:expr))+) => {
|
||||||
$(
|
$(
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn $expr(state: &mut State) -> ParseResult<Expression> {
|
fn $expr(state: &mut State) -> ParseResult<Expression> {
|
||||||
@ -481,107 +481,286 @@ expressions! {
|
|||||||
arrays::legacy_array_expression(state)
|
arrays::legacy_array_expression(state)
|
||||||
})
|
})
|
||||||
|
|
||||||
#[before(fallback), current(TokenKind::LeftBracket)]
|
#[before(new), current(TokenKind::LeftBracket)]
|
||||||
left_bracket(|state: &mut State| {
|
left_bracket(|state: &mut State| {
|
||||||
arrays::array_expression(state)
|
arrays::array_expression(state)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#[before(directory_magic_constant), current(TokenKind::New)]
|
||||||
|
new(|state: &mut State| {
|
||||||
|
state.next();
|
||||||
|
let target = match state.current.kind {
|
||||||
|
TokenKind::Self_ => {
|
||||||
|
if !state.has_class_scope {
|
||||||
|
return Err(ParseError::CannotFindTypeInCurrentScope(
|
||||||
|
state.current.kind.to_string(),
|
||||||
|
state.current.span,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Expression::Self_
|
||||||
|
}
|
||||||
|
TokenKind::Static => {
|
||||||
|
if !state.has_class_scope {
|
||||||
|
return Err(ParseError::CannotFindTypeInCurrentScope(
|
||||||
|
state.current.kind.to_string(),
|
||||||
|
state.current.span,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Expression::Static
|
||||||
|
}
|
||||||
|
TokenKind::Parent => {
|
||||||
|
if !state.has_class_scope {
|
||||||
|
return Err(ParseError::CannotFindTypeInCurrentScope(
|
||||||
|
state.current.kind.to_string(),
|
||||||
|
state.current.span,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Expression::Parent
|
||||||
|
}
|
||||||
|
_ => clone_or_new_precedence(state)?,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut args = vec![];
|
||||||
|
if state.current.kind == TokenKind::LeftParen {
|
||||||
|
args = parameters::args_list(state)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Expression::New{target:Box::new(target),args,})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(file_magic_constant), current(TokenKind::DirConstant)]
|
||||||
|
directory_magic_constant(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Ok(Expression::MagicConst {
|
||||||
|
span,
|
||||||
|
constant: MagicConst::Directory
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(line_magic_constant), current(TokenKind::FileConstant)]
|
||||||
|
file_magic_constant(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Ok(Expression::MagicConst {
|
||||||
|
span,
|
||||||
|
constant: MagicConst::File
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(function_magic_constant), current(TokenKind::LineConstant)]
|
||||||
|
line_magic_constant(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Ok(Expression::MagicConst {
|
||||||
|
span,
|
||||||
|
constant: MagicConst::Line
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(class_magic_constant), current(TokenKind::FunctionConstant)]
|
||||||
|
function_magic_constant(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Ok(Expression::MagicConst {
|
||||||
|
span,
|
||||||
|
constant: MagicConst::Function,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(method_magic_constant), current(TokenKind::ClassConstant)]
|
||||||
|
class_magic_constant(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Ok(Expression::MagicConst {
|
||||||
|
span,
|
||||||
|
constant: MagicConst::Class,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(namespace_magic_constant), current(TokenKind::MethodConstant)]
|
||||||
|
method_magic_constant(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Ok(Expression::MagicConst {
|
||||||
|
span,
|
||||||
|
constant: MagicConst::Method,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(trait_magic_constant), current(TokenKind::NamespaceConstant)]
|
||||||
|
namespace_magic_constant(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Ok(Expression::MagicConst {
|
||||||
|
span,
|
||||||
|
constant: MagicConst::Namespace,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(include), current(TokenKind::TraitConstant)]
|
||||||
|
trait_magic_constant(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
Ok(Expression::MagicConst {
|
||||||
|
span,
|
||||||
|
constant: MagicConst::Trait
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(cast_prefix), current(TokenKind::Include | TokenKind::IncludeOnce | TokenKind::Require | TokenKind::RequireOnce)]
|
||||||
|
include(|state: &mut State| {
|
||||||
|
let kind: IncludeKind = (&state.current.kind).into();
|
||||||
|
let span = state.current.span;
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
let path = lowest_precedence(state)?;
|
||||||
|
|
||||||
|
Ok(Expression::Include {
|
||||||
|
span,
|
||||||
|
kind,
|
||||||
|
path:Box::new(path)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(numeric_prefix), current(
|
||||||
|
| TokenKind::StringCast | TokenKind::BinaryCast | TokenKind::ObjectCast
|
||||||
|
| TokenKind::BoolCast | TokenKind::BooleanCast | TokenKind::IntCast
|
||||||
|
| TokenKind::IntegerCast | TokenKind::FloatCast | TokenKind::DoubleCast
|
||||||
|
| TokenKind::RealCast | TokenKind::UnsetCast | TokenKind::ArrayCast
|
||||||
|
)]
|
||||||
|
cast_prefix(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
let kind = state.current.kind.clone().into();
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
let rhs = for_precedence(state, Precedence::Prefix)?;
|
||||||
|
|
||||||
|
Ok(Expression::Cast {
|
||||||
|
span,
|
||||||
|
kind,
|
||||||
|
value: Box::new(rhs),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(bang_prefix), current(TokenKind::Decrement | TokenKind::Increment | TokenKind::Minus | TokenKind::Plus)]
|
||||||
|
numeric_prefix(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
let op = state.current.kind.clone();
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
let rhs = for_precedence(state, Precedence::Prefix)?;
|
||||||
|
|
||||||
|
let expr = match op {
|
||||||
|
TokenKind::Minus => Expression::Negate {
|
||||||
|
span,
|
||||||
|
value: Box::new(rhs),
|
||||||
|
},
|
||||||
|
TokenKind::Plus => Expression::UnaryPlus {
|
||||||
|
span,
|
||||||
|
value: Box::new(rhs),
|
||||||
|
},
|
||||||
|
TokenKind::Decrement => Expression::PreDecrement {
|
||||||
|
span,
|
||||||
|
value: Box::new(rhs),
|
||||||
|
},
|
||||||
|
TokenKind::Increment => Expression::PreIncrement {
|
||||||
|
span,
|
||||||
|
value: Box::new(rhs),
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(at_prefix), current(TokenKind::Bang)]
|
||||||
|
bang_prefix(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
let rhs = for_precedence(state, Precedence::Bang)?;
|
||||||
|
|
||||||
|
Ok(Expression::BooleanNot {
|
||||||
|
span,
|
||||||
|
value: Box::new(rhs)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(print_prefix), current(TokenKind::At)]
|
||||||
|
at_prefix(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
let rhs = for_precedence(state, Precedence::Prefix)?;
|
||||||
|
|
||||||
|
Ok(Expression::ErrorSuppress {
|
||||||
|
span,
|
||||||
|
expr: Box::new(rhs)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(bitwise_prefix), current(TokenKind::Print)]
|
||||||
|
print_prefix(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
let rhs = for_precedence(state, Precedence::Prefix)?;
|
||||||
|
|
||||||
|
Ok(Expression::Print {
|
||||||
|
span,
|
||||||
|
value: Box::new(rhs)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(dynamic_variable), current(TokenKind::BitwiseNot)]
|
||||||
|
bitwise_prefix(|state: &mut State| {
|
||||||
|
let span = state.current.span;
|
||||||
|
|
||||||
|
state.next();
|
||||||
|
|
||||||
|
let rhs = for_precedence(state, Precedence::Prefix)?;
|
||||||
|
|
||||||
|
Ok(Expression::BitwiseNot {
|
||||||
|
span,
|
||||||
|
value: Box::new(rhs)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
#[before(unexpected_token), current(TokenKind::Dollar)]
|
||||||
|
dynamic_variable(|state: &mut State| {
|
||||||
|
variables::dynamic_variable(state)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fallback(state: &mut State) -> ParseResult<Expression> {
|
fn unexpected_token(state: &mut State) -> ParseResult<Expression> {
|
||||||
let expr = match &state.current.kind {
|
Err(ParseError::UnexpectedToken(
|
||||||
TokenKind::New => {
|
state.current.kind.to_string(),
|
||||||
utils::skip(state, TokenKind::New)?;
|
state.current.span,
|
||||||
|
))
|
||||||
let target = match state.current.kind {
|
|
||||||
TokenKind::Self_ => {
|
|
||||||
if !state.has_class_scope {
|
|
||||||
return Err(ParseError::CannotFindTypeInCurrentScope(
|
|
||||||
state.current.kind.to_string(),
|
|
||||||
state.current.span,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
state.next();
|
|
||||||
|
|
||||||
Expression::Self_
|
|
||||||
}
|
|
||||||
TokenKind::Static => {
|
|
||||||
if !state.has_class_scope {
|
|
||||||
return Err(ParseError::CannotFindTypeInCurrentScope(
|
|
||||||
state.current.kind.to_string(),
|
|
||||||
state.current.span,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
state.next();
|
|
||||||
|
|
||||||
Expression::Static
|
|
||||||
}
|
|
||||||
TokenKind::Parent => {
|
|
||||||
if !state.has_class_scope {
|
|
||||||
return Err(ParseError::CannotFindTypeInCurrentScope(
|
|
||||||
state.current.kind.to_string(),
|
|
||||||
state.current.span,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
state.next();
|
|
||||||
|
|
||||||
Expression::Parent
|
|
||||||
}
|
|
||||||
_ => clone_or_new_precedence(state)?,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut args = vec![];
|
|
||||||
if state.current.kind == TokenKind::LeftParen {
|
|
||||||
args = parameters::args_list(state)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression::New {
|
|
||||||
target: Box::new(target),
|
|
||||||
args,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TokenKind::DirConstant => {
|
|
||||||
state.next();
|
|
||||||
Expression::MagicConst {
|
|
||||||
constant: MagicConst::Dir,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TokenKind::Include
|
|
||||||
| TokenKind::IncludeOnce
|
|
||||||
| TokenKind::Require
|
|
||||||
| TokenKind::RequireOnce => {
|
|
||||||
let kind: IncludeKind = (&state.current.kind).into();
|
|
||||||
state.next();
|
|
||||||
|
|
||||||
let path = lowest_precedence(state)?;
|
|
||||||
|
|
||||||
Expression::Include {
|
|
||||||
kind,
|
|
||||||
path: Box::new(path),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ if is_prefix(&state.current.kind) => {
|
|
||||||
let op = state.current.kind.clone();
|
|
||||||
|
|
||||||
state.next();
|
|
||||||
|
|
||||||
let rpred = Precedence::prefix(&op);
|
|
||||||
let rhs = for_precedence(state, rpred)?;
|
|
||||||
|
|
||||||
prefix(&op, rhs)
|
|
||||||
}
|
|
||||||
TokenKind::Dollar => variables::dynamic_variable(state)?,
|
|
||||||
_ => {
|
|
||||||
return Err(ParseError::UnexpectedToken(
|
|
||||||
state.current.kind.to_string(),
|
|
||||||
state.current.span,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(expr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn postfix(state: &mut State, lhs: Expression, op: &TokenKind) -> Result<Expression, ParseError> {
|
fn postfix(state: &mut State, lhs: Expression, op: &TokenKind) -> Result<Expression, ParseError> {
|
||||||
@ -949,9 +1128,11 @@ fn interpolated_string_part(state: &mut State) -> ParseResult<Option<StringPart>
|
|||||||
e
|
e
|
||||||
}
|
}
|
||||||
TokenKind::Minus => {
|
TokenKind::Minus => {
|
||||||
|
let span = state.current.span;
|
||||||
state.next();
|
state.next();
|
||||||
if let TokenKind::LiteralInteger(i) = &state.current.kind {
|
if let TokenKind::LiteralInteger(i) = &state.current.kind {
|
||||||
let e = Expression::Negate {
|
let e = Expression::Negate {
|
||||||
|
span,
|
||||||
value: Box::new(Expression::LiteralInteger { i: i.clone() }),
|
value: Box::new(Expression::LiteralInteger { i: i.clone() }),
|
||||||
};
|
};
|
||||||
state.next();
|
state.next();
|
||||||
@ -1014,79 +1195,6 @@ fn interpolated_string_part(state: &mut State) -> ParseResult<Option<StringPart>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn is_prefix(op: &TokenKind) -> bool {
|
|
||||||
matches!(
|
|
||||||
op,
|
|
||||||
TokenKind::Bang
|
|
||||||
| TokenKind::Print
|
|
||||||
| TokenKind::BitwiseNot
|
|
||||||
| TokenKind::Decrement
|
|
||||||
| TokenKind::Increment
|
|
||||||
| TokenKind::Minus
|
|
||||||
| TokenKind::Plus
|
|
||||||
| 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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn prefix(op: &TokenKind, rhs: Expression) -> Expression {
|
|
||||||
match op {
|
|
||||||
TokenKind::Print => Expression::Print {
|
|
||||||
value: Box::new(rhs),
|
|
||||||
},
|
|
||||||
TokenKind::Bang => Expression::BooleanNot {
|
|
||||||
value: Box::new(rhs),
|
|
||||||
},
|
|
||||||
TokenKind::Minus => Expression::Negate {
|
|
||||||
value: Box::new(rhs),
|
|
||||||
},
|
|
||||||
TokenKind::Plus => Expression::UnaryPlus {
|
|
||||||
value: Box::new(rhs),
|
|
||||||
},
|
|
||||||
TokenKind::BitwiseNot => Expression::BitwiseNot {
|
|
||||||
value: Box::new(rhs),
|
|
||||||
},
|
|
||||||
TokenKind::Decrement => Expression::PreDecrement {
|
|
||||||
value: Box::new(rhs),
|
|
||||||
},
|
|
||||||
TokenKind::Increment => Expression::PreIncrement {
|
|
||||||
value: Box::new(rhs),
|
|
||||||
},
|
|
||||||
TokenKind::StringCast
|
|
||||||
| TokenKind::BinaryCast
|
|
||||||
| TokenKind::ObjectCast
|
|
||||||
| TokenKind::BoolCast
|
|
||||||
| TokenKind::BooleanCast
|
|
||||||
| TokenKind::IntCast
|
|
||||||
| TokenKind::IntegerCast
|
|
||||||
| TokenKind::FloatCast
|
|
||||||
| TokenKind::DoubleCast
|
|
||||||
| TokenKind::RealCast
|
|
||||||
| TokenKind::UnsetCast
|
|
||||||
| TokenKind::ArrayCast => Expression::Cast {
|
|
||||||
kind: op.into(),
|
|
||||||
value: Box::new(rhs),
|
|
||||||
},
|
|
||||||
TokenKind::At => Expression::ErrorSuppress {
|
|
||||||
expr: Box::new(rhs),
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_infix(t: &TokenKind) -> bool {
|
fn is_infix(t: &TokenKind) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
t,
|
t,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::lexer::token::TokenKind;
|
use crate::lexer::token::TokenKind;
|
||||||
|
use crate::parser;
|
||||||
use crate::parser::ast::Statement;
|
use crate::parser::ast::Statement;
|
||||||
use crate::parser::error::ParseResult;
|
use crate::parser::error::ParseResult;
|
||||||
use crate::parser::expressions;
|
use crate::parser::expressions;
|
||||||
use crate::parser::internal::blocks;
|
use crate::parser::internal::blocks;
|
||||||
use crate::parser::internal::utils;
|
use crate::parser::internal::utils;
|
||||||
use crate::parser::state::State;
|
use crate::parser::state::State;
|
||||||
use crate::parser;
|
|
||||||
|
|
||||||
pub fn foreach_loop(state: &mut State) -> ParseResult<Statement> {
|
pub fn foreach_loop(state: &mut State) -> ParseResult<Statement> {
|
||||||
utils::skip(state, TokenKind::Foreach)?;
|
utils::skip(state, TokenKind::Foreach)?;
|
||||||
@ -175,21 +175,19 @@ pub fn while_loop(state: &mut State) -> ParseResult<Statement> {
|
|||||||
let body = if state.current.kind == TokenKind::SemiColon {
|
let body = if state.current.kind == TokenKind::SemiColon {
|
||||||
utils::skip_semicolon(state)?;
|
utils::skip_semicolon(state)?;
|
||||||
vec![]
|
vec![]
|
||||||
|
} else if state.current.kind == TokenKind::Colon {
|
||||||
|
utils::skip_colon(state)?;
|
||||||
|
let then = blocks::body(state, &TokenKind::EndWhile)?;
|
||||||
|
utils::skip(state, TokenKind::EndWhile)?;
|
||||||
|
utils::skip_semicolon(state)?;
|
||||||
|
then
|
||||||
|
} else if state.current.kind == TokenKind::LeftBrace {
|
||||||
|
utils::skip_left_brace(state)?;
|
||||||
|
let then = blocks::body(state, &TokenKind::RightBrace)?;
|
||||||
|
utils::skip_right_brace(state)?;
|
||||||
|
then
|
||||||
} else {
|
} else {
|
||||||
if state.current.kind == TokenKind::Colon {
|
vec![parser::statement(state)?]
|
||||||
utils::skip_colon(state)?;
|
|
||||||
let then = blocks::body(state, &TokenKind::EndWhile)?;
|
|
||||||
utils::skip(state, TokenKind::EndWhile)?;
|
|
||||||
utils::skip_semicolon(state)?;
|
|
||||||
then
|
|
||||||
} else if state.current.kind == TokenKind::LeftBrace {
|
|
||||||
utils::skip_left_brace(state)?;
|
|
||||||
let then = blocks::body(state, &TokenKind::RightBrace)?;
|
|
||||||
utils::skip_right_brace(state)?;
|
|
||||||
then
|
|
||||||
} else {
|
|
||||||
vec![parser::statement(state)?]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Statement::While { condition, body })
|
Ok(Statement::While { condition, body })
|
||||||
|
@ -41,16 +41,6 @@ pub enum Precedence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Precedence {
|
impl Precedence {
|
||||||
pub fn prefix(kind: &TokenKind) -> Self {
|
|
||||||
use TokenKind::*;
|
|
||||||
|
|
||||||
match kind {
|
|
||||||
Bang => Self::Bang,
|
|
||||||
Clone | New => Self::CloneOrNew,
|
|
||||||
_ => Self::Prefix,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn infix(kind: &TokenKind) -> Self {
|
pub fn infix(kind: &TokenKind) -> Self {
|
||||||
use TokenKind::*;
|
use TokenKind::*;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ pub fn skip_semicolon(state: &mut State) -> ParseResult<Span> {
|
|||||||
return Err(ParseError::ExpectedToken(
|
return Err(ParseError::ExpectedToken(
|
||||||
vec!["`;`".to_string()],
|
vec!["`;`".to_string()],
|
||||||
found,
|
found,
|
||||||
state.current.span,
|
end,
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
state.next();
|
state.next();
|
||||||
|
16
tests/fixtures/0006/ast.txt
vendored
16
tests/fixtures/0006/ast.txt
vendored
@ -1,6 +1,10 @@
|
|||||||
[
|
[
|
||||||
Expression {
|
Expression {
|
||||||
expr: Include {
|
expr: Include {
|
||||||
|
span: (
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
),
|
||||||
kind: Include,
|
kind: Include,
|
||||||
path: LiteralString {
|
path: LiteralString {
|
||||||
value: "foo.php",
|
value: "foo.php",
|
||||||
@ -9,6 +13,10 @@
|
|||||||
},
|
},
|
||||||
Expression {
|
Expression {
|
||||||
expr: Include {
|
expr: Include {
|
||||||
|
span: (
|
||||||
|
5,
|
||||||
|
1,
|
||||||
|
),
|
||||||
kind: IncludeOnce,
|
kind: IncludeOnce,
|
||||||
path: LiteralString {
|
path: LiteralString {
|
||||||
value: "bar.php",
|
value: "bar.php",
|
||||||
@ -17,6 +25,10 @@
|
|||||||
},
|
},
|
||||||
Expression {
|
Expression {
|
||||||
expr: Include {
|
expr: Include {
|
||||||
|
span: (
|
||||||
|
7,
|
||||||
|
1,
|
||||||
|
),
|
||||||
kind: Require,
|
kind: Require,
|
||||||
path: LiteralString {
|
path: LiteralString {
|
||||||
value: "baz.php",
|
value: "baz.php",
|
||||||
@ -25,6 +37,10 @@
|
|||||||
},
|
},
|
||||||
Expression {
|
Expression {
|
||||||
expr: Include {
|
expr: Include {
|
||||||
|
span: (
|
||||||
|
9,
|
||||||
|
1,
|
||||||
|
),
|
||||||
kind: RequireOnce,
|
kind: RequireOnce,
|
||||||
path: LiteralString {
|
path: LiteralString {
|
||||||
value: "qux.php",
|
value: "qux.php",
|
||||||
|
4
tests/fixtures/0010/ast.txt
vendored
4
tests/fixtures/0010/ast.txt
vendored
@ -532,6 +532,10 @@
|
|||||||
Arg {
|
Arg {
|
||||||
name: None,
|
name: None,
|
||||||
value: BitwiseNot {
|
value: BitwiseNot {
|
||||||
|
span: (
|
||||||
|
16,
|
||||||
|
13,
|
||||||
|
),
|
||||||
value: LiteralInteger {
|
value: LiteralInteger {
|
||||||
i: "2",
|
i: "2",
|
||||||
},
|
},
|
||||||
|
4
tests/fixtures/0011/ast.txt
vendored
4
tests/fixtures/0011/ast.txt
vendored
@ -792,6 +792,10 @@
|
|||||||
Arg {
|
Arg {
|
||||||
name: None,
|
name: None,
|
||||||
value: BitwiseNot {
|
value: BitwiseNot {
|
||||||
|
span: (
|
||||||
|
16,
|
||||||
|
13,
|
||||||
|
),
|
||||||
value: Variable(
|
value: Variable(
|
||||||
Variable {
|
Variable {
|
||||||
start: (
|
start: (
|
||||||
|
16
tests/fixtures/0017/ast.txt
vendored
16
tests/fixtures/0017/ast.txt
vendored
@ -50,6 +50,10 @@
|
|||||||
),
|
),
|
||||||
op: Assign,
|
op: Assign,
|
||||||
rhs: UnaryPlus {
|
rhs: UnaryPlus {
|
||||||
|
span: (
|
||||||
|
4,
|
||||||
|
6,
|
||||||
|
),
|
||||||
value: LiteralInteger {
|
value: LiteralInteger {
|
||||||
i: "1",
|
i: "1",
|
||||||
},
|
},
|
||||||
@ -73,6 +77,10 @@
|
|||||||
),
|
),
|
||||||
op: Assign,
|
op: Assign,
|
||||||
rhs: BitwiseNot {
|
rhs: BitwiseNot {
|
||||||
|
span: (
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
),
|
||||||
value: LiteralInteger {
|
value: LiteralInteger {
|
||||||
i: "2",
|
i: "2",
|
||||||
},
|
},
|
||||||
@ -96,6 +104,10 @@
|
|||||||
),
|
),
|
||||||
op: Assign,
|
op: Assign,
|
||||||
rhs: PreDecrement {
|
rhs: PreDecrement {
|
||||||
|
span: (
|
||||||
|
6,
|
||||||
|
6,
|
||||||
|
),
|
||||||
value: Variable(
|
value: Variable(
|
||||||
Variable {
|
Variable {
|
||||||
start: (
|
start: (
|
||||||
@ -129,6 +141,10 @@
|
|||||||
),
|
),
|
||||||
op: Assign,
|
op: Assign,
|
||||||
rhs: PreIncrement {
|
rhs: PreIncrement {
|
||||||
|
span: (
|
||||||
|
7,
|
||||||
|
6,
|
||||||
|
),
|
||||||
value: Variable(
|
value: Variable(
|
||||||
Variable {
|
Variable {
|
||||||
start: (
|
start: (
|
||||||
|
4
tests/fixtures/0072/ast.txt
vendored
4
tests/fixtures/0072/ast.txt
vendored
@ -1,6 +1,10 @@
|
|||||||
[
|
[
|
||||||
Expression {
|
Expression {
|
||||||
expr: ErrorSuppress {
|
expr: ErrorSuppress {
|
||||||
|
span: (
|
||||||
|
1,
|
||||||
|
7,
|
||||||
|
),
|
||||||
expr: Call {
|
expr: Call {
|
||||||
target: Identifier(
|
target: Identifier(
|
||||||
Identifier {
|
Identifier {
|
||||||
|
4
tests/fixtures/0103/ast.txt
vendored
4
tests/fixtures/0103/ast.txt
vendored
@ -1,6 +1,10 @@
|
|||||||
[
|
[
|
||||||
Expression {
|
Expression {
|
||||||
expr: Print {
|
expr: Print {
|
||||||
|
span: (
|
||||||
|
1,
|
||||||
|
7,
|
||||||
|
),
|
||||||
value: Variable(
|
value: Variable(
|
||||||
Variable {
|
Variable {
|
||||||
start: (
|
start: (
|
||||||
|
10
tests/fixtures/0237/ast.txt
vendored
10
tests/fixtures/0237/ast.txt
vendored
@ -1,10 +1,18 @@
|
|||||||
[
|
[
|
||||||
Expression {
|
Expression {
|
||||||
expr: Include {
|
expr: Include {
|
||||||
|
span: (
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
),
|
||||||
kind: Require,
|
kind: Require,
|
||||||
path: Infix {
|
path: Infix {
|
||||||
lhs: MagicConst {
|
lhs: MagicConst {
|
||||||
constant: Dir,
|
span: (
|
||||||
|
3,
|
||||||
|
9,
|
||||||
|
),
|
||||||
|
constant: Directory,
|
||||||
},
|
},
|
||||||
op: Concat,
|
op: Concat,
|
||||||
rhs: LiteralString {
|
rhs: LiteralString {
|
||||||
|
10
tests/fixtures/0238/ast.txt
vendored
10
tests/fixtures/0238/ast.txt
vendored
@ -16,10 +16,18 @@
|
|||||||
),
|
),
|
||||||
op: Assign,
|
op: Assign,
|
||||||
rhs: Include {
|
rhs: Include {
|
||||||
|
span: (
|
||||||
|
3,
|
||||||
|
8,
|
||||||
|
),
|
||||||
kind: Require,
|
kind: Require,
|
||||||
path: Infix {
|
path: Infix {
|
||||||
lhs: MagicConst {
|
lhs: MagicConst {
|
||||||
constant: Dir,
|
span: (
|
||||||
|
3,
|
||||||
|
16,
|
||||||
|
),
|
||||||
|
constant: Directory,
|
||||||
},
|
},
|
||||||
op: Concat,
|
op: Concat,
|
||||||
rhs: LiteralString {
|
rhs: LiteralString {
|
||||||
|
4
tests/fixtures/0269/ast.txt
vendored
4
tests/fixtures/0269/ast.txt
vendored
@ -219,6 +219,10 @@
|
|||||||
[
|
[
|
||||||
Expression {
|
Expression {
|
||||||
expr: Print {
|
expr: Print {
|
||||||
|
span: (
|
||||||
|
11,
|
||||||
|
5,
|
||||||
|
),
|
||||||
value: Infix {
|
value: Infix {
|
||||||
lhs: Variable(
|
lhs: Variable(
|
||||||
Variable {
|
Variable {
|
||||||
|
74
tests/fixtures/0276 copy/ast.txt
vendored
Normal file
74
tests/fixtures/0276 copy/ast.txt
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
[
|
||||||
|
Expression {
|
||||||
|
expr: MagicConst {
|
||||||
|
span: (
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
constant: Directory,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expression {
|
||||||
|
expr: MagicConst {
|
||||||
|
span: (
|
||||||
|
4,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
constant: File,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expression {
|
||||||
|
expr: MagicConst {
|
||||||
|
span: (
|
||||||
|
5,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
constant: Line,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expression {
|
||||||
|
expr: MagicConst {
|
||||||
|
span: (
|
||||||
|
6,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
constant: Namespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expression {
|
||||||
|
expr: MagicConst {
|
||||||
|
span: (
|
||||||
|
7,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
constant: Class,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expression {
|
||||||
|
expr: MagicConst {
|
||||||
|
span: (
|
||||||
|
8,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
constant: Method,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expression {
|
||||||
|
expr: MagicConst {
|
||||||
|
span: (
|
||||||
|
9,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
constant: Trait,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Expression {
|
||||||
|
expr: MagicConst {
|
||||||
|
span: (
|
||||||
|
10,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
constant: Function,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
10
tests/fixtures/0276 copy/code.php
vendored
Normal file
10
tests/fixtures/0276 copy/code.php
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
__DIR__;
|
||||||
|
__FILE__;
|
||||||
|
__LINE__;
|
||||||
|
__NAMESPACE__;
|
||||||
|
__CLASS__;
|
||||||
|
__METHOD__;
|
||||||
|
__TRAIT__;
|
||||||
|
__FUNCTION__;
|
Loading…
Reference in New Issue
Block a user