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
|
//! Tokenized and syntax tree representations of source code.
use std::collections::HashMap;
use std::fmt::{self, Display, Formatter};
use std::ops::Deref;
use crate::func::Function;
use crate::utility::StrExt;
/// A logical unit of the incoming text stream.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Token<'s> {
/// One or more whitespace (non-newline) codepoints.
Space,
/// A line feed (either `\n` or `\r\n`).
Newline,
/// A left bracket: `[`.
LeftBracket,
/// A right bracket: `]`.
RightBracket,
/// A colon (`:`) indicating the beginning of function arguments.
///
/// If a colon occurs outside of the function header, it will be
/// tokenized as a [Word](Token::Word).
Colon,
/// Same as with [Colon](Token::Colon).
Equals,
/// Two underscores, indicating text in _italics_.
DoubleUnderscore,
/// Two stars, indicating **bold** text.
DoubleStar,
/// A dollar sign, indicating _mathematical_ content.
Dollar,
/// A hashtag starting a _comment_.
Hashtag,
/// Everything else just is a literal word.
Word(&'s str),
}
/// A tree representation of the source.
#[derive(Debug, PartialEq)]
pub struct SyntaxTree {
/// The children.
pub nodes: Vec<Node>,
}
impl SyntaxTree {
/// Create an empty syntax tree.
#[inline]
pub fn new() -> SyntaxTree {
SyntaxTree { nodes: vec![] }
}
}
/// A node in the abstract syntax tree.
#[derive(Debug, PartialEq)]
pub enum Node {
/// Whitespace between other nodes.
Space,
/// A line feed.
Newline,
/// Indicates that italics were enabled/disabled.
ToggleItalics,
/// Indicates that boldface was enabled/disabled.
ToggleBold,
/// Indicates that math mode was enabled/disabled.
ToggleMath,
/// A literal word.
Word(String),
/// A function invocation.
Func(FuncInvocation),
}
/// A complete function invocation consisting of header and body.
#[derive(Debug)]
pub struct FuncInvocation {
pub header: FuncHeader,
pub body: Box<dyn Function>,
}
impl PartialEq for FuncInvocation {
fn eq(&self, other: &FuncInvocation) -> bool {
(self.header == other.header) && (&self.body == &other.body)
}
}
/// Contains header information of a function invocation.
#[derive(Debug, Clone, PartialEq)]
pub struct FuncHeader {
pub name: Ident,
pub args: Vec<Expression>,
pub kwargs: HashMap<Ident, Expression>
}
/// A potentially unevaluated expression.
#[derive(Debug, Clone, PartialEq)]
pub enum Expression {}
/// An owned valid identifier.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Ident(String);
impl Ident {
/// Create a new identifier if the string is a valid one.
#[inline]
pub fn new<S: Into<String>>(ident: S) -> Option<Ident> {
let ident = ident.into();
if ident.is_identifier() {
Some(Ident(ident))
} else {
None
}
}
/// Consume self and return the underlying string.
#[inline]
pub fn into_inner(self) -> String {
self.0
}
}
impl Display for Ident {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl Deref for Ident {
type Target = str;
#[inline]
fn deref(&self) -> &str {
&*self.0
}
}
|