use crate::lexer::{
TOKEN_KIND_CONSTRUCT_DELIMITERS, TOKEN_KIND_INSIDE_PARENS_CONSTRUCT_DELIMITERS,
TOKEN_KIND_MACRO_CALL_DELIMITERS, Token, TokenKind,
};
use crate::list::{Stringified, TokenKindList};
use crate::parser::RsmlParser;
use crate::parser::parse_error::{ParseError, ParseErrorMessage};
use crate::parser::types::*;
use crate::{node_token_matches, token_kind_list};
use phf_macros::phf_set;
static MACRO_RETURN_TYPES: phf::Set<&str> = phf_set! {
"Construct",
"Datatype",
"Selector",
};
static MACRO_RETURN_TYPE_NAMES: [&str; 3] = ["Construct", "Datatype", "Selector"];
impl<'a> RsmlParser<'a> {
pub(crate) fn parse_declaration_with_datatype(
&mut self,
node: Node<'a>,
declaration_token_kind: TokenKind,
constructor: fn(
declaration: Node<'a>,
body: Option<Box<Construct<'a>>>,
terminator: Option<Node<'a>>,
) -> Construct<'a>,
) -> Parsed<'a> {
if node.token.value().kind() != declaration_token_kind {
return Parsed(Some(node), None);
}
let declaration_node = node;
let node = self.advance_without_flags();
self.did_advance = true;
let (node_status, body_nodes) = self.parse_datatype(node, TOKEN_KIND_CONSTRUCT_DELIMITERS);
let body_nodes = body_nodes.map(|x| Box::new(x));
let terminator = match node_status {
NodeStatus::Exists => match self.advance_until(
token_kind_list![SemiColon],
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(constructor(declaration_node, body_nodes, None)),
);
}
None => return Parsed(None, Some(constructor(declaration_node, body_nodes, None))),
},
NodeStatus::Err(node) => {
if node_token_matches!(node, SemiColon) {
node
} else {
let construct = constructor(declaration_node, body_nodes, None);
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::SemiColon.name())),
},
self.range_from_span(clamp_span_to_end(construct.end())),
);
return Parsed(Some(node), Some(construct));
}
}
NodeStatus::None => {
let construct = constructor(declaration_node, body_nodes, None);
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::SemiColon.name())),
},
self.range_from_span(clamp_span_to_end(construct.end())),
);
return Parsed(None, Some(construct));
}
};
Parsed(
self.advance(),
Some(constructor(declaration_node, body_nodes, Some(terminator))),
)
}
pub(crate) fn parse_derive(&mut self, node: Node<'a>) -> Parsed<'a> {
self.parse_declaration_with_datatype(
node,
TokenKind::DeriveDeclaration,
|declaration, body, terminator| Construct::Derive {
declaration,
body,
terminator,
},
)
}
pub(crate) fn parse_priority(&mut self, node: Node<'a>) -> Parsed<'a> {
self.parse_declaration_with_datatype(
node,
TokenKind::PriorityDeclaration,
|declaration, body, terminator| Construct::Priority {
declaration,
body,
terminator,
},
)
}
pub(crate) fn parse_tween(&mut self, node: Node<'a>) -> Parsed<'a> {
if !node_token_matches!(node, TweenDeclaration) {
return Parsed(Some(node), None);
}
let declaration_node = node;
let name_node = match self.advance_until(
token_kind_list!("tween name", [Identifier]),
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => Some(node),
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::Tween {
declaration: declaration_node,
name: None,
body: None,
terminator: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::Tween {
declaration: declaration_node,
name: None,
body: None,
terminator: None,
}),
);
}
};
let node = self.advance_without_flags();
self.did_advance = true;
let (node_status, body_nodes) = self.parse_datatype(node, TOKEN_KIND_CONSTRUCT_DELIMITERS);
let body_nodes = body_nodes.map(|x| Box::new(x));
let terminator = match node_status {
NodeStatus::Exists => match self.advance_until(
token_kind_list![SemiColon],
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::Tween {
declaration: declaration_node,
name: name_node,
body: body_nodes,
terminator: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::Tween {
declaration: declaration_node,
name: name_node,
body: body_nodes,
terminator: None,
}),
);
}
},
NodeStatus::Err(node) => {
if node_token_matches!(node, SemiColon) {
node
} else {
let construct = Construct::Tween {
declaration: declaration_node,
name: name_node,
body: body_nodes,
terminator: None,
};
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::SemiColon.name())),
},
self.range_from_span(clamp_span_to_end(construct.end())),
);
return Parsed(Some(node), Some(construct));
}
}
NodeStatus::None => {
let construct = Construct::Tween {
declaration: declaration_node,
name: name_node,
body: body_nodes,
terminator: None,
};
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::SemiColon.name())),
},
self.range_from_span(clamp_span_to_end(construct.end())),
);
return Parsed(None, Some(construct));
}
};
Parsed(
self.advance(),
Some(Construct::Tween {
declaration: declaration_node,
name: name_node,
body: body_nodes,
terminator: Some(terminator),
}),
)
}
pub(crate) fn parse_macro_call(&mut self, node: Node<'a>) -> Parsed<'a> {
if !node_token_matches!(node, MacroCallIdentifier(_)) {
return Parsed(Some(node), None);
}
let Parsed(next_node, construct) = self.parse_macro_call_body(node);
if let Some(ref next) = next_node
&& (node_token_matches!(next, ScopeOpen) || node_token_matches!(next, Comma))
&& let Some(Construct::MacroCall { name, body, .. }) = construct
{
let is_scope_open = node_token_matches!(next, ScopeOpen);
let selector_node = SelectorNode::MacroCall { name, body };
let selectors = vec![selector_node];
if is_scope_open {
return self.parse_rule_scope_body(next_node.unwrap(), Some(selectors));
} else {
let comma_node = next_node.unwrap();
let token = comma_node.token.clone();
let mut selectors = selectors;
selectors.push(SelectorNode::Token(comma_node));
return self.parse_rule_scope_selector(token, selectors, false);
}
}
Parsed(next_node, construct)
}
fn parse_macro_call_args(
&mut self,
open_node: Node<'a>,
) -> (Option<Node<'a>>, Delimited<'a>) {
let first_node = match self.advance() {
Some(node) => {
let token_value = node.token.value();
if matches!(token_value, Token::ParensClose) {
return (None, Delimited::new(open_node, None, Some(node)));
} else if TOKEN_KIND_INSIDE_PARENS_CONSTRUCT_DELIMITERS
.contains(&token_value.kind())
{
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ParensClose.name())),
},
self.range_from_span(clamp_span_to_end(open_node.token.end())),
);
return (Some(node), Delimited::new(open_node, None, None));
}
node
}
None => {
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ParensClose.name())),
},
self.range_from_span(clamp_span_to_end(open_node.token.end())),
);
return (None, Delimited::new(open_node, None, None));
}
};
let (next_node, datatype_groups) = self.parse_table_datatype_args(Some(first_node));
if !node_token_matches!(next_node, Some(ParensClose)) {
let delimited = Delimited::new(open_node, datatype_groups, None);
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ParensClose.name())),
},
self.range_from_span(clamp_span_to_end(delimited.end())),
);
return (next_node, delimited);
}
(None, Delimited::new(open_node, datatype_groups, next_node))
}
pub(crate) fn parse_macro_call_body(&mut self, name_node: Node<'a>) -> Parsed<'a> {
let open_node = match self.advance_until(
token_kind_list![ParensOpen],
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::MacroCall {
name: name_node,
body: None,
terminator: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::MacroCall {
name: name_node,
body: None,
terminator: None,
}),
);
}
};
let (next_node, body) = self.parse_macro_call_args(open_node);
if body.right.is_none() {
return Parsed(
next_node,
Some(Construct::MacroCall {
name: name_node,
body: Some(body),
terminator: None,
}),
);
}
let terminator_node = match self.advance_until(
token_kind_list![SemiColon, ScopeOpen, Comma],
&TOKEN_KIND_MACRO_CALL_DELIMITERS,
) {
Some(Ok(node)) if !matches!(node.token.value(), Token::SemiColon) => {
return Parsed(
Some(node),
Some(Construct::MacroCall {
name: name_node,
body: Some(body),
terminator: None,
}),
);
}
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::MacroCall {
name: name_node,
body: Some(body),
terminator: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::MacroCall {
name: name_node,
body: Some(body),
terminator: None,
}),
);
}
};
Parsed(
self.advance(),
Some(Construct::MacroCall {
name: name_node,
body: Some(body),
terminator: Some(terminator_node),
}),
)
}
pub(crate) fn parse_macro_call_in_selector(
&mut self,
name_node: Node<'a>,
) -> (Option<Node<'a>>, SelectorNode<'a>) {
let open_node = match self.advance_until(
token_kind_list![ParensOpen],
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
return (
Some(node),
SelectorNode::MacroCall {
name: name_node,
body: None,
},
);
}
None => {
return (
None,
SelectorNode::MacroCall {
name: name_node,
body: None,
},
);
}
};
let (next_node, body) = self.parse_macro_call_args(open_node);
if body.right.is_none() {
return (
next_node,
SelectorNode::MacroCall {
name: name_node,
body: Some(body),
},
);
}
(
self.advance(),
SelectorNode::MacroCall {
name: name_node,
body: Some(body),
},
)
}
pub(crate) fn parse_macro(&mut self, node: Node<'a>) -> Parsed<'a> {
if !node_token_matches!(node, MacroDeclaration) {
return Parsed(Some(node), None);
}
let declaration_node = node;
let name_node = match self.advance_until(
token_kind_list!("macro name", [Identifier]),
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => Some(node),
Some(Err(node)) => {
let construct = Construct::Macro {
declaration: declaration_node,
name: None,
args: None,
return_type: None,
body: None,
};
return Parsed(Some(node), Some(construct));
}
None => {
let construct = Construct::Macro {
declaration: declaration_node,
name: None,
args: None,
return_type: None,
body: None,
};
return Parsed(self.advance(), Some(construct));
}
};
let args_or_body_node = match self.advance_until(
token_kind_list!(
"macro arguments, return type or body",
[ScopeOpen, ParensOpen, ReturnArrow]
),
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: None,
return_type: None,
body: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: None,
return_type: None,
body: None,
}),
);
}
};
if matches!(args_or_body_node.token.value(), Token::ParensOpen) {
self.parse_macro_args(args_or_body_node, declaration_node, name_node)
} else if matches!(args_or_body_node.token.value(), Token::ReturnArrow) {
let (return_type, return_type_str) = self.parse_macro_return_type(args_or_body_node);
let body_node = match self.advance_until(
token_kind_list![ScopeOpen],
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: None,
return_type: Some(return_type),
body: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: None,
return_type: Some(return_type),
body: None,
}),
);
}
};
self.parse_macro_body(
body_node,
declaration_node,
name_node,
None,
Some(return_type),
return_type_str,
)
} else {
self.parse_macro_body(
args_or_body_node,
declaration_node,
name_node,
None,
None,
None,
)
}
}
fn parse_macro_return_type(
&mut self,
arrow_node: Node<'a>,
) -> ((Node<'a>, Option<Node<'a>>), Option<&'a str>) {
let ident_node = match self.advance_until(
token_kind_list!("macro return type", [Identifier]),
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(_)) | None => return ((arrow_node, None), None),
};
let return_type_str = if let Token::Identifier(name) = ident_node.token.value() {
if MACRO_RETURN_TYPES.contains(*name) {
Some(*name)
} else {
self.ast_errors.push(
ParseError::UnexpectedTokens {
msg: Some(ParseErrorMessage::correction(
Some(name.to_string()),
self.range_from_span(ident_node.token.span()),
&MACRO_RETURN_TYPE_NAMES,
)),
},
self.range_from_span(ident_node.token.span()),
);
None
}
} else {
None
};
((arrow_node, Some(ident_node)), return_type_str)
}
fn parse_macro_args(
&mut self,
args_open_node: Node<'a>,
declaration_node: Node<'a>,
name_node: Option<Node<'a>>,
) -> Parsed<'a> {
let mut node = match self.advance_until(
token_kind_list![MacroArgIdentifier, Comma, ParensClose],
&TOKEN_KIND_INSIDE_PARENS_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: Some(Delimited {
left: args_open_node,
content: None,
right: None,
}),
return_type: None,
body: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: Some(Delimited {
left: args_open_node,
content: None,
right: None,
}),
return_type: None,
body: None,
}),
);
}
};
let mut last_token_value = node.token.value().clone();
let mut last_token_span = node.token.span();
if matches!(last_token_value, Token::ParensClose) {
return self.parse_macro_body_open(
declaration_node,
name_node,
args_open_node,
None,
Some(node),
);
}
let mut args = vec![Construct::Node { node }];
loop {
let advance_until_result = match last_token_value {
Token::Comma => self.advance_until(
token_kind_list![MacroArgIdentifier, ParensClose],
&TOKEN_KIND_INSIDE_PARENS_CONSTRUCT_DELIMITERS,
),
_ => self.advance_until(
token_kind_list![MacroArgIdentifier, Comma, ParensClose],
&TOKEN_KIND_INSIDE_PARENS_CONSTRUCT_DELIMITERS,
),
};
node = match advance_until_result {
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: Some(Delimited::new(args_open_node, Some(args), None)),
return_type: None,
body: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: Some(Delimited::new(args_open_node, Some(args), None)),
return_type: None,
body: None,
}),
);
}
};
let token_span = node.token.span();
let token_value = node.token.value().clone();
if matches!(token_value, Token::ParensClose) {
return self.parse_macro_body_open(
declaration_node,
name_node,
args_open_node,
Some(args),
Some(node),
);
};
args.push(Construct::Node { node });
if matches!(
(&last_token_value, &token_value),
(Token::MacroArgIdentifier(_), Token::MacroArgIdentifier(_))
) {
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::Comma.name())),
},
self.range_from_span((last_token_span.1 - 1, last_token_span.1)),
);
}
last_token_value = token_value;
last_token_span = token_span;
}
}
fn parse_macro_body_open(
&mut self,
declaration_node: Node<'a>,
name_node: Option<Node<'a>>,
args_open_node: Node<'a>,
args_content_node: Option<Vec<Construct<'a>>>,
args_close_node: Option<Node<'a>>,
) -> Parsed<'a> {
let body_or_arrow_node = match self.advance_until(
token_kind_list![ScopeOpen, ReturnArrow],
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: Some(Delimited {
left: args_open_node,
content: args_content_node,
right: args_close_node,
}),
return_type: None,
body: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: Some(Delimited {
left: args_open_node,
content: args_content_node,
right: args_close_node,
}),
return_type: None,
body: None,
}),
);
}
};
let args = Some(Delimited::new(
args_open_node,
args_content_node,
args_close_node,
));
if matches!(body_or_arrow_node.token.value(), Token::ReturnArrow) {
let (return_type, return_type_str) = self.parse_macro_return_type(body_or_arrow_node);
let body_node = match self.advance_until(
token_kind_list![ScopeOpen],
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args,
return_type: Some(return_type),
body: None,
}),
);
}
None => {
return Parsed(
None,
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args,
return_type: Some(return_type),
body: None,
}),
);
}
};
self.parse_macro_body(
body_node,
declaration_node,
name_node,
args,
Some(return_type),
return_type_str,
)
} else {
self.parse_macro_body(
body_or_arrow_node,
declaration_node,
name_node,
args,
None,
None,
)
}
}
pub(crate) fn parse_macro_body(
&mut self,
body_open_node: Node<'a>,
declaration_node: Node<'a>,
name_node: Option<Node<'a>>,
args_node: Option<Delimited<'a>>,
return_type: Option<(Node<'a>, Option<Node<'a>>)>,
return_type_str: Option<&str>,
) -> Parsed<'a> {
match return_type_str {
Some("Datatype") => self.parse_macro_body_datatype(
body_open_node,
declaration_node,
name_node,
args_node,
return_type,
),
Some("Selector") => self.parse_macro_body_selector(
body_open_node,
declaration_node,
name_node,
args_node,
return_type,
),
_ => self.parse_macro_body_construct(
body_open_node,
declaration_node,
name_node,
args_node,
return_type,
),
}
}
fn parse_macro_body_construct(
&mut self,
body_open_node: Node<'a>,
declaration_node: Node<'a>,
name_node: Option<Node<'a>>,
args_node: Option<Delimited<'a>>,
return_type: Option<(Node<'a>, Option<Node<'a>>)>,
) -> Parsed<'a> {
let Some(node) = self.advance() else {
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ScopeClose.name())),
},
self.range_from_span(clamp_span_to_end(body_open_node.token.end())),
);
return Parsed(
None,
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Construct(None),
close: None,
}),
}),
);
};
if node_token_matches!(node, ScopeClose) {
return Parsed(
self.advance(),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Construct(None),
close: Some(node),
}),
}),
);
}
let mut body_content: Vec<Construct<'a>> = vec![];
let (node, parse_ended_reason) = self.parse_loop_inner(node, |parser, mut node| {
node = parser
.parse_macro(node)
.handle_construct(&mut body_content)?;
node = parser
.parse_macro_call(node)
.handle_construct(&mut body_content)?;
node = parser
.parse_derive(node)
.handle_construct(&mut body_content)?;
node = parser
.parse_priority(node)
.handle_construct(&mut body_content)?;
node = parser
.parse_tween(node)
.handle_construct(&mut body_content)?;
node = parser
.parse_static_token_assignment(node)
.handle_construct(&mut body_content)?;
node = parser
.parse_token_assignment(node)
.handle_construct(&mut body_content)?;
node = parser
.parse_property_assignment_or_rule_scope(node)
.handle_construct(&mut body_content)?;
node = parser
.parse_rule_scope_selector_begin(node)
.handle_construct(&mut body_content)?;
node = parser
.parse_none(node)
.handle_construct(&mut body_content)?;
let end_parsing = node_token_matches!(node, ScopeClose);
Some((node, end_parsing))
});
if matches!(parse_ended_reason, ParseEndedReason::Manual) {
return Parsed(
self.advance(),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Construct(Some(body_content)),
close: node,
}),
}),
);
} else {
let construct = Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Construct(Some(body_content)),
close: None,
}),
};
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ScopeClose.name())),
},
self.range_from_span(clamp_span_to_end(construct.end())),
);
Parsed(self.advance(), Some(construct))
}
}
fn parse_macro_body_datatype(
&mut self,
body_open_node: Node<'a>,
declaration_node: Node<'a>,
name_node: Option<Node<'a>>,
args_node: Option<Delimited<'a>>,
return_type: Option<(Node<'a>, Option<Node<'a>>)>,
) -> Parsed<'a> {
let Some(node) = self.advance() else {
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ScopeClose.name())),
},
self.range_from_span(clamp_span_to_end(body_open_node.token.end())),
);
return Parsed(
None,
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Datatype(None),
close: None,
}),
}),
);
};
if node_token_matches!(node, ScopeClose) {
return Parsed(
self.advance(),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Datatype(None),
close: Some(node),
}),
}),
);
}
let (node_status, datatype) =
self.parse_datatype(Some(node), TOKEN_KIND_CONSTRUCT_DELIMITERS);
let close_node = match node_status {
NodeStatus::Exists => match self.advance_until(
token_kind_list![ScopeClose],
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => Some(node),
Some(Err(node)) => {
return Parsed(
Some(node),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Datatype(datatype.map(Box::new)),
close: None,
}),
}),
);
}
None => None,
},
NodeStatus::Err(node) => {
if node_token_matches!(node, ScopeClose) {
Some(node)
} else {
return Parsed(
Some(node),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Datatype(datatype.map(Box::new)),
close: None,
}),
}),
);
}
}
NodeStatus::None => None,
};
if close_node.is_none() {
let construct = Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Datatype(datatype.map(Box::new)),
close: None,
}),
};
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ScopeClose.name())),
},
self.range_from_span(clamp_span_to_end(construct.end())),
);
return Parsed(self.advance(), Some(construct));
}
Parsed(
self.advance(),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Datatype(datatype.map(Box::new)),
close: close_node,
}),
}),
)
}
fn parse_macro_body_selector(
&mut self,
body_open_node: Node<'a>,
declaration_node: Node<'a>,
name_node: Option<Node<'a>>,
args_node: Option<Delimited<'a>>,
return_type: Option<(Node<'a>, Option<Node<'a>>)>,
) -> Parsed<'a> {
let Some(node) = self.advance() else {
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ScopeClose.name())),
},
self.range_from_span(clamp_span_to_end(body_open_node.token.end())),
);
return Parsed(
None,
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Selector(None),
close: None,
}),
}),
);
};
if node_token_matches!(node, ScopeClose) {
return Parsed(
self.advance(),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Selector(None),
close: Some(node),
}),
}),
);
}
let node = match self.node_is_kind_else_advance_until(
node,
&token_kind_list!(
"selector part",
[
Identifier,
NameSelector,
TagSelectorOrEnumPart,
StateSelectorOrEnumPart,
PseudoSelector,
QuerySelector,
ChildrenSelector,
DescendantsSelector,
MacroCallIdentifier,
ScopeClose
]
),
&TOKEN_KIND_CONSTRUCT_DELIMITERS,
) {
Some(Ok(node)) => node,
Some(Err(node)) => {
let has_close = node_token_matches!(node, ScopeClose);
let close = if has_close { Some(node) } else { None };
let construct = Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Selector(None),
close,
}),
};
if !has_close {
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ScopeClose.name())),
},
self.range_from_span(clamp_span_to_end(construct.end())),
);
}
return Parsed(self.advance(), Some(construct));
}
None => {
let construct = Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Selector(None),
close: None,
}),
};
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ScopeClose.name())),
},
self.range_from_span(clamp_span_to_end(construct.end())),
);
return Parsed(None, Some(construct));
}
};
if node_token_matches!(node, ScopeClose) {
return Parsed(
self.advance(),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Selector(None),
close: Some(node),
}),
}),
);
}
let (terminator, selectors) = if node_token_matches!(node, MacroCallIdentifier(_)) {
let (next_node, selector_node) = self.parse_macro_call_in_selector(node);
let mut selectors = vec![selector_node];
match next_node {
Some(next)
if node_token_matches!(next, ScopeOpen)
|| node_token_matches!(next, ScopeClose) =>
{
(Some(next), selectors)
}
Some(next) => {
let token = next.token.clone();
selectors.push(SelectorNode::Token(next));
match token.value() {
Token::Comma => self.parse_selector_tokens(token, selectors, false),
_ => self.parse_selector_tokens(token, selectors, true),
}
}
None => (None, selectors),
}
} else {
let first_token = node.token.clone();
let selectors = vec![SelectorNode::Token(node)];
self.parse_selector_tokens(first_token, selectors, true)
};
let content = if selectors.is_empty() {
None
} else {
Some(selectors)
};
if let Some(close_node) = terminator {
if node_token_matches!(close_node, ScopeClose) {
return Parsed(
self.advance(),
Some(Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Selector(content),
close: Some(close_node),
}),
}),
);
}
}
let construct = Construct::Macro {
declaration: declaration_node,
name: name_node,
args: args_node,
return_type,
body: Some(MacroBody {
open: body_open_node,
content: MacroBodyContent::Selector(content),
close: None,
}),
};
self.ast_errors.push(
ParseError::MissingToken {
msg: Some(ParseErrorMessage::Expected(TokenKind::ScopeClose.name())),
},
self.range_from_span(clamp_span_to_end(construct.end())),
);
Parsed(self.advance(), Some(construct))
}
}