mirror of
https://github.com/danog/parser.git
synced 2024-11-27 04:14:55 +01:00
parser: support enums
This commit is contained in:
parent
63d3c4bffd
commit
f488e584bd
17
phpast/samples/enum.php
Normal file
17
phpast/samples/enum.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
enum Foo {
|
||||||
|
case Bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Bar: string {
|
||||||
|
case Baz = 'car';
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Baz: int {
|
||||||
|
case Caz = 'boo';
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Foo implements Bob {
|
||||||
|
|
||||||
|
}
|
@ -240,9 +240,25 @@ pub enum Statement {
|
|||||||
catches: Vec<Catch>,
|
catches: Vec<Catch>,
|
||||||
finally: Option<Block>,
|
finally: Option<Block>,
|
||||||
},
|
},
|
||||||
|
Enum {
|
||||||
|
name: Identifier,
|
||||||
|
implements: Vec<Identifier>,
|
||||||
|
backed_type: Option<BackedEnumType>,
|
||||||
|
body: Block,
|
||||||
|
},
|
||||||
|
EnumCase {
|
||||||
|
name: Identifier,
|
||||||
|
value: Option<Expression>,
|
||||||
|
},
|
||||||
Noop,
|
Noop,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||||
|
pub enum BackedEnumType {
|
||||||
|
String,
|
||||||
|
Int,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||||
pub struct Case {
|
pub struct Case {
|
||||||
pub condition: Option<Expression>,
|
pub condition: Option<Expression>,
|
||||||
|
@ -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::{ArrayItem, Use, MethodFlag, ClassFlag, ElseIf, UseKind, MagicConst}, Identifier, Type, MatchArm, Catch, Case};
|
use crate::{Program, Statement, Block, Expression, ast::{ArrayItem, Use, MethodFlag, ClassFlag, ElseIf, UseKind, MagicConst, BackedEnumType}, Identifier, Type, MatchArm, Catch, Case};
|
||||||
|
|
||||||
type ParseResult<T> = Result<T, ParseError>;
|
type ParseResult<T> = Result<T, ParseError>;
|
||||||
|
|
||||||
@ -342,6 +342,75 @@ impl Parser {
|
|||||||
|
|
||||||
Statement::Interface { name: name.into(), extends, body }
|
Statement::Interface { name: name.into(), extends, body }
|
||||||
},
|
},
|
||||||
|
TokenKind::Enum if matches!(self.peek.kind, TokenKind::Identifier(_)) => {
|
||||||
|
self.next();
|
||||||
|
|
||||||
|
let name = self.ident()?;
|
||||||
|
|
||||||
|
let mut is_backed = false;
|
||||||
|
let backed_type: Option<BackedEnumType> = if self.current.kind == TokenKind::Colon {
|
||||||
|
expect!(self, TokenKind::Colon, "expected :");
|
||||||
|
|
||||||
|
match self.current.kind.clone() {
|
||||||
|
TokenKind::Identifier(s) if s == String::from("string") || s == String::from("int") => {
|
||||||
|
self.next();
|
||||||
|
|
||||||
|
is_backed = true;
|
||||||
|
|
||||||
|
Some(match s.as_str() {
|
||||||
|
"string" => BackedEnumType::String,
|
||||||
|
"int" => BackedEnumType::Int,
|
||||||
|
_ => unreachable!()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
_ => return Err(ParseError::UnexpectedToken(self.current.kind.to_string(), self.current.span))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut implements = Vec::new();
|
||||||
|
if self.current.kind == TokenKind::Implements {
|
||||||
|
self.next();
|
||||||
|
|
||||||
|
while self.current.kind != TokenKind::LeftBrace {
|
||||||
|
implements.push(self.full_name()?.into());
|
||||||
|
|
||||||
|
self.optional_comma()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.lbrace()?;
|
||||||
|
|
||||||
|
let mut body = Block::new();
|
||||||
|
while self.current.kind != TokenKind::RightBrace {
|
||||||
|
match self.current.kind {
|
||||||
|
TokenKind::Case => {
|
||||||
|
self.next();
|
||||||
|
|
||||||
|
let name = self.ident()?;
|
||||||
|
let mut value = None;
|
||||||
|
|
||||||
|
if is_backed {
|
||||||
|
expect!(self, TokenKind::Equals, "expected =");
|
||||||
|
|
||||||
|
value = Some(self.expression(0)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.semi()?;
|
||||||
|
|
||||||
|
body.push(Statement::EnumCase { name: name.into(), value })
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
body.push(self.class_statement()?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rbrace()?;
|
||||||
|
|
||||||
|
Statement::Enum { name: name.into(), backed_type, implements, body }
|
||||||
|
},
|
||||||
TokenKind::Use => {
|
TokenKind::Use => {
|
||||||
self.next();
|
self.next();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user