mirror of
https://github.com/danog/parser.git
synced 2024-11-26 20:04:57 +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>,
|
||||
finally: Option<Block>,
|
||||
},
|
||||
Enum {
|
||||
name: Identifier,
|
||||
implements: Vec<Identifier>,
|
||||
backed_type: Option<BackedEnumType>,
|
||||
body: Block,
|
||||
},
|
||||
EnumCase {
|
||||
name: Identifier,
|
||||
value: Option<Expression>,
|
||||
},
|
||||
Noop,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
pub enum BackedEnumType {
|
||||
String,
|
||||
Int,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
pub struct Case {
|
||||
pub condition: Option<Expression>,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::{vec::IntoIter, fmt::{Display}};
|
||||
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>;
|
||||
|
||||
@ -342,6 +342,75 @@ impl Parser {
|
||||
|
||||
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 => {
|
||||
self.next();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user