pub fn parse_parameter_name_end(state: &mut crate::State) {
let stack_length = state.stack.len();
if stack_length > 0 {
if let crate::OpenNode {
type_:
crate::OpenNodeType::Template {
name: Some(_),
parameters,
},
..
} = &mut state.stack[stack_length - 1]
{
let parameters_length = parameters.len();
let name = &mut parameters[parameters_length - 1].name;
if name.is_none() {
crate::state::flush(
&mut state.nodes,
state.flushed_position,
crate::state::skip_whitespace_backwards(state.wiki_text, state.scan_position),
state.wiki_text,
);
state.flushed_position = crate::state::skip_whitespace_forwards(
state.wiki_text,
state.scan_position + 1,
);
state.scan_position = state.flushed_position;
*name = Some(std::mem::replace(&mut state.nodes, vec![]));
return;
}
}
}
state.scan_position += 1;
}
pub fn parse_parameter_separator(state: &mut crate::State) {
match state.stack.last_mut() {
Some(crate::OpenNode {
type_: crate::OpenNodeType::Parameter { default, name },
..
}) => {
if name.is_none() {
let position =
crate::state::skip_whitespace_backwards(state.wiki_text, state.scan_position);
crate::state::flush(
&mut state.nodes,
state.flushed_position,
position,
state.wiki_text,
);
*name = Some(std::mem::replace(&mut state.nodes, vec![]));
} else {
crate::state::flush(
&mut state.nodes,
state.flushed_position,
state.scan_position,
state.wiki_text,
);
*default = Some(std::mem::replace(&mut state.nodes, vec![]));
state.warnings.push(crate::Warning {
end: state.scan_position + 1,
message: crate::WarningMessage::UselessTextInParameter,
start: state.scan_position,
});
}
state.scan_position += 1;
state.flushed_position = state.scan_position;
}
_ => unreachable!(),
}
}
pub fn parse_template_end(state: &mut crate::State) {
match state.stack.last() {
Some(crate::OpenNode {
type_: crate::OpenNodeType::Parameter { .. },
..
}) => match state.stack.pop() {
Some(crate::OpenNode {
nodes,
start,
type_: crate::OpenNodeType::Parameter { default, name },
}) => {
if state.get_byte(state.scan_position + 2) == Some(b'}') {
if let Some(name) = name {
let start_position = state.scan_position;
state.flush(start_position);
let nodes = std::mem::replace(&mut state.nodes, nodes);
state.nodes.push(crate::Node::Parameter {
default: Some(default.unwrap_or(nodes)),
end: state.scan_position,
name,
start,
});
} else {
let start_position = state.skip_whitespace_backwards(state.scan_position);
state.flush(start_position);
let nodes = std::mem::replace(&mut state.nodes, nodes);
state.nodes.push(crate::Node::Parameter {
default: None,
end: state.scan_position,
name: nodes,
start,
});
}
state.scan_position += 3;
state.flushed_position = state.scan_position;
} else {
state.warnings.push(crate::Warning {
end: state.scan_position + 2,
message: crate::WarningMessage::UnexpectedEndTagRewinding,
start: state.scan_position,
});
state.rewind(nodes, start);
}
}
_ => unreachable!(),
},
Some(crate::OpenNode {
type_: crate::OpenNodeType::Template { .. },
..
}) => match state.stack.pop() {
Some(crate::OpenNode {
nodes,
start,
type_:
crate::OpenNodeType::Template {
name,
mut parameters,
},
}) => {
let position = state.skip_whitespace_backwards(state.scan_position);
state.flush(position);
state.scan_position += 2;
state.flushed_position = state.scan_position;
let name = match name {
None => std::mem::replace(&mut state.nodes, nodes),
Some(name) => {
let parameters_length = parameters.len();
let parameter = &mut parameters[parameters_length - 1];
parameter.end = position;
parameter.value = std::mem::replace(&mut state.nodes, nodes);
name
}
};
state.nodes.push(crate::Node::Template {
end: state.scan_position,
name,
parameters,
start,
});
}
_ => unreachable!(),
},
_ => {
if state
.stack
.iter()
.rev()
.skip(1)
.any(|item| match item.type_ {
crate::OpenNodeType::Parameter { .. } => {
state.get_byte(state.scan_position + 2) == Some(b'}')
}
crate::OpenNodeType::Template { .. } => true,
_ => false,
})
{
state.warnings.push(crate::Warning {
end: state.scan_position + 2,
message: crate::WarningMessage::UnexpectedEndTagRewinding,
start: state.scan_position,
});
let open_node = state.stack.pop().unwrap();
state.rewind(open_node.nodes, open_node.start);
} else {
state.warnings.push(crate::Warning {
end: state.scan_position + 2,
message: crate::WarningMessage::UnexpectedEndTag,
start: state.scan_position,
});
state.scan_position += 2;
}
}
}
}
pub fn parse_template_separator(state: &mut crate::State) {
match state.stack.last_mut() {
Some(crate::OpenNode {
type_: crate::OpenNodeType::Template { name, parameters },
..
}) => {
let position =
crate::state::skip_whitespace_backwards(state.wiki_text, state.scan_position);
crate::state::flush(
&mut state.nodes,
state.flushed_position,
position,
state.wiki_text,
);
state.flushed_position =
crate::state::skip_whitespace_forwards(state.wiki_text, state.scan_position + 1);
state.scan_position = state.flushed_position;
if name.is_none() {
*name = Some(std::mem::replace(&mut state.nodes, vec![]));
} else {
let parameters_length = parameters.len();
let parameter = &mut parameters[parameters_length - 1];
parameter.end = position;
parameter.value = std::mem::replace(&mut state.nodes, vec![]);
}
parameters.push(crate::Parameter {
end: 0,
name: None,
start: state.scan_position,
value: vec![],
});
}
_ => unreachable!(),
}
}
pub fn parse_template_start(state: &mut crate::State) {
let scan_position = state.scan_position;
if state.get_byte(state.scan_position + 2) == Some(b'{') {
let position = state.skip_whitespace_forwards(scan_position + 3);
state.push_open_node(
crate::OpenNodeType::Parameter {
default: None,
name: None,
},
position,
);
} else {
let position = state.skip_whitespace_forwards(scan_position + 2);
state.push_open_node(
crate::OpenNodeType::Template {
name: None,
parameters: vec![],
},
position,
);
}
}