summaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-01-01 17:54:31 +0100
committerLaurenz <laurmaedje@gmail.com>2021-01-01 17:54:31 +0100
commit8cad78481cd52680317032c3bb84cacda5666489 (patch)
tree7cc0d17b2ec6d231c33205fa4765de1d63ee32ea /src/parse
parent2b6ccd82489afbcd679fb3199de2618fa8811325 (diff)
A few small improvements ♻
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/mod.rs46
-rw-r--r--src/parse/parser.rs40
-rw-r--r--src/parse/scanner.rs10
-rw-r--r--src/parse/tokens.rs11
4 files changed, 35 insertions, 72 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index 99cc9d10..7880dd7a 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -123,10 +123,9 @@ fn heading(p: &mut Parser) -> NodeHeading {
/// Handle a raw block.
fn raw(p: &mut Parser, token: TokenRaw) -> NodeRaw {
- let span = p.peek_span();
let raw = resolve::resolve_raw(token.text, token.backticks);
if !token.terminated {
- p.diag(error!(span.end, "expected backtick(s)"));
+ p.diag(error!(p.peek_span().end, "expected backtick(s)"));
}
raw
}
@@ -193,7 +192,7 @@ fn bracket_call(p: &mut Parser) -> ExprCall {
while let Some(mut top) = outer.pop() {
let span = inner.span;
let node = inner.map(|c| SynNode::Expr(Expr::Call(c)));
- let expr = Expr::Lit(Lit::Content(vec![node])).span_with(span);
+ let expr = Expr::Lit(Lit::Content(vec![node])).with_span(span);
top.v.args.v.0.push(LitDictEntry { key: None, expr });
inner = top;
}
@@ -213,7 +212,7 @@ fn bracket_subheader(p: &mut Parser) -> ExprCall {
} else {
p.diag_expected(what);
}
- Ident(String::new()).span_with(start)
+ Ident(String::new()).with_span(start)
});
let args = p.span(|p| dict_contents(p).0);
@@ -247,7 +246,7 @@ fn dict_contents(p: &mut Parser) -> (LitDict, bool) {
if let Some(key) = &entry.key {
comma_and_keyless = false;
- p.deco(Deco::DictKey.span_with(key.span));
+ p.deco(Deco::Name.with_span(key.span));
}
dict.0.push(entry);
@@ -286,7 +285,7 @@ fn dict_entry(p: &mut Parser) -> Option<LitDictEntry> {
expr: {
let start = ident.span.start;
let call = paren_call(p, ident);
- Expr::Call(call).span_with(start .. p.last_end())
+ Expr::Call(call).with_span(start .. p.last_end())
},
}),
@@ -335,7 +334,7 @@ fn binops(
op,
rhs: Box::new(rhs),
});
- lhs = expr.span_with(span);
+ lhs = expr.with_span(span);
} else {
break;
}
@@ -361,36 +360,32 @@ fn factor(p: &mut Parser) -> Option<Expr> {
/// Parse a value.
fn value(p: &mut Parser) -> Option<Expr> {
- let start = p.next_start();
- Some(match p.eat() {
+ let expr = match p.peek() {
// Bracketed function call.
Some(Token::LeftBracket) => {
- p.jump(start);
let node = p.span(|p| SynNode::Expr(Expr::Call(bracket_call(p))));
- Expr::Lit(Lit::Content(vec![node]))
+ return Some(Expr::Lit(Lit::Content(vec![node])));
}
// Content expression.
Some(Token::LeftBrace) => {
- p.jump(start);
- Expr::Lit(Lit::Content(content(p)))
+ return Some(Expr::Lit(Lit::Content(content(p))));
}
// Dictionary or just a parenthesized expression.
Some(Token::LeftParen) => {
- p.jump(start);
- parenthesized(p)
+ return Some(parenthesized(p));
}
// Function or just ident.
Some(Token::Ident(id)) => {
+ p.eat();
let ident = Ident(id.into());
- let after = p.last_end();
if p.peek() == Some(Token::LeftParen) {
- let name = ident.span_with(start .. after);
- Expr::Call(paren_call(p, name))
+ let name = ident.with_span(p.peek_span());
+ return Some(Expr::Call(paren_call(p, name)));
} else {
- Expr::Lit(Lit::Ident(ident))
+ return Some(Expr::Lit(Lit::Ident(ident)));
}
}
@@ -400,16 +395,17 @@ fn value(p: &mut Parser) -> Option<Expr> {
Some(Token::Float(f)) => Expr::Lit(Lit::Float(f)),
Some(Token::Length(val, unit)) => Expr::Lit(Lit::Length(val, unit)),
Some(Token::Percent(p)) => Expr::Lit(Lit::Percent(p)),
- Some(Token::Hex(hex)) => Expr::Lit(Lit::Color(color(p, hex, start))),
+ Some(Token::Hex(hex)) => Expr::Lit(Lit::Color(color(p, hex))),
Some(Token::Str(token)) => Expr::Lit(Lit::Str(str(p, token))),
// No value.
_ => {
- p.jump(start);
p.diag_expected("expression");
return None;
}
- })
+ };
+ p.eat();
+ Some(expr)
}
// Parse a content value: `{...}`.
@@ -444,10 +440,10 @@ fn ident(p: &mut Parser) -> Option<Ident> {
}
/// Parse a color.
-fn color(p: &mut Parser, hex: &str, start: Pos) -> RgbaColor {
+fn color(p: &mut Parser, hex: &str) -> RgbaColor {
RgbaColor::from_str(hex).unwrap_or_else(|_| {
// Replace color with black.
- p.diag(error!(start .. p.last_end(), "invalid color"));
+ p.diag(error!(p.peek_span(), "invalid color"));
RgbaColor::new(0, 0, 0, 255)
})
}
@@ -455,7 +451,7 @@ fn color(p: &mut Parser, hex: &str, start: Pos) -> RgbaColor {
/// Parse a string.
fn str(p: &mut Parser, token: TokenStr) -> String {
if !token.terminated {
- p.diag_expected_at("quote", p.last_end());
+ p.diag_expected_at("quote", p.peek_span().end);
}
resolve::resolve_string(token.string)
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index bf6eb76f..f6acff6e 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -3,7 +3,7 @@ use std::fmt::{self, Debug, Formatter};
use super::{Scanner, TokenMode, Tokens};
use crate::diag::Diag;
use crate::diag::{Deco, Feedback};
-use crate::syntax::{Pos, Span, SpanWith, Spanned, Token};
+use crate::syntax::{Pos, Span, Spanned, Token, WithSpan};
/// A convenient token-based parser.
pub struct Parser<'s> {
@@ -23,7 +23,7 @@ pub struct Parser<'s> {
/// The stack of open groups.
groups: Vec<Group>,
/// Accumulated feedback.
- f: Feedback,
+ feedback: Feedback,
}
impl<'s> Parser<'s> {
@@ -39,18 +39,18 @@ impl<'s> Parser<'s> {
last_end: Pos::ZERO,
modes: vec![],
groups: vec![],
- f: Feedback::new(),
+ feedback: Feedback::new(),
}
}
/// Finish parsing and return the accumulated feedback.
pub fn finish(self) -> Feedback {
- self.f
+ self.feedback
}
/// Add a diagnostic to the feedback.
pub fn diag(&mut self, diag: Spanned<Diag>) {
- self.f.diags.push(diag);
+ self.feedback.diags.push(diag);
}
/// Eat the next token and add a diagnostic that it is not the expected
@@ -89,7 +89,7 @@ impl<'s> Parser<'s> {
/// Add a decoration to the feedback.
pub fn deco(&mut self, deco: Spanned<Deco>) {
- self.f.decos.push(deco);
+ self.feedback.decos.push(deco);
}
/// Update the token mode and push the previous mode onto a stack.
@@ -162,7 +162,7 @@ impl<'s> Parser<'s> {
let start = self.next_start;
let output = f(self);
let end = self.last_end;
- output.span_with(start .. end)
+ output.with_span(start .. end)
}
/// A version of [`span`](Self::span) that works better with options.
@@ -251,34 +251,11 @@ impl<'s> Parser<'s> {
self.last_end
}
- /// Jump to a position in the source string.
- pub fn jump(&mut self, pos: Pos) {
- self.tokens.jump(pos);
- self.bump();
- }
-
/// Slice a part out of the source string.
pub fn get(&self, span: impl Into<Span>) -> &'s str {
self.tokens.scanner().get(span.into().to_range())
}
- /// The full source string up to the end of the last token.
- pub fn eaten(&self) -> &'s str {
- self.tokens.scanner().get(.. self.last_end.to_usize())
- }
-
- /// The source string from `start` to the end of the last token.
- pub fn eaten_from(&self, start: Pos) -> &'s str {
- self.tokens
- .scanner()
- .get(start.to_usize() .. self.last_end.to_usize())
- }
-
- /// The remaining source string after the start of the next token.
- pub fn rest(&self) -> &'s str {
- self.tokens.scanner().get(self.next_start.to_usize() ..)
- }
-
/// The underlying scanner.
pub fn scanner(&self) -> Scanner<'s> {
let mut scanner = self.tokens.scanner().clone();
@@ -325,7 +302,8 @@ impl<'s> Parser<'s> {
impl Debug for Parser<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "Parser({}|{})", self.eaten(), self.rest())
+ let s = self.scanner();
+ write!(f, "Parser({}|{})", s.eaten(), s.rest())
}
}
diff --git a/src/parse/scanner.rs b/src/parse/scanner.rs
index c4ba2cfd..69ad2138 100644
--- a/src/parse/scanner.rs
+++ b/src/parse/scanner.rs
@@ -102,11 +102,6 @@ impl<'s> Scanner<'s> {
self.peek().map(f).unwrap_or(false)
}
- /// Whether the end of the source string is reached.
- pub fn eof(&self) -> bool {
- self.index == self.src.len()
- }
-
/// The previous index in the source string.
pub fn last_index(&self) -> usize {
self.src[.. self.index]
@@ -126,11 +121,6 @@ impl<'s> Scanner<'s> {
self.index = index;
}
- /// The full source string.
- pub fn src(&self) -> &'s str {
- self.src
- }
-
/// Slice a part out of the source string.
pub fn get<I>(&self, index: I) -> &'s str
where
diff --git a/src/parse/tokens.rs b/src/parse/tokens.rs
index c9e159f1..d7919763 100644
--- a/src/parse/tokens.rs
+++ b/src/parse/tokens.rs
@@ -46,11 +46,6 @@ impl<'s> Tokens<'s> {
self.s.index().into()
}
- /// Jump to a position in the source string.
- pub fn jump(&mut self, pos: Pos) {
- self.s.jump(pos.to_usize());
- }
-
/// The underlying scanner.
pub fn scanner(&self) -> &Scanner<'s> {
&self.s
@@ -325,7 +320,9 @@ impl<'s> Tokens<'s> {
}
// Read the suffix.
- self.s.eat_while(|c| c == '%' || c.is_ascii_alphanumeric());
+ if !self.s.eat_if('%') {
+ self.s.eat_while(|c| c.is_ascii_alphanumeric());
+ }
// Parse into one of the suitable types.
let string = self.s.eaten_from(start);
@@ -790,5 +787,7 @@ mod tests {
// Test invalid number suffixes.
t!(Header[" /"]: "1foo" => Invalid("1foo"));
+ t!(Header: "1p%" => Invalid("1p"), Invalid("%"));
+ t!(Header: "1%%" => Percent(1.0), Invalid("%"));
}
}