summaryrefslogtreecommitdiff
path: root/src/parse/tokens.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-01-30 12:09:26 +0100
committerLaurenz <laurmaedje@gmail.com>2021-01-30 12:09:26 +0100
commit89eb8bae49edb71d9a9279a2210bb1ccaf4dd707 (patch)
tree160b1a2ff41b5bba8a58f882df9d10c9eb036cf2 /src/parse/tokens.rs
parentac24075469f171fe83a976b9a97b9b1ea078a7e3 (diff)
New syntax 💎
- Everything everywhere! - Blocks with curly braces: {} - Templates with brackets: [] - Function templates with hashtag: `#[f]` - Headings with equals sign: `= Introduction`
Diffstat (limited to 'src/parse/tokens.rs')
-rw-r--r--src/parse/tokens.rs89
1 files changed, 42 insertions, 47 deletions
diff --git a/src/parse/tokens.rs b/src/parse/tokens.rs
index 056bbbbb..4f5d8ab4 100644
--- a/src/parse/tokens.rs
+++ b/src/parse/tokens.rs
@@ -67,12 +67,15 @@ impl<'s> Iterator for Tokens<'s> {
loop {
// Common elements.
return Some(match c {
- // Functions, blocks and terminators.
+ // Blocks and templates.
'[' => Token::LeftBracket,
']' => Token::RightBracket,
'{' => Token::LeftBrace,
'}' => Token::RightBrace,
+ // Keywords, function templates, colors.
+ '#' => self.hash(start),
+
// Whitespace.
c if c.is_whitespace() => self.whitespace(c),
@@ -90,8 +93,8 @@ impl<'s> Iterator for Tokens<'s> {
// Markup.
'*' => Token::Star,
'_' => Token::Underscore,
+ '=' => Token::Eq,
'~' => Token::Tilde,
- '#' => self.hash(start),
'`' => self.raw(),
'$' => self.math(),
'\\' => self.backslash(),
@@ -140,8 +143,7 @@ impl<'s> Iterator for Tokens<'s> {
self.number(start, c)
}
- // Hex values and strings.
- '#' => self.hex(start),
+ // Strings.
'"' => self.string(),
_ => Token::Invalid(self.s.eaten_from(start)),
@@ -151,6 +153,27 @@ impl<'s> Iterator for Tokens<'s> {
}
impl<'s> Tokens<'s> {
+ fn hash(&mut self, start: usize) -> Token<'s> {
+ if self.s.eat_if('[') {
+ return Token::HashBracket;
+ }
+
+ self.s.eat_while(is_id_continue);
+ let read = self.s.eaten_from(start);
+
+ if let Some(keyword) = keyword(read) {
+ return keyword;
+ }
+
+ if self.mode == TokenMode::Code {
+ if let Ok(color) = RgbaColor::from_str(read) {
+ return Token::Color(color);
+ }
+ }
+
+ Token::Invalid(read)
+ }
+
fn whitespace(&mut self, first: char) -> Token<'s> {
// Fast path for just a single space
if first == ' ' && !self.s.check(|c| c.is_whitespace()) {
@@ -182,10 +205,10 @@ impl<'s> Tokens<'s> {
c if c.is_whitespace() => true,
// Comments.
'/' if self.s.check(|c| c == '/' || c == '*') => true,
- // Parenthesis.
- '[' | ']' | '{' | '}' => true,
+ // Parenthesis and hashtag.
+ '[' | ']' | '{' | '}' | '#' => true,
// Markup.
- '*' | '_' | '#' | '~' | '`' | '$' => true,
+ '*' | '_' | '=' | '~' | '`' | '$' => true,
// Escaping.
'\\' => true,
_ => false,
@@ -198,21 +221,6 @@ impl<'s> Tokens<'s> {
Token::Text(self.s.eaten_from(start))
}
- fn hash(&mut self, start: usize) -> Token<'s> {
- if self.s.check(is_id_start) {
- self.s.eat();
- self.s.eat_while(is_id_continue);
- let read = self.s.eaten_from(start);
- if let Some(keyword) = keyword(read) {
- keyword
- } else {
- Token::Invalid(read)
- }
- } else {
- Token::Hash
- }
- }
-
fn raw(&mut self) -> Token<'s> {
let mut backticks = 1;
while self.s.eat_if('`') {
@@ -276,10 +284,10 @@ impl<'s> Tokens<'s> {
match c {
// Backslash and comments.
'\\' | '/' |
- // Parenthesis.
- '[' | ']' | '{' | '}' |
+ // Parenthesis and hashtag.
+ '[' | ']' | '{' | '}' | '#' |
// Markup.
- '*' | '_' | '#' | '~' | '`' | '$' => {
+ '*' | '_' | '=' | '~' | '`' | '$' => {
let start = self.s.index();
self.s.eat_assert(c);
Token::Text(&self.s.eaten_from(start))
@@ -367,18 +375,6 @@ impl<'s> Tokens<'s> {
}
}
- fn hex(&mut self, start: usize) -> Token<'s> {
- self.s.eat_while(is_id_continue);
- let read = self.s.eaten_from(start);
- if let Some(keyword) = keyword(read) {
- keyword
- } else if let Ok(color) = RgbaColor::from_str(read) {
- Token::Color(color)
- } else {
- Token::Invalid(read)
- }
- }
-
fn string(&mut self) -> Token<'s> {
let mut escaped = false;
Token::Str(TokenStr {
@@ -596,8 +592,8 @@ mod tests {
// Test markup tokens.
t!(Markup[" a1"]: "*" => Star);
t!(Markup: "_" => Underscore);
- t!(Markup[""]: "###" => Hash, Hash, Hash);
- t!(Markup["a1/"]: "# " => Hash, Space(0));
+ t!(Markup[""]: "===" => Eq, Eq, Eq);
+ t!(Markup["a1/"]: "= " => Eq, Space(0));
t!(Markup: "~" => Tilde);
t!(Markup[" "]: r"\" => Backslash);
}
@@ -655,10 +651,9 @@ mod tests {
];
for &(s, t) in &both {
- t!(Code[" "]: format!("#{}", s) => t);
- t!(Markup[" "]: format!("#{}", s) => t);
- t!(Markup[" "]: format!("#{0}#{0}", s) => t, t);
- t!(Markup[" /"]: format!("# {}", s) => Hash, Space(0), Text(s));
+ t!(Both[" "]: format!("#{}", s) => t);
+ t!(Both[" "]: format!("#{0}#{0}", s) => t, t);
+ t!(Markup[" /"]: format!("# {}", s) => Token::Invalid("#"), Space(0), Text(s));
}
let code = [
@@ -713,7 +708,7 @@ mod tests {
// Test code symbols in text.
t!(Markup[" /"]: "a():\"b" => Text("a():\"b"));
- t!(Markup[" /"]: ";:,=|/+-" => Text(";:,=|/+-"));
+ t!(Markup[" /"]: ";:,|/+-" => Text(";:,|/+-"));
// Test text ends.
t!(Markup[""]: "hello " => Text("hello"), Space(0));
@@ -765,17 +760,17 @@ mod tests {
t!(Markup: r"\}" => Text("}"));
t!(Markup: r"\*" => Text("*"));
t!(Markup: r"\_" => Text("_"));
- t!(Markup: r"\#" => Text("#"));
+ t!(Markup: r"\=" => Text("="));
t!(Markup: r"\~" => Text("~"));
t!(Markup: r"\`" => Text("`"));
t!(Markup: r"\$" => Text("$"));
+ t!(Markup: r"\#" => Text("#"));
// Test unescapable symbols.
t!(Markup[" /"]: r"\a" => Text(r"\"), Text("a"));
t!(Markup[" /"]: r"\u" => Text(r"\"), Text("u"));
t!(Markup[" /"]: r"\1" => Text(r"\"), Text("1"));
t!(Markup[" /"]: r"\:" => Text(r"\"), Text(":"));
- t!(Markup[" /"]: r"\=" => Text(r"\"), Text("="));
t!(Markup[" /"]: r#"\""# => Text(r"\"), Text("\""));
// Test basic unicode escapes.
@@ -947,7 +942,7 @@ mod tests {
t!(Code: "1%%" => Percent(1.0), Invalid("%"));
// Test invalid keyword.
- t!(Markup[" /"]: "#-" => Hash, Text("-"));
+ t!(Markup[" /"]: "#-" => Invalid("#-"));
t!(Markup[" /"]: "#do" => Invalid("#do"));
t!(Code[" /"]: r"#letter" => Invalid(r"#letter"));
}