1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*!
A submodule that contains Parser-related type aliases.

Copyright © 2020 Santtu Söderholm
*/

use super::*;

// =====================================
//   Type aliases needed by the parser
// =====================================

/// A function pointer type alias for a State transition method.
/// `TransitionMethod`s take in the document tree and regex captures
/// for doctree modifications.
/// They return a `TransitionResult::{Success, Failure}`, the success variant of which contains a doctree,
/// a possible next state for the parser, information about manipulating the machine stack and whether to advance the parser line cursor.
/// If the optional next state is *not* `None`, the current state is either replaced with the new state or
/// the new state is pushed on top of the machine stack of the parser and parsing proceeds
/// in that state from the current line.
pub type TransitionMethod = fn(
    src_lines: &Vec<String>,
    base_indent: usize,
    section_level: &mut usize,
    line_cursor: &mut LineCursor,
    doctree: DocTree,
    captures: &regex::Captures,
    pattern_name: &Pattern,
) -> TransitionResult;

/// A type alias for a tuple `(PatternName, Regex, TransitionMethod)`
pub type Transition = (Pattern, regex::Regex, TransitionMethod);

/// A type alias for a transition `(PatternName, regex_pattern, TransitionMethod)`, whose regex pattern has not
/// been compiled into a DFA yet.
pub type UncompiledTransition = (Pattern, &'static str, TransitionMethod);

/// A type alias for a function describing an inline transition.
/// Returns a node a length of the match, so that the inline parser
/// could determine how many characters to eat off the start of the
/// source string.
pub type InlineParsingMethod = fn(
    opt_doctree_ref: &mut Option<&mut DocTree>,
    pattern_name: Pattern,
    captures: &regex::Captures,
) -> (Vec<TreeNodeType>, usize);

/// A type alias for a tuple `(PatternName, regex pattern, InlineTransitionMethod)`.
pub type InlineTransition = (Pattern, &'static str, InlineParsingMethod);

// ====================================================
//   Types and enums used by submodules of the parser
// ====================================================

/// An enumeration of the different results, including errors,
/// that a transition function might have.
pub enum TransitionResult {

    /// This is returned if nothing goes wrong with a transition method.
    /// It includes the modified document tree, plus information about
    /// how to manipulate the parser stack, whether the parser should advance
    /// its line cursor.
    Success {
        doctree: DocTree,
        push_or_pop: PushOrPop,
        line_advance: LineAdvance,
    },

    /// A general failure result. This will be returned if a clear error, such as a completetely invalid enumerator was
    /// encountered in a transition method functions. Contains an error message and the doctree in its current state.
    Failure { message: String, doctree: DocTree },
}

/// An enum for manipulating the machine stack. Transition methods should return this information
/// with a possible next state, so the parser knows how to proceed. The `Push` variant signifies
/// a state should be pushed on top of the stack, `Pop` tells of the need to pop from the stack
/// and `Neither` initiates a transition of the current state into another one.
#[derive(Debug)]
pub enum PushOrPop {

    /// Causes `Parser::parse` to push the contained states on top of the parser stack.
    Push(Vec<State>),
    /// Causes `Parser::parse` to pop the topmost state from the parser state stack.
    Pop,
    /// Signifies to `Parser::parse` that nothing about the stack needs to change.
    Neither,
}

/// An enum returned by the transition methods to tell the parser whether
/// it needs to advance its line cursor after the method execution or not.
pub enum LineAdvance {
    Some(usize),
    None,
}

/// An enumeration of the different ways an inline parsing function might succeed or fail.
pub enum InlineParsingResult {

    /// If no doctree was given to the inline parsing function, so tree nodes might be appended to it directly,
    /// the data of the generated nodes is given to the caller stored in a vector.
    Nodes(Vec<TreeNodeType>),

    /// If no nodes were discovered and no doctree was given to be modified, this empty variant is returned.
    NoNodes,
}

/// A enumeration of the different ways a node's child indentation might
/// interact with the indentation of the parent.
pub enum IndentationMatch {

    /// If a (sub)?body node has less indentation than its parent would require,
    /// it is interpreted as not belonging to the currently focused on node.
    TooLittle,

    /// This node belongs to the parent node.
    JustRight,

    /// This node is most likely a block quote.
    TooMuch,
}

/// A enumeration of the different ways the function `Parser::read_indented_block` could succeed or fail.
pub enum IndentedBlockResult {
    /// The reading of the text block succeeded as intended
    Ok {
        lines: Vec<String>,
        minimum_indent: usize,
        offset: usize,
        blank_finish: bool,
    },
    /// The given line vector was empty
    EmptyLinesErr,
    ///
    UnfinishedErr {
        lines: Vec<String>,
        minimum_indent: usize,
        offset: usize,
        blank_finish: bool,
    }
}

/// A enumeration of the different ways the function `Parser::read_text_block` could succeed or fail.
pub enum TextBlockResult {
    Ok {
        lines: Vec<String>,
        offset: usize,
    },
    Err {
        lines: Vec<String>,
        offset: usize,
    }
}