mirror of
https://github.com/danog/parser.git
synced 2025-01-22 21:11:55 +01:00
parser: support class extends and implements
This commit is contained in:
parent
a8a29a0e7c
commit
33fc8c6b0e
@ -61,6 +61,8 @@ pub enum Statement {
|
|||||||
},
|
},
|
||||||
Class {
|
Class {
|
||||||
name: Identifier,
|
name: Identifier,
|
||||||
|
extends: Option<Identifier>,
|
||||||
|
implements: Vec<Identifier>,
|
||||||
body: Block,
|
body: Block,
|
||||||
},
|
},
|
||||||
Method {
|
Method {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::{vec::IntoIter, fmt::Display};
|
use std::{vec::IntoIter, fmt::Display};
|
||||||
use trunk_lexer::{Token, TokenKind, Span};
|
use trunk_lexer::{Token, TokenKind, Span};
|
||||||
use crate::{Program, Statement, Block, Expression, ast::MethodFlag};
|
use crate::{Program, Statement, Block, Expression, ast::MethodFlag, Identifier};
|
||||||
|
|
||||||
macro_rules! expect {
|
macro_rules! expect {
|
||||||
($parser:expr, $expected:pat, $out:expr, $message:literal) => {
|
($parser:expr, $expected:pat, $out:expr, $message:literal) => {
|
||||||
@ -73,6 +73,26 @@ impl Parser {
|
|||||||
self.next();
|
self.next();
|
||||||
|
|
||||||
let name = expect!(self, TokenKind::Identifier(i), i, "expected class name");
|
let name = expect!(self, TokenKind::Identifier(i), i, "expected class name");
|
||||||
|
let mut extends: Option<Identifier> = None;
|
||||||
|
|
||||||
|
if self.current.kind == TokenKind::Extends {
|
||||||
|
self.next();
|
||||||
|
extends = expect!(self, TokenKind::Identifier(i), Some(i.into()), "expected identifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut implements = Vec::new();
|
||||||
|
if self.current.kind == TokenKind::Implements {
|
||||||
|
self.next();
|
||||||
|
|
||||||
|
while self.current.kind != TokenKind::LeftBrace {
|
||||||
|
if self.current.kind == TokenKind::Comma {
|
||||||
|
self.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
implements.push(expect!(self, TokenKind::Identifier(i), i.into(), "expected identifier"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
expect!(self, TokenKind::LeftBrace, "expected left-brace");
|
expect!(self, TokenKind::LeftBrace, "expected left-brace");
|
||||||
|
|
||||||
let mut body = Vec::new();
|
let mut body = Vec::new();
|
||||||
@ -90,7 +110,7 @@ impl Parser {
|
|||||||
|
|
||||||
expect!(self, TokenKind::RightBrace, "expected right-brace");
|
expect!(self, TokenKind::RightBrace, "expected right-brace");
|
||||||
|
|
||||||
Statement::Class { name: name.into(), body }
|
Statement::Class { name: name.into(), extends, implements, body }
|
||||||
},
|
},
|
||||||
TokenKind::Echo => {
|
TokenKind::Echo => {
|
||||||
self.next();
|
self.next();
|
||||||
@ -348,12 +368,24 @@ mod tests {
|
|||||||
Statement::Class {
|
Statement::Class {
|
||||||
name: $name.to_string().into(),
|
name: $name.to_string().into(),
|
||||||
body: vec![],
|
body: vec![],
|
||||||
|
extends: None,
|
||||||
|
implements: vec![],
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($name:literal, $body:expr) => {
|
($name:literal, $body:expr) => {
|
||||||
Statement::Class {
|
Statement::Class {
|
||||||
name: $name.to_string().into(),
|
name: $name.to_string().into(),
|
||||||
body: $body.to_vec(),
|
body: $body.to_vec(),
|
||||||
|
extends: None,
|
||||||
|
implements: vec![],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($name:literal, $extends:expr, $implements:expr, $body:expr) => {
|
||||||
|
Statement::Class {
|
||||||
|
name: $name.to_string().into(),
|
||||||
|
body: $body.to_vec(),
|
||||||
|
extends: $extends,
|
||||||
|
implements: $implements.to_vec(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -507,6 +539,28 @@ mod tests {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn class_with_extends() {
|
||||||
|
assert_ast("\
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Foo extends Bar {}
|
||||||
|
", &[
|
||||||
|
class!("Foo", Some("Bar".to_string().into()), &[], &[]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn class_with_implements() {
|
||||||
|
assert_ast("\
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Foo implements Bar, Baz {}
|
||||||
|
", &[
|
||||||
|
class!("Foo", None, &["Bar".to_string().into(), "Baz".to_string().into()], &[]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
fn assert_ast(source: &str, expected: &[Statement]) {
|
fn assert_ast(source: &str, expected: &[Statement]) {
|
||||||
let mut lexer = Lexer::new(None);
|
let mut lexer = Lexer::new(None);
|
||||||
let tokens = lexer.tokenize(source).unwrap();
|
let tokens = lexer.tokenize(source).unwrap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user