Code Review: No Patrick, question marks are not an instrument

This commit is contained in:
Martin Haug 2021-11-05 12:53:52 +01:00
parent 5c952d56d0
commit cf2e527a02
7 changed files with 260 additions and 317 deletions

View File

@ -76,7 +76,7 @@ impl Walk for HeadingNode {
ctx.template.save(); ctx.template.save();
ctx.template.modify(move |style| { ctx.template.modify(move |style| {
let text = style.text_mut(); let text = style.text_mut();
let upscale = 1.6 - 0.1 * level as f64; let upscale = (1.6 - 0.1 * level as f64).max(0.75);
text.size *= upscale; text.size *= upscale;
text.strong = true; text.strong = true;
}); });

View File

@ -14,9 +14,8 @@ use std::rc::Rc;
use crate::syntax::ast::{Associativity, BinOp, UnOp}; use crate::syntax::ast::{Associativity, BinOp, UnOp};
use crate::syntax::{ErrorPosition, GreenNode, NodeKind}; use crate::syntax::{ErrorPosition, GreenNode, NodeKind};
use crate::util::EcoString;
type ParseResult = Result<(), ()>; type ParseResult<T = ()> = Result<T, ()>;
/// Parse a source file. /// Parse a source file.
pub fn parse(source: &str) -> Rc<GreenNode> { pub fn parse(source: &str) -> Rc<GreenNode> {
@ -52,12 +51,11 @@ fn markup_while<F>(p: &mut Parser, mut at_start: bool, f: &mut F)
where where
F: FnMut(&mut Parser) -> bool, F: FnMut(&mut Parser) -> bool,
{ {
p.start(); p.perform(NodeKind::Markup, |p| {
while !p.eof() && f(p) { while !p.eof() && f(p) {
markup_node(p, &mut at_start); markup_node(p, &mut at_start).ok();
} }
});
p.end(NodeKind::Markup);
} }
/// Parse a markup node. /// Parse a markup node.
@ -91,7 +89,6 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) -> ParseResult {
| NodeKind::Raw(_) | NodeKind::Raw(_)
| NodeKind::UnicodeEscape(_) => { | NodeKind::UnicodeEscape(_) => {
p.eat(); p.eat();
Ok(())
} }
NodeKind::Eq if *at_start => heading(p), NodeKind::Eq if *at_start => heading(p),
@ -101,7 +98,6 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) -> ParseResult {
// Line-based markup that is not currently at the start of the line. // Line-based markup that is not currently at the start of the line.
NodeKind::Eq | NodeKind::ListBullet | NodeKind::EnumNumbering(_) => { NodeKind::Eq | NodeKind::ListBullet | NodeKind::EnumNumbering(_) => {
p.convert(NodeKind::Text(p.peek_src().into())); p.convert(NodeKind::Text(p.peek_src().into()));
Ok(())
} }
// Hashtag + keyword / identifier. // Hashtag + keyword / identifier.
@ -120,7 +116,7 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) -> ParseResult {
if stmt && res.is_ok() && !p.eof() { if stmt && res.is_ok() && !p.eof() {
p.expected_at("semicolon or line break"); p.expected_at("semicolon or line break");
} }
p.end_group() p.end_group();
} }
// Block and template. // Block and template.
@ -135,58 +131,46 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) -> ParseResult {
NodeKind::Error(_, _) => { NodeKind::Error(_, _) => {
p.eat(); p.eat();
Ok(())
} }
_ => { _ => {
p.unexpected(); p.unexpected();
Err(()) return Err(());
} }
}?; };
*at_start = false; *at_start = false;
Ok(()) Ok(())
} }
/// Parse a heading. /// Parse a heading.
fn heading(p: &mut Parser) -> ParseResult { fn heading(p: &mut Parser) {
p.start(); p.perform(NodeKind::Heading, |p| {
p.eat_assert(&NodeKind::Eq); p.eat_assert(&NodeKind::Eq);
// Count depth. while p.eat_if(&NodeKind::Eq) {}
let mut level: usize = 1;
while p.eat_if(&NodeKind::Eq) {
level += 1;
}
if level > 6 {
p.end(NodeKind::Text(EcoString::from('=').repeat(level)));
} else {
let column = p.column(p.prev_end()); let column = p.column(p.prev_end());
markup_indented(p, column); markup_indented(p, column);
p.end(NodeKind::Heading); });
}
Ok(())
} }
/// Parse a single list item. /// Parse a single list item.
fn list_node(p: &mut Parser) -> ParseResult { fn list_node(p: &mut Parser) {
p.start(); p.perform(NodeKind::List, |p| {
p.eat_assert(&NodeKind::ListBullet); p.eat_assert(&NodeKind::ListBullet);
let column = p.column(p.prev_end()); let column = p.column(p.prev_end());
markup_indented(p, column); markup_indented(p, column);
p.end(NodeKind::List); });
Ok(())
} }
/// Parse a single enum item. /// Parse a single enum item.
fn enum_node(p: &mut Parser) -> ParseResult { fn enum_node(p: &mut Parser) {
p.start(); p.perform(NodeKind::Enum, |p| {
p.eat(); p.eat();
let column = p.column(p.prev_end()); let column = p.column(p.prev_end());
markup_indented(p, column); markup_indented(p, column);
p.end(NodeKind::Enum); });
Ok(())
} }
/// Parse an expression. /// Parse an expression.
@ -224,7 +208,7 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
p.peek_direct(), p.peek_direct(),
Some(NodeKind::LeftParen | NodeKind::LeftBracket) Some(NodeKind::LeftParen | NodeKind::LeftBracket)
) { ) {
call(p, &marker); call(p, &marker)?;
continue; continue;
} }
@ -255,19 +239,14 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
Associativity::Right => {} Associativity::Right => {}
} }
if expr_with(p, atomic, prec).is_err() { marker.perform(p, NodeKind::Binary, |p| expr_with(p, atomic, prec))?;
break Ok(());
}
marker.end(p, NodeKind::Binary);
} }
} }
/// Parse a primary expression. /// Parse a primary expression.
fn primary(p: &mut Parser, atomic: bool) -> ParseResult { fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
let lit = literal(p); if literal(p) {
if lit.is_ok() { return Ok(());
return lit;
} }
match p.peek() { match p.peek() {
@ -282,9 +261,7 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
marker.end(p, NodeKind::ClosureParams); marker.end(p, NodeKind::ClosureParams);
p.eat(); p.eat();
let e = expr(p); marker.perform(p, NodeKind::Closure, expr)
marker.end(p, NodeKind::Closure);
e
} else { } else {
Ok(()) Ok(())
} }
@ -292,8 +269,14 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
// Structures. // Structures.
Some(NodeKind::LeftParen) => parenthesized(p), Some(NodeKind::LeftParen) => parenthesized(p),
Some(NodeKind::LeftBracket) => template(p), Some(NodeKind::LeftBracket) => {
Some(NodeKind::LeftBrace) => block(p), template(p);
Ok(())
}
Some(NodeKind::LeftBrace) => {
block(p);
Ok(())
}
// Keywords. // Keywords.
Some(NodeKind::Let) => let_expr(p), Some(NodeKind::Let) => let_expr(p),
@ -317,7 +300,7 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
} }
/// Parse a literal. /// Parse a literal.
fn literal(p: &mut Parser) -> ParseResult { fn literal(p: &mut Parser) -> bool {
match p.peek() { match p.peek() {
// Basic values. // Basic values.
Some( Some(
@ -333,10 +316,10 @@ fn literal(p: &mut Parser) -> ParseResult {
| NodeKind::Str(_), | NodeKind::Str(_),
) => { ) => {
p.eat(); p.eat();
Ok(()) true
} }
_ => Err(()), _ => false,
} }
} }
@ -364,10 +347,7 @@ fn parenthesized(p: &mut Parser) -> ParseResult {
p.eat_assert(&NodeKind::Arrow); p.eat_assert(&NodeKind::Arrow);
let r = expr(p); return marker.perform(p, NodeKind::Closure, expr);
marker.end(p, NodeKind::Closure);
return r;
} }
// Find out which kind of collection this is. // Find out which kind of collection this is.
@ -439,37 +419,35 @@ fn collection(p: &mut Parser) -> (CollectionKind, usize) {
} }
/// Parse an expression or a named pair. Returns if this is a named pair. /// Parse an expression or a named pair. Returns if this is a named pair.
fn item(p: &mut Parser) -> Result<NodeKind, ()> { fn item(p: &mut Parser) -> ParseResult<NodeKind> {
let marker = p.marker(); let marker = p.marker();
if p.eat_if(&NodeKind::Dots) { if p.eat_if(&NodeKind::Dots) {
let r = expr(p); return marker
.perform(p, NodeKind::Spread, |p| expr(p).map(|_| NodeKind::Spread));
marker.end(p, NodeKind::Spread);
return r.map(|_| NodeKind::Spread);
} }
let ident_marker = p.marker(); let ident_marker = p.marker();
if expr(p).is_err() { expr(p)?;
return Err(());
}
if p.peek() == Some(&NodeKind::Colon) { if p.peek() == Some(&NodeKind::Colon) {
let r = if matches!(p.child(0).unwrap().kind(), &NodeKind::Ident(_)) { marker.perform(p, NodeKind::Named, |p| {
p.eat(); if matches!(
expr(p) ident_marker.child_at(p).unwrap().kind(),
} else { &NodeKind::Ident(_)
ident_marker.end( ) {
p, p.eat();
NodeKind::Error(ErrorPosition::Full, "expected identifier".into()), expr(p).map(|_| NodeKind::Named)
); } else {
p.eat(); ident_marker.end(
p,
NodeKind::Error(ErrorPosition::Full, "expected identifier".into()),
);
p.eat();
expr(p); expr(p).ok();
Err(()) Err(())
}; }
})
marker.end(p, NodeKind::Named);
r.map(|_| NodeKind::Named)
} else { } else {
Ok(p.last_child().unwrap().kind().clone()) Ok(p.last_child().unwrap().kind().clone())
} }
@ -478,23 +456,16 @@ fn item(p: &mut Parser) -> Result<NodeKind, ()> {
/// Convert a collection into an array, producing errors for anything other than /// Convert a collection into an array, producing errors for anything other than
/// expressions. /// expressions.
fn array(p: &mut Parser, marker: &Marker) -> ParseResult { fn array(p: &mut Parser, marker: &Marker) -> ParseResult {
marker.filter_children( marker.filter_children(p, |x| match x.kind() {
p, NodeKind::Named => Err((
|x| match x.kind() { ErrorPosition::Full,
NodeKind::Named | NodeKind::Spread => false, "expected expression, found named pair".into(),
_ => true, )),
}, NodeKind::Spread => {
|kind| match kind { Err((ErrorPosition::Full, "spreading is not allowed here".into()))
NodeKind::Named => ( }
ErrorPosition::Full, _ => Ok(()),
"expected expression, found named pair".into(), });
),
NodeKind::Spread => {
(ErrorPosition::Full, "spreading is not allowed here".into())
}
_ => unreachable!(),
},
);
marker.end(p, NodeKind::Array); marker.end(p, NodeKind::Array);
Ok(()) Ok(())
@ -503,24 +474,17 @@ fn array(p: &mut Parser, marker: &Marker) -> ParseResult {
/// Convert a collection into a dictionary, producing errors for anything other /// Convert a collection into a dictionary, producing errors for anything other
/// than named pairs. /// than named pairs.
fn dict(p: &mut Parser, marker: &Marker) -> ParseResult { fn dict(p: &mut Parser, marker: &Marker) -> ParseResult {
marker.filter_children( marker.filter_children(p, |x| match x.kind() {
p, NodeKind::Named | NodeKind::Comma | NodeKind::Colon => Ok(()),
|x| { NodeKind::Spread => {
x.kind() == &NodeKind::Named Err((ErrorPosition::Full, "spreading is not allowed here".into()))
|| x.kind().is_paren() }
|| x.kind() == &NodeKind::Comma _ if x.kind().is_paren() => Ok(()),
|| x.kind() == &NodeKind::Colon _ => Err((
}, ErrorPosition::Full,
|kind| match kind { "expected named pair, found expression".into(),
NodeKind::Spread => { )),
(ErrorPosition::Full, "spreading is not allowed here".into()) });
}
_ => (
ErrorPosition::Full,
"expected named pair, found expression".into(),
),
},
);
marker.end(p, NodeKind::Dict); marker.end(p, NodeKind::Dict);
Ok(()) Ok(())
@ -529,96 +493,90 @@ fn dict(p: &mut Parser, marker: &Marker) -> ParseResult {
/// Convert a collection into a list of parameters, producing errors for /// Convert a collection into a list of parameters, producing errors for
/// anything other than identifiers, spread operations and named pairs. /// anything other than identifiers, spread operations and named pairs.
fn params(p: &mut Parser, marker: &Marker, allow_parens: bool) { fn params(p: &mut Parser, marker: &Marker, allow_parens: bool) {
marker.filter_children( marker.filter_children(p, |x| match x.kind() {
p, NodeKind::Named | NodeKind::Comma | NodeKind::Ident(_) => Ok(()),
|x| match x.kind() { NodeKind::Spread
NodeKind::Named | NodeKind::Comma | NodeKind::Ident(_) => true, if matches!(
NodeKind::Spread => matches!( x.children().last().map(|x| x.kind()),
x.children().last().map(|x| x.kind()), Some(&NodeKind::Ident(_))
Some(&NodeKind::Ident(_)) ) =>
), {
_ => false, Ok(())
} }
|| (allow_parens && x.kind().is_paren()), _ if allow_parens && x.kind().is_paren() => Ok(()),
|_| (ErrorPosition::Full, "expected identifier".into()), _ => Err((ErrorPosition::Full, "expected identifier".into())),
); });
} }
// Parse a template block: `[...]`. // Parse a template block: `[...]`.
fn template(p: &mut Parser) -> ParseResult { fn template(p: &mut Parser) {
p.start(); p.perform(NodeKind::Template, |p| {
p.start_group(Group::Bracket, TokenMode::Markup); p.start_group(Group::Bracket, TokenMode::Markup);
markup(p); markup(p);
p.end_group(); p.end_group();
p.end(NodeKind::Template); });
Ok(())
} }
/// Parse a code block: `{...}`. /// Parse a code block: `{...}`.
fn block(p: &mut Parser) -> ParseResult { fn block(p: &mut Parser) {
p.start(); p.perform(NodeKind::Block, |p| {
p.start_group(Group::Brace, TokenMode::Code); p.start_group(Group::Brace, TokenMode::Code);
while !p.eof() { while !p.eof() {
p.start_group(Group::Stmt, TokenMode::Code); p.start_group(Group::Stmt, TokenMode::Code);
if expr(p).is_ok() { if expr(p).is_ok() && !p.eof() {
if !p.eof() {
p.expected_at("semicolon or line break"); p.expected_at("semicolon or line break");
} }
p.end_group();
// Forcefully skip over newlines since the group's contents can't.
p.eat_while(|t| matches!(t, NodeKind::Space(_)));
} }
p.end_group(); p.end_group();
});
// Forcefully skip over newlines since the group's contents can't.
p.eat_while(|t| matches!(t, NodeKind::Space(_)));
}
p.end_group();
p.end(NodeKind::Block);
Ok(())
} }
/// Parse a function call. /// Parse a function call.
fn call(p: &mut Parser, callee: &Marker) -> ParseResult { fn call(p: &mut Parser, callee: &Marker) -> ParseResult {
let res = match p.peek_direct() { callee.perform(p, NodeKind::Call, |p| match p.peek_direct() {
Some(NodeKind::LeftParen) | Some(NodeKind::LeftBracket) => args(p, true), Some(NodeKind::LeftParen) | Some(NodeKind::LeftBracket) => {
args(p, true);
Ok(())
}
_ => { _ => {
p.expected_at("argument list"); p.expected_at("argument list");
Err(()) Err(())
} }
}; })
callee.end(p, NodeKind::Call);
res
} }
/// Parse the arguments to a function call. /// Parse the arguments to a function call.
fn args(p: &mut Parser, allow_template: bool) -> ParseResult { fn args(p: &mut Parser, allow_template: bool) {
p.start(); p.perform(NodeKind::CallArgs, |p| {
if !allow_template || p.peek_direct() == Some(&NodeKind::LeftParen) { if !allow_template || p.peek_direct() == Some(&NodeKind::LeftParen) {
p.start_group(Group::Paren, TokenMode::Code); p.start_group(Group::Paren, TokenMode::Code);
collection(p); collection(p);
p.end_group(); p.end_group();
} }
while allow_template && p.peek_direct() == Some(&NodeKind::LeftBracket) { while allow_template && p.peek_direct() == Some(&NodeKind::LeftBracket) {
template(p); template(p);
} }
})
p.end(NodeKind::CallArgs);
Ok(())
} }
/// Parse a with expression. /// Parse a with expression.
fn with_expr(p: &mut Parser, marker: &Marker) -> ParseResult { fn with_expr(p: &mut Parser, marker: &Marker) -> ParseResult {
p.eat_assert(&NodeKind::With); marker.perform(p, NodeKind::WithExpr, |p| {
p.eat_assert(&NodeKind::With);
let res = if p.peek() == Some(&NodeKind::LeftParen) { if p.peek() == Some(&NodeKind::LeftParen) {
args(p, false) args(p, false);
} else { Ok(())
p.expected("argument list"); } else {
Err(()) p.expected("argument list");
}; Err(())
}
marker.end(p, NodeKind::WithExpr); })
res
} }
/// Parse a let expression. /// Parse a let expression.
@ -630,17 +588,17 @@ fn let_expr(p: &mut Parser) -> ParseResult {
ident(p)?; ident(p)?;
if p.peek() == Some(&NodeKind::With) { if p.peek() == Some(&NodeKind::With) {
with_expr(p, &marker); with_expr(p, &marker)?;
} else { } else {
// If a parenthesis follows, this is a function definition. // If a parenthesis follows, this is a function definition.
let has_params = if p.peek_direct() == Some(&NodeKind::LeftParen) { let has_params = if p.peek_direct() == Some(&NodeKind::LeftParen) {
p.start(); p.perform(NodeKind::ClosureParams, |p| {
p.start_group(Group::Paren, TokenMode::Code); p.start_group(Group::Paren, TokenMode::Code);
let marker = p.marker(); let marker = p.marker();
collection(p); collection(p);
params(p, &marker, true); params(p, &marker, true);
p.end_group(); p.end_group();
p.end(NodeKind::ClosureParams); });
true true
} else { } else {
false false
@ -699,13 +657,10 @@ fn for_expr(p: &mut Parser) -> ParseResult {
p.eat_assert(&NodeKind::For); p.eat_assert(&NodeKind::For);
for_pattern(p)?; for_pattern(p)?;
if p.eat_expect(&NodeKind::In) { p.eat_expect(&NodeKind::In)?;
expr(p)?; expr(p)?;
body(p)?; body(p)?;
Ok(()) Ok(())
} else {
Err(())
}
}) })
} }
@ -723,44 +678,42 @@ fn for_pattern(p: &mut Parser) -> ParseResult {
/// Parse an import expression. /// Parse an import expression.
fn import_expr(p: &mut Parser) -> ParseResult { fn import_expr(p: &mut Parser) -> ParseResult {
p.start(); p.perform(NodeKind::ImportExpr, |p| {
p.eat_assert(&NodeKind::Import); p.eat_assert(&NodeKind::Import);
if !p.eat_if(&NodeKind::Star) { if !p.eat_if(&NodeKind::Star) {
// This is the list of identifiers scenario. // This is the list of identifiers scenario.
p.start(); p.perform(NodeKind::ImportItems, |p| {
p.start_group(Group::Imports, TokenMode::Code); p.start_group(Group::Imports, TokenMode::Code);
let marker = p.marker(); let marker = p.marker();
let items = collection(p).1; let items = collection(p).1;
if items == 0 { if items == 0 {
p.expected_at("import items"); p.expected_at("import items");
}
p.end_group();
marker.filter_children(p, |n| match n.kind() {
NodeKind::Ident(_) | NodeKind::Comma => Ok(()),
_ => Err((ErrorPosition::Full, "expected identifier".into())),
});
});
};
if p.eat_expect(&NodeKind::From).is_ok() {
expr(p)?;
} }
p.end_group();
marker.filter_children( Ok(())
p, })
|n| matches!(n.kind(), NodeKind::Ident(_) | NodeKind::Comma),
|_| (ErrorPosition::Full, "expected identifier".into()),
);
p.end(NodeKind::ImportItems);
};
if p.eat_expect(&NodeKind::From) {
expr(p);
}
p.end(NodeKind::ImportExpr);
Ok(())
} }
/// Parse an include expression. /// Parse an include expression.
fn include_expr(p: &mut Parser) -> ParseResult { fn include_expr(p: &mut Parser) -> ParseResult {
p.start(); p.perform(NodeKind::IncludeExpr, |p| {
p.eat_assert(&NodeKind::Include); p.eat_assert(&NodeKind::Include);
expr(p)?;
expr(p); Ok(())
p.end(NodeKind::IncludeExpr); })
Ok(())
} }
/// Parse an identifier. /// Parse an identifier.
@ -784,7 +737,9 @@ fn body(p: &mut Parser) -> ParseResult {
Some(NodeKind::LeftBrace) => block(p), Some(NodeKind::LeftBrace) => block(p),
_ => { _ => {
p.expected_at("body"); p.expected_at("body");
Err(()) return Err(());
} }
} }
Ok(())
} }

View File

@ -62,28 +62,24 @@ pub struct Marker(usize);
impl Marker { impl Marker {
/// Wraps all children in front of the marker. /// Wraps all children in front of the marker.
pub fn end(&self, p: &mut Parser, kind: NodeKind) { pub fn end(&self, p: &mut Parser, kind: NodeKind) {
if p.children.len() != self.0 { let stop_nl = p.stop_at_newline();
let stop_nl = p.stop_at_newline(); let end = (self.0 .. p.children.len())
let end = (self.0 .. p.children.len()) .rev()
.rev() .find(|&i| !Parser::skip_type_ext(p.children[i].kind(), stop_nl))
.find(|&i| !Parser::skip_type_ext(p.children[i].kind(), stop_nl)) .unwrap_or(self.0)
.unwrap_or(self.0) + 1;
+ 1;
let children: Vec<_> = p.children.drain(self.0 .. end).collect(); let children: Vec<_> = p.children.drain(self.0 .. end).collect();
let len = children.iter().map(Green::len).sum(); p.children
p.children .insert(self.0, GreenNode::with_children(kind, children).into());
.insert(self.0, GreenNode::with_children(kind, len, children).into());
}
} }
/// Wrap all children that do not fulfill the predicate in error nodes. /// Wrap all children that do not fulfill the predicate in error nodes.
pub fn filter_children<F, G>(&self, p: &mut Parser, f: F, error: G) pub fn filter_children<F>(&self, p: &mut Parser, f: F)
where where
F: Fn(&Green) -> bool, F: Fn(&Green) -> Result<(), (ErrorPosition, EcoString)>,
G: Fn(&NodeKind) -> (ErrorPosition, EcoString),
{ {
p.filter_children(self, f, error) p.filter_children(self, f)
} }
/// Insert an error message that `what` was expected at the marker position. /// Insert an error message that `what` was expected at the marker position.
@ -97,6 +93,20 @@ impl Marker {
.into(), .into(),
); );
} }
/// Return a reference to the child after the marker.
pub fn child_at<'a>(&self, p: &'a Parser) -> Option<&'a Green> {
p.children.get(self.0)
}
pub fn perform<T, F>(&self, p: &mut Parser, kind: NodeKind, f: F) -> T
where
F: FnOnce(&mut Parser) -> T,
{
let success = f(p);
self.end(p, kind);
success
}
} }
impl<'s> Parser<'s> { impl<'s> Parser<'s> {
@ -121,58 +131,31 @@ impl<'s> Parser<'s> {
/// ///
/// Each start call has to be matched with a call to `end`, /// Each start call has to be matched with a call to `end`,
/// `end_with_custom_children`, `lift`, `abort`, or `end_or_abort`. /// `end_with_custom_children`, `lift`, `abort`, or `end_or_abort`.
pub fn start(&mut self) { fn start(&mut self) {
self.stack.push(std::mem::take(&mut self.children)); self.stack.push(std::mem::take(&mut self.children));
} }
/// Filter the last children using the given predicate. /// Filter the last children using the given predicate.
fn filter_children<F, G>(&mut self, count: &Marker, f: F, error: G) fn filter_children<F>(&mut self, count: &Marker, f: F)
where where
F: Fn(&Green) -> bool, F: Fn(&Green) -> Result<(), (ErrorPosition, EcoString)>,
G: Fn(&NodeKind) -> (ErrorPosition, EcoString),
{ {
for child in &mut self.children[count.0 ..] { for child in &mut self.children[count.0 ..] {
if !((self.tokens.mode() != TokenMode::Code if !((self.tokens.mode() != TokenMode::Code
|| Self::skip_type_ext(child.kind(), false)) || Self::skip_type_ext(child.kind(), false))
|| child.kind().is_error() || child.kind().is_error())
|| f(&child))
{ {
let (pos, msg) = error(child.kind()); if let Err((pos, msg)) = f(child) {
let inner = std::mem::take(child); let inner = std::mem::take(child);
*child = *child =
GreenNode::with_child(NodeKind::Error(pos, msg), inner.len(), inner) GreenNode::with_child(NodeKind::Error(pos, msg), inner).into();
.into(); }
} }
} }
} }
/// Return the a child from the current stack frame specified by its
/// non-trivia index from the back.
pub fn child(&self, child: usize) -> Option<&Green> {
self.node_index_from_back(child).map(|i| &self.children[i])
}
/// Map a non-trivia index from the back of the current stack frame to a
/// normal index.
fn node_index_from_back(&self, child: usize) -> Option<usize> {
let len = self.children.len();
let code = self.tokens.mode() == TokenMode::Code;
let mut seen = 0;
for x in (0 .. len).rev() {
if self.skip_type(self.children[x].kind()) && code {
continue;
}
if seen == child {
return Some(x);
}
seen += 1;
}
None
}
/// End the current node as a node of given `kind`. /// End the current node as a node of given `kind`.
pub fn end(&mut self, kind: NodeKind) { fn end(&mut self, kind: NodeKind) {
let outer = self.stack.pop().unwrap(); let outer = self.stack.pop().unwrap();
let mut children = std::mem::replace(&mut self.children, outer); let mut children = std::mem::replace(&mut self.children, outer);
@ -191,15 +174,13 @@ impl<'s> Parser<'s> {
remains.reverse(); remains.reverse();
} }
let len = children.iter().map(|c| c.len()).sum(); self.children.push(GreenNode::with_children(kind, children).into());
self.children
.push(GreenNode::with_children(kind, len, children).into());
self.children.extend(remains); self.children.extend(remains);
} }
pub fn perform<F>(&mut self, kind: NodeKind, f: F) -> ParseResult pub fn perform<T, F>(&mut self, kind: NodeKind, f: F) -> T
where where
F: FnOnce(&mut Self) -> ParseResult, F: FnOnce(&mut Self) -> T,
{ {
self.start(); self.start();
let success = f(self); let success = f(self);
@ -267,12 +248,12 @@ impl<'s> Parser<'s> {
/// Consume the next token if it is the given one and produce an error if /// Consume the next token if it is the given one and produce an error if
/// not. /// not.
pub fn eat_expect(&mut self, t: &NodeKind) -> bool { pub fn eat_expect(&mut self, t: &NodeKind) -> ParseResult {
let eaten = self.eat_if(t); let eaten = self.eat_if(t);
if !eaten { if !eaten {
self.expected_at(t.as_str()); self.expected_at(t.as_str());
} }
eaten if eaten { Ok(()) } else { Err(()) }
} }
/// Consume the next token, debug-asserting that it is one of the given ones. /// Consume the next token, debug-asserting that it is one of the given ones.
@ -368,10 +349,9 @@ impl<'s> Parser<'s> {
/// End the parsing of a group. /// End the parsing of a group.
/// ///
/// This panics if no group was started. /// This panics if no group was started.
pub fn end_group(&mut self) -> ParseResult { pub fn end_group(&mut self) {
let prev_mode = self.tokens.mode(); let prev_mode = self.tokens.mode();
let group = self.groups.pop().expect("no started group"); let group = self.groups.pop().expect("no started group");
let mut success = true;
self.tokens.set_mode(group.prev_mode); self.tokens.set_mode(group.prev_mode);
self.repeek(); self.repeek();
@ -392,7 +372,6 @@ impl<'s> Parser<'s> {
rescan = false; rescan = false;
} else if required { } else if required {
self.push_error(format!("expected {}", end)); self.push_error(format!("expected {}", end));
success = false;
} }
} }
@ -415,8 +394,6 @@ impl<'s> Parser<'s> {
self.next = self.tokens.next(); self.next = self.tokens.next();
self.repeek(); self.repeek();
} }
if success { Ok(()) } else { Err(()) }
} }
/// Add an error that `what` was expected at the given span. /// Add an error that `what` was expected at the given span.
@ -436,12 +413,13 @@ impl<'s> Parser<'s> {
pub fn expected(&mut self, what: &str) { pub fn expected(&mut self, what: &str) {
match self.peek().cloned() { match self.peek().cloned() {
Some(found) => { Some(found) => {
self.start(); self.perform(
self.eat(); NodeKind::Error(
self.end(NodeKind::Error( ErrorPosition::Full,
ErrorPosition::Full, format!("expected {}, found {}", what, found).into(),
format!("expected {}, found {}", what, found).into(), ),
)); Self::eat,
);
} }
None => self.expected_at(what), None => self.expected_at(what),
} }
@ -451,12 +429,13 @@ impl<'s> Parser<'s> {
pub fn unexpected(&mut self) { pub fn unexpected(&mut self) {
match self.peek().cloned() { match self.peek().cloned() {
Some(found) => { Some(found) => {
self.start(); self.perform(
self.eat(); NodeKind::Error(
self.end(NodeKind::Error( ErrorPosition::Full,
ErrorPosition::Full, format!("unexpected {}", found).into(),
format!("unexpected {}", found).into(), ),
)); Self::eat,
);
} }
None => self.push_error("unexpected end of file"), None => self.push_error("unexpected end of file"),
} }

View File

@ -156,7 +156,11 @@ impl HeadingNode {
/// The section depth (numer of equals signs). /// The section depth (numer of equals signs).
pub fn level(&self) -> u8 { pub fn level(&self) -> u8 {
self.0.children().filter(|n| n.kind() == &NodeKind::Eq).count() as u8 self.0
.children()
.filter(|n| n.kind() == &NodeKind::Eq)
.count()
.min(u8::MAX.into()) as u8
} }
} }

View File

@ -98,15 +98,20 @@ pub struct GreenNode {
impl GreenNode { impl GreenNode {
/// Creates a new node with the given kind and children. /// Creates a new node with the given kind and children.
pub fn with_children(kind: NodeKind, len: usize, children: Vec<Green>) -> Self { pub fn with_children(kind: NodeKind, children: Vec<Green>) -> Self {
let mut data = GreenData::new(kind, len); let mut data = GreenData::new(kind, 0);
data.erroneous |= children.iter().any(|c| c.erroneous()); let len = children
.iter()
.inspect(|c| data.erroneous |= c.erroneous())
.map(Green::len)
.sum();
data.len = len;
Self { data, children } Self { data, children }
} }
/// Creates a new node with the given kind and a single child. /// Creates a new node with the given kind and a single child.
pub fn with_child(kind: NodeKind, len: usize, child: impl Into<Green>) -> Self { pub fn with_child(kind: NodeKind, child: impl Into<Green>) -> Self {
Self::with_children(kind, len, vec![child.into()]) Self::with_children(kind, vec![child.into()])
} }
/// The node's children. /// The node's children.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -8,8 +8,8 @@
=== Level 2 === Level 2
====== Level 6 ====== Level 6
// Too many hashtags. // At some point, it should stop shrinking.
======= Level 7 =========== Level 11
--- ---
// Heading vs. no heading. // Heading vs. no heading.