aboutsummaryrefslogtreecommitdiff
path: root/parse_wiki_text/src/template.rs
diff options
context:
space:
mode:
Diffstat (limited to 'parse_wiki_text/src/template.rs')
-rw-r--r--parse_wiki_text/src/template.rs248
1 files changed, 248 insertions, 0 deletions
diff --git a/parse_wiki_text/src/template.rs b/parse_wiki_text/src/template.rs
new file mode 100644
index 0000000..494644b
--- /dev/null
+++ b/parse_wiki_text/src/template.rs
@@ -0,0 +1,248 @@
+// Copyright 2019 Fredrik Portström <https://portstrom.com>
+// This is free software distributed under the terms specified in
+// the file LICENSE at the top-level directory of this distribution.
+
+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,
+ );
+ }
+}