Skip to main content

oxyl_parser/
lib.rs

1// oxyl-parser
2// 
3// AST node types for oxyl. 
4// TODO - add actual parsing logic :)
5
6use oxyl_lexer::Span;
7
8/// The root of a parsed LaTeX document.
9#[derive(Debug, Clone)]
10pub struct Document {
11    /// Everything before `\begin{document}`.
12    pub preamble: Vec<Node>,
13    /// The body of the document.
14    pub body: Vec<Node>
15}
16
17/// A single node in the LaTeX AST.
18///
19/// More variants will be added as the parser is built out.
20#[derive(Debug, Clone)]
21pub enum Node {
22    /// A run of plain text characters
23    Text(String, Span),
24
25    /// A paragraph break (blank line in the source)
26    ParagraphBreak(Span),
27
28    /// A LaTeX command and its arguments, e.g. `\textbf{hello}`.
29    Command {
30        name: String ,
31        args: Vec<Arg>,
32        body: Vec<Node>,
33        span: Span,
34    },
35
36    /// A `\begin{name}...\end{name}` environment
37    Environment {
38        name: String,
39        args: Vec<Arg>,
40        body: Vec<Node>,
41        span: Span,
42    },
43
44    /// A braced group `{...}` that is not a command argument.
45    Group(Vec<Node>, Span),
46}
47
48impl Node {
49    /// The source span of this node.
50    pub fn span(&self) -> Span {
51        match self {
52            Node::Text(_,s) => *s,
53            Node::ParagraphBreak(s) => *s,
54            Node::Command { span, .. } => *span,
55            Node::Environment { span, .. } => *span,
56            Node::Group(_, s) => *s,
57        }
58    }
59}
60
61/// A single argument to a command or environment 
62#[derive(Debug, Clone)]
63pub enum Arg {
64    /// A mandatory argument in braces `{...}`.
65    Mandatory(Vec<Node>),
66    /// An optional argument in brackets `[...]`
67    Optional(Vec<Node>),
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn text_node_span() {
76        let span = Span::new(0, 5);
77        let node = Node::Text("hello".into(), span);
78        assert_eq!(node.span(), span);
79    }
80
81    #[test]
82    fn group_node_span() {
83        let span = Span::new(2, 9);
84        let node = Node::Group(vec![], span);
85        assert_eq!(node.span(), span);
86    }
87}