From 8cad78481cd52680317032c3bb84cacda5666489 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 1 Jan 2021 17:54:31 +0100 Subject: =?UTF-8?q?A=20few=20small=20improvements=20=E2=99=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parse/mod.rs | 46 +++++++++++++++++++++------------------------- src/parse/parser.rs | 40 +++++++++------------------------------- src/parse/scanner.rs | 10 ---------- src/parse/tokens.rs | 11 +++++------ 4 files changed, 35 insertions(+), 72 deletions(-) (limited to 'src/parse') 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 { 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 { /// Parse a value. fn value(p: &mut Parser) -> Option { - 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 { 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 { } /// 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, /// 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) { - 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) { - 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) -> &'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(&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("%")); } } -- cgit v1.2.3