Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ dump file:
cargo run --bin php-parser-rs -- {{file}}

# run all integration tests, except third-party.
test filter='':
cargo test --all {{filter}} -- --skip third_party
test filter='-- --skip third_party':
cargo test --all {{filter}}

# run integration tests for third party libraries.
test-third-party:
Expand Down
26 changes: 13 additions & 13 deletions src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1588,7 +1588,7 @@ fn parse_int(buffer: &[u8]) -> SyntaxResult<TokenKind> {
}

fn identifier_to_keyword(ident: &[u8]) -> Option<TokenKind> {
Some(match ident {
Some(match ident.to_ascii_lowercase().as_slice() {
b"enddeclare" => TokenKind::EndDeclare,
b"endswitch" => TokenKind::EndSwitch,
b"endfor" => TokenKind::EndFor,
Expand All @@ -1600,7 +1600,7 @@ fn identifier_to_keyword(ident: &[u8]) -> Option<TokenKind> {
b"or" => TokenKind::LogicalOr,
b"xor" => TokenKind::LogicalXor,
b"print" => TokenKind::Print,
b"__halt_compiler" | b"__HALT_COMPILER" => TokenKind::HaltCompiler,
b"__halt_compiler" => TokenKind::HaltCompiler,
b"readonly" => TokenKind::Readonly,
b"global" => TokenKind::Global,
b"match" => TokenKind::Match,
Expand All @@ -1622,7 +1622,7 @@ fn identifier_to_keyword(ident: &[u8]) -> Option<TokenKind> {
b"elseif" => TokenKind::ElseIf,
b"enum" => TokenKind::Enum,
b"extends" => TokenKind::Extends,
b"false" | b"FALSE" => TokenKind::False,
b"false" => TokenKind::False,
b"final" => TokenKind::Final,
b"finally" => TokenKind::Finally,
b"fn" => TokenKind::Fn,
Expand All @@ -1638,7 +1638,7 @@ fn identifier_to_keyword(ident: &[u8]) -> Option<TokenKind> {
b"instanceof" => TokenKind::Instanceof,
b"namespace" => TokenKind::Namespace,
b"new" => TokenKind::New,
b"null" | b"NULL" => TokenKind::Null,
b"null" => TokenKind::Null,
b"private" => TokenKind::Private,
b"protected" => TokenKind::Protected,
b"public" => TokenKind::Public,
Expand All @@ -1649,19 +1649,19 @@ fn identifier_to_keyword(ident: &[u8]) -> Option<TokenKind> {
b"switch" => TokenKind::Switch,
b"throw" => TokenKind::Throw,
b"trait" => TokenKind::Trait,
b"true" | b"TRUE" => TokenKind::True,
b"true" => TokenKind::True,
b"try" => TokenKind::Try,
b"use" => TokenKind::Use,
b"var" => TokenKind::Var,
b"yield" => TokenKind::Yield,
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"__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"insteadof" => TokenKind::Insteadof,
b"list" => TokenKind::List,
Expand Down
4 changes: 3 additions & 1 deletion src/parser/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub enum ParseError {
CannotAssignReferenceToNonReferencableValue(Span),
CannotMixKeyedAndUnkeyedEntries(Span),
CannotUsePositionalArgumentAfterNamedArgument(Span),
CannotUseReservedKeywordAsATypeName(String, Span),
}

impl From<SyntaxError> for ParseError {
Expand Down Expand Up @@ -127,7 +128,8 @@ impl Display for ParseError {
Self::IllegalSpreadOperator(span) => write!(f, "Parse Error: Cannot use spread operator on line {} column {}.", span.0, span.1),
Self::CannotAssignReferenceToNonReferencableValue(span) => write!(f, "Parse Error: cannot assign reference to non-referencable value on line {} column {}", span.0, span.1),
Self::CannotMixKeyedAndUnkeyedEntries(span) => write!(f, "Parse Error: cannot mix keyed and un-keyed entries on line {}", span.0),
Self::CannotUsePositionalArgumentAfterNamedArgument(span) => write!(f, "Parse Error: cannot use positional argument after named argument on line {}", span.0),
Self::CannotUsePositionalArgumentAfterNamedArgument(span) => write!(f, "Parse Error: cannot use positional argument after named argument on line {} column {}", span.0, span.1),
Self::CannotUseReservedKeywordAsATypeName(ty, span) => write!(f, "Parse Error: cannot use `{}` as a type name as it is reserved on line {} column {}", ty, span.0, span.1)
}
}
}
22 changes: 15 additions & 7 deletions src/parser/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ fn for_precedence(state: &mut State, precedence: Precedence) -> ParseResult<Expr
}

state.next();
state.skip_comments();

left =
match kind {
Expand Down Expand Up @@ -535,7 +536,7 @@ expressions! {
| TokenKind::Enum | TokenKind::From
), peek(TokenKind::LeftParen)]
reserved_identifier_function_call(|state: &mut State| {
let ident = identifiers::ident_maybe_soft_reserved(state)?;
let ident = identifiers::identifier_maybe_soft_reserved(state)?;
let lhs = Expression::Identifier(Identifier::SimpleIdentifier(ident));

postfix(state, lhs, &TokenKind::LeftParen)
Expand Down Expand Up @@ -1004,6 +1005,7 @@ fn postfix(state: &mut State, lhs: Expression, op: &TokenKind) -> Result<Express
Ok(match op {
TokenKind::Coalesce => {
state.next();
state.skip_comments();

let rhs = null_coalesce_precedence(state)?;

Expand All @@ -1013,6 +1015,7 @@ fn postfix(state: &mut State, lhs: Expression, op: &TokenKind) -> Result<Express
}
}
TokenKind::LeftParen => {
state.skip_comments();
let args = parameters::args_list(state)?;

Expression::Call {
Expand All @@ -1022,6 +1025,7 @@ fn postfix(state: &mut State, lhs: Expression, op: &TokenKind) -> Result<Express
}
TokenKind::LeftBracket => {
utils::skip_left_bracket(state)?;
state.skip_comments();

if state.current.kind == TokenKind::RightBracket {
state.next();
Expand All @@ -1043,16 +1047,17 @@ fn postfix(state: &mut State, lhs: Expression, op: &TokenKind) -> Result<Express
}
TokenKind::DoubleColon => {
utils::skip_double_colon(state)?;
state.skip_comments();

let mut must_be_method_call = false;

let property = match state.current.kind.clone() {
TokenKind::Variable(_) | TokenKind::Dollar | TokenKind::DollarLeftBrace => {
Expression::Variable(variables::dynamic_variable(state)?)
}
_ if identifiers::is_ident_maybe_reserved(&state.current.kind) => {
_ if identifiers::is_identifier_maybe_reserved(&state.current.kind) => {
Expression::Identifier(Identifier::SimpleIdentifier(
identifiers::ident_maybe_reserved(state)?,
identifiers::identifier_maybe_reserved(state)?,
))
}
TokenKind::LeftBrace => {
Expand Down Expand Up @@ -1117,14 +1122,15 @@ fn postfix(state: &mut State, lhs: Expression, op: &TokenKind) -> Result<Express
}
TokenKind::Arrow | TokenKind::NullsafeArrow => {
state.next();
state.skip_comments();

let property = match state.current.kind {
TokenKind::Variable(_) | TokenKind::Dollar | TokenKind::DollarLeftBrace => {
Expression::Variable(variables::dynamic_variable(state)?)
}
_ if identifiers::is_ident_maybe_reserved(&state.current.kind) => {
_ if identifiers::is_identifier_maybe_reserved(&state.current.kind) => {
Expression::Identifier(Identifier::SimpleIdentifier(
identifiers::ident_maybe_reserved(state)?,
identifiers::identifier_maybe_reserved(state)?,
))
}
TokenKind::LeftBrace => {
Expand Down Expand Up @@ -1177,6 +1183,7 @@ fn postfix(state: &mut State, lhs: Expression, op: &TokenKind) -> Result<Express
TokenKind::Increment => {
let span = state.current.span;
state.next();
state.skip_comments();

Expression::ArithmeticOperation(ArithmeticOperation::PostIncrement {
left: Box::new(lhs),
Expand All @@ -1186,6 +1193,7 @@ fn postfix(state: &mut State, lhs: Expression, op: &TokenKind) -> Result<Express
TokenKind::Decrement => {
let span = state.current.span;
state.next();
state.skip_comments();

Expression::ArithmeticOperation(ArithmeticOperation::PostDecrement {
left: Box::new(lhs),
Expand Down Expand Up @@ -1486,7 +1494,7 @@ fn interpolated_string_part(state: &mut State) -> ParseResult<Option<StringPart>
Expression::PropertyFetch {
target: Box::new(variable),
property: Box::new(Expression::Identifier(Identifier::SimpleIdentifier(
identifiers::ident_maybe_reserved(state)?,
identifiers::identifier_maybe_reserved(state)?,
))),
}
}
Expand All @@ -1495,7 +1503,7 @@ fn interpolated_string_part(state: &mut State) -> ParseResult<Option<StringPart>
Expression::NullsafePropertyFetch {
target: Box::new(variable),
property: Box::new(Expression::Identifier(Identifier::SimpleIdentifier(
identifiers::ident_maybe_reserved(state)?,
identifiers::identifier_maybe_reserved(state)?,
))),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/parser/internal/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn parse(state: &mut State) -> ParseResult<Statement> {

let start = utils::skip(state, TokenKind::Class)?;

let name = identifiers::ident(state)?;
let name = identifiers::type_identifier(state)?;

let extends = if state.current.kind == TokenKind::Extends {
let span = state.current.span;
Expand Down
4 changes: 2 additions & 2 deletions src/parser/internal/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn parse(state: &mut State) -> ParseResult<Constant> {
let mut entries = vec![];

loop {
let name = identifiers::ident(state)?;
let name = identifiers::identifier(state)?;

utils::skip(state, TokenKind::Equals)?;

Expand Down Expand Up @@ -52,7 +52,7 @@ pub fn classish(
let mut entries = vec![];

loop {
let name = identifiers::ident_maybe_soft_reserved(state)?;
let name = identifiers::identifier_maybe_soft_reserved(state)?;

utils::skip(state, TokenKind::Equals)?;

Expand Down
7 changes: 7 additions & 0 deletions src/parser/internal/data_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ fn optional_simple_data_type(state: &mut State) -> ParseResult<Option<Type>> {

Ok(Some(Type::ParentReference))
}
TokenKind::Enum | TokenKind::From => {
let span = state.current.span;
let name = state.current.kind.to_string().into();
state.next();

Ok(Some(Type::Identifier(SimpleIdentifier { span, name })))
}
TokenKind::Identifier(id) => {
let span = state.current.span;
state.next();
Expand Down
8 changes: 4 additions & 4 deletions src/parser/internal/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ pub fn parse(state: &mut State) -> ParseResult<Statement> {

utils::skip(state, TokenKind::Enum)?;

let name = identifiers::ident(state)?;
let name = identifiers::identifier(state)?;

let backed_type: Option<BackedEnumType> = if state.current.kind == TokenKind::Colon {
utils::skip_colon(state)?;

let identifier = identifiers::ident_of(state, &["string", "int"])?;
let identifier = identifiers::identifier_of(state, &["string", "int"])?;
Some(match &identifier.name[..] {
b"string" => BackedEnumType::String(identifier.span),
b"int" => BackedEnumType::Int(identifier.span),
Expand Down Expand Up @@ -111,7 +111,7 @@ fn unit_member(state: &mut State, enum_name: String) -> ParseResult<UnitEnumMemb
let start = state.current.span;
state.next();

let name = identifiers::ident(state)?;
let name = identifiers::type_identifier(state)?;

if state.current.kind == TokenKind::Equals {
return Err(ParseError::CaseValueForUnitEnum(
Expand Down Expand Up @@ -150,7 +150,7 @@ fn backed_member(state: &mut State, enum_name: String) -> ParseResult<BackedEnum
let start = state.current.span;
state.next();

let name = identifiers::ident(state)?;
let name = identifiers::identifier(state)?;

if state.current.kind == TokenKind::SemiColon {
return Err(ParseError::MissingCaseValueForBackedEnum(
Expand Down
4 changes: 2 additions & 2 deletions src/parser/internal/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub fn function(state: &mut State) -> ParseResult<Statement> {
false
};

let name = identifiers::ident_maybe_soft_reserved(state)?;
let name = identifiers::identifier_maybe_soft_reserved(state)?;

// get attributes before processing parameters, otherwise
// parameters will steal attributes of this function.
Expand Down Expand Up @@ -219,7 +219,7 @@ pub fn method(state: &mut State, modifiers: MethodModifierGroup) -> ParseResult<
false
};

let name = identifiers::ident_maybe_reserved(state)?;
let name = identifiers::identifier_maybe_reserved(state)?;

let has_body = expected_scope!([
Scope::Class(_, class_modifiers, _) => {
Expand Down
4 changes: 2 additions & 2 deletions src/parser/internal/goto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::parser::internal::utils;
use crate::parser::state::State;

pub fn label_statement(state: &mut State) -> ParseResult<Statement> {
let label = identifiers::ident(state)?;
let label = identifiers::identifier(state)?;

utils::skip_colon(state)?;

Expand All @@ -16,7 +16,7 @@ pub fn label_statement(state: &mut State) -> ParseResult<Statement> {
pub fn goto_statement(state: &mut State) -> ParseResult<Statement> {
utils::skip(state, TokenKind::Goto)?;

let label = identifiers::ident(state)?;
let label = identifiers::identifier(state)?;

utils::skip_semicolon(state)?;

Expand Down
Loading