mirror of
https://github.com/danog/parser.git
synced 2024-11-27 04:14:55 +01:00
Merge pull request #64 from ryangjchandler/feature/readonly-classes
This commit is contained in:
commit
736964de7a
@ -836,6 +836,7 @@ impl Lexer {
|
||||
#[allow(dead_code)]
|
||||
fn identifier_to_keyword(ident: &[u8]) -> Option<TokenKind> {
|
||||
Some(match ident {
|
||||
b"readonly" => TokenKind::Readonly,
|
||||
b"global" => TokenKind::Global,
|
||||
b"match" => TokenKind::Match,
|
||||
b"abstract" => TokenKind::Abstract,
|
||||
@ -949,7 +950,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn keywords() {
|
||||
assert_tokens("<?php function if else elseif echo return class extends implements public protected private static null NULL true TRUE false FALSE use const namespace interface new foreach instanceof", &[
|
||||
assert_tokens("<?php function if else elseif echo return class extends implements public protected private static null NULL true TRUE false FALSE use const namespace interface new foreach instanceof readonly", &[
|
||||
open!(),
|
||||
TokenKind::Function,
|
||||
TokenKind::If,
|
||||
@ -977,6 +978,7 @@ mod tests {
|
||||
TokenKind::New,
|
||||
TokenKind::Foreach,
|
||||
TokenKind::Instanceof,
|
||||
TokenKind::Readonly,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ pub enum OpenTagKind {
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum TokenKind {
|
||||
Readonly,
|
||||
Global,
|
||||
Abstract,
|
||||
Ampersand,
|
||||
@ -169,6 +170,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::Readonly => "readonly",
|
||||
Self::AsteriskEqual => "*=",
|
||||
Self::ObjectCast => "(object)",
|
||||
Self::Abstract => "abstract",
|
||||
|
@ -118,6 +118,7 @@ impl From<TokenKind> for MethodFlag {
|
||||
pub enum ClassFlag {
|
||||
Final,
|
||||
Abstract,
|
||||
Readonly,
|
||||
}
|
||||
|
||||
impl From<TokenKind> for ClassFlag {
|
||||
@ -125,6 +126,7 @@ impl From<TokenKind> for ClassFlag {
|
||||
match k {
|
||||
TokenKind::Final => Self::Final,
|
||||
TokenKind::Abstract => Self::Abstract,
|
||||
TokenKind::Readonly => Self::Readonly,
|
||||
_ => unreachable!("token {:?} can't be converted into class flag.", k),
|
||||
}
|
||||
}
|
||||
|
@ -416,6 +416,26 @@ impl Parser {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
TokenKind::Readonly if self.peek.kind == TokenKind::Class => {
|
||||
self.next();
|
||||
|
||||
match self.class()? {
|
||||
Statement::Class {
|
||||
name,
|
||||
extends,
|
||||
implements,
|
||||
body,
|
||||
..
|
||||
} => Statement::Class {
|
||||
name,
|
||||
extends,
|
||||
implements,
|
||||
body,
|
||||
flag: Some(ClassFlag::Readonly),
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
TokenKind::Trait => {
|
||||
self.next();
|
||||
|
||||
@ -2193,8 +2213,8 @@ mod tests {
|
||||
use super::Parser;
|
||||
use crate::{
|
||||
ast::{
|
||||
Arg, ArrayItem, Case, Constant, DeclareItem, ElseIf, IncludeKind, InfixOp, MethodFlag,
|
||||
PropertyFlag,
|
||||
Arg, ArrayItem, Case, ClassFlag, Constant, DeclareItem, ElseIf, IncludeKind, InfixOp,
|
||||
MethodFlag, PropertyFlag,
|
||||
},
|
||||
Catch, Expression, Identifier, Param, Statement, Type,
|
||||
};
|
||||
@ -3515,6 +3535,20 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn readonly_classes() {
|
||||
assert_ast(
|
||||
"<?php readonly class Foo {}",
|
||||
&[Statement::Class {
|
||||
name: "Foo".as_bytes().into(),
|
||||
extends: None,
|
||||
implements: vec![],
|
||||
body: vec![],
|
||||
flag: Some(ClassFlag::Readonly),
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
||||
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