use super::super::prelude::*;
use super::mapping::get_block_rule_with_name;
pub const RULE_BLOCK: Rule = Rule {
name: "block",
position: LineRequirement::Any,
try_consume_fn: block_regular,
};
pub const RULE_BLOCK_STAR: Rule = Rule {
name: "block-star",
position: LineRequirement::Any,
try_consume_fn: block_star,
};
pub const RULE_BLOCK_SKIP_NEWLINE: Rule = Rule {
name: "block-skip",
position: LineRequirement::Any, try_consume_fn: block_skip,
};
fn block_regular<'r, 't>(
parser: &mut Parser<'r, 't>,
) -> ParseResult<'r, 't, Elements<'t>> {
debug!("Trying to process a block");
parse_block(parser, false)
}
fn block_star<'r, 't>(parser: &mut Parser<'r, 't>) -> ParseResult<'r, 't, Elements<'t>> {
debug!("Trying to process a block (with star flag)");
parse_block(parser, true)
}
fn block_skip<'r, 't>(parser: &mut Parser<'r, 't>) -> ParseResult<'r, 't, Elements<'t>> {
debug!("Trying to see if we skip a newline due to upcoming block");
let current = parser.step()?;
let result = parser.evaluate_fn(|parser| {
if ![Token::LeftBlock, Token::LeftBlockStar].contains(¤t.token) {
return Ok(false);
}
let (name, _) = parser.get_block_name(false)?;
match get_block_rule_with_name(name) {
Some(block_rule) => Ok(block_rule.accepts_newlines),
None => Ok(false),
}
});
if result {
debug!("Skipping newline due to upcoming line-terminated block");
ok!(Elements::None)
} else {
Err(parser.make_err(ParseErrorKind::RuleFailed))
}
}
fn parse_block<'r, 't>(
parser: &mut Parser<'r, 't>,
flag_star: bool,
) -> ParseResult<'r, 't, Elements<'t>>
where
'r: 't,
{
debug!("Trying to process a block (star {flag_star})");
parser.set_rule(if flag_star {
RULE_BLOCK_STAR
} else {
RULE_BLOCK
});
parser.get_optional_space()?;
let (name, in_head) = parser.get_block_name(flag_star)?;
trace!("Got block name '{name}' (in head {in_head})");
let (name, flag_score) = match name.strip_suffix('_') {
Some(name) => (name, true),
None => (name, false),
};
let block = match get_block_rule_with_name(name) {
Some(block) => block,
None => return Err(parser.make_err(ParseErrorKind::NoSuchBlock)),
};
parser.set_block(block);
if !block.accepts_star && flag_star {
return Err(parser.make_err(ParseErrorKind::BlockDisallowsStar));
}
if !block.accepts_score && flag_score {
return Err(parser.make_err(ParseErrorKind::BlockDisallowsScore));
}
parser.get_optional_space()?;
(block.parse_fn)(parser, name, flag_star, flag_score, in_head)
}