use super::super::expr::errors::{ParseError, ParseResult};
use super::*;
impl Parser {
pub(crate) fn parse_enum_decl(&mut self, exported: bool, const_: bool) -> ParseResult<IrNode> {
let start_byte = self.current_byte_offset();
let const_ = if self.at(SyntaxKind::ConstKw) {
self.consume();
self.skip_whitespace();
true
} else {
const_
};
if !self.at(SyntaxKind::EnumKw) {
return Err(ParseError::unexpected_eof(
self.current_byte_offset(),
"enum keyword",
))
.map_err(|e| e.with_context("parsing enum declaration"));
}
self.consume().ok_or_else(|| {
ParseError::unexpected_eof(self.current_byte_offset(), "enum keyword")
})?;
self.skip_whitespace();
let name = self.parse_ts_ident_or_placeholder().ok_or_else(|| {
ParseError::unexpected_eof(self.current_byte_offset(), "enum name")
.with_context("parsing enum declaration")
})?;
self.skip_whitespace();
if !self.at(SyntaxKind::LBrace) {
return Err(ParseError::new(
ParseErrorKind::UnexpectedToken,
self.current_byte_offset(),
)
.with_context("expected '{' for enum body"));
}
self.consume(); self.skip_whitespace();
let members = self.parse_enum_members()?;
self.skip_whitespace();
self.expect(SyntaxKind::RBrace);
Ok(IrNode::EnumDecl {
span: IrSpan::new(start_byte, self.current_byte_offset()),
exported,
declare: false,
const_,
name: Box::new(name),
members,
})
}
fn parse_enum_members(&mut self) -> ParseResult<Vec<IrNode>> {
let mut members = Vec::new();
while !self.at_eof() && !self.at(SyntaxKind::RBrace) {
self.skip_whitespace();
if self.at(SyntaxKind::RBrace) {
break;
}
if let Some(kind) = self.current_kind() {
match kind {
SyntaxKind::BraceHashIf
| SyntaxKind::BraceHashFor
| SyntaxKind::BraceHashWhile
| SyntaxKind::BraceHashMatch => {
members.push(self.parse_control_block(kind)?);
continue;
}
_ => {}
}
}
if self.at(SyntaxKind::DollarOpen) {
if let Some(node) = self.parse_directive() {
members.push(node);
}
continue;
}
match self.parse_enum_member() {
Ok(member) => members.push(member),
Err(e) => {
if self.at(SyntaxKind::Comma) || self.at(SyntaxKind::RBrace) {
} else {
return Err(e.with_context("parsing enum members"));
}
}
}
self.skip_whitespace();
if self.at(SyntaxKind::Comma) {
self.consume();
}
}
Ok(members)
}
fn parse_enum_member(&mut self) -> ParseResult<IrNode> {
let start_byte = self.current_byte_offset();
let name = self.parse_ts_ident_or_placeholder().ok_or_else(|| {
ParseError::unexpected_eof(self.current_byte_offset(), "enum member name")
.with_context("parsing enum member")
})?;
self.skip_whitespace();
let init = if self.at(SyntaxKind::Eq) {
self.consume();
self.skip_whitespace();
Some(Box::new(
self.parse_ts_expr_until(&[SyntaxKind::Comma, SyntaxKind::RBrace])
.map_err(|e| e.with_context("parsing enum member initializer"))?,
))
} else {
None
};
Ok(IrNode::EnumMember {
span: IrSpan::new(start_byte, self.current_byte_offset()),
name: Box::new(name),
init,
})
}
}