mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Code Review: No Patrick, question marks are not an instrument
This commit is contained in:
parent
5c952d56d0
commit
cf2e527a02
@ -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;
|
||||||
});
|
});
|
||||||
|
269
src/parse/mod.rs
269
src/parse/mod.rs
@ -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,24 +419,24 @@ 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| {
|
||||||
|
if matches!(
|
||||||
|
ident_marker.child_at(p).unwrap().kind(),
|
||||||
|
&NodeKind::Ident(_)
|
||||||
|
) {
|
||||||
p.eat();
|
p.eat();
|
||||||
expr(p)
|
expr(p).map(|_| NodeKind::Named)
|
||||||
} else {
|
} else {
|
||||||
ident_marker.end(
|
ident_marker.end(
|
||||||
p,
|
p,
|
||||||
@ -464,12 +444,10 @@ fn item(p: &mut Parser) -> Result<NodeKind, ()> {
|
|||||||
);
|
);
|
||||||
p.eat();
|
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() {
|
|
||||||
NodeKind::Named | NodeKind::Spread => false,
|
|
||||||
_ => true,
|
|
||||||
},
|
|
||||||
|kind| match kind {
|
|
||||||
NodeKind::Named => (
|
|
||||||
ErrorPosition::Full,
|
ErrorPosition::Full,
|
||||||
"expected expression, found named pair".into(),
|
"expected expression, found named pair".into(),
|
||||||
),
|
)),
|
||||||
NodeKind::Spread => {
|
NodeKind::Spread => {
|
||||||
(ErrorPosition::Full, "spreading is not allowed here".into())
|
Err((ErrorPosition::Full, "spreading is not allowed here".into()))
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => Ok(()),
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
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| {
|
|
||||||
x.kind() == &NodeKind::Named
|
|
||||||
|| x.kind().is_paren()
|
|
||||||
|| x.kind() == &NodeKind::Comma
|
|
||||||
|| x.kind() == &NodeKind::Colon
|
|
||||||
},
|
|
||||||
|kind| match kind {
|
|
||||||
NodeKind::Spread => {
|
NodeKind::Spread => {
|
||||||
(ErrorPosition::Full, "spreading is not allowed here".into())
|
Err((ErrorPosition::Full, "spreading is not allowed here".into()))
|
||||||
}
|
}
|
||||||
_ => (
|
_ if x.kind().is_paren() => Ok(()),
|
||||||
|
_ => Err((
|
||||||
ErrorPosition::Full,
|
ErrorPosition::Full,
|
||||||
"expected named pair, found expression".into(),
|
"expected named pair, found expression".into(),
|
||||||
),
|
)),
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
marker.end(p, NodeKind::Dict);
|
marker.end(p, NodeKind::Dict);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -529,69 +493,65 @@ 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();
|
p.end_group();
|
||||||
|
|
||||||
// Forcefully skip over newlines since the group's contents can't.
|
// Forcefully skip over newlines since the group's contents can't.
|
||||||
p.eat_while(|t| matches!(t, NodeKind::Space(_)));
|
p.eat_while(|t| matches!(t, NodeKind::Space(_)));
|
||||||
}
|
}
|
||||||
p.end_group();
|
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);
|
||||||
@ -601,24 +561,22 @@ fn args(p: &mut Parser, allow_template: bool) -> ParseResult {
|
|||||||
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 {
|
||||||
|
marker.perform(p, NodeKind::WithExpr, |p| {
|
||||||
p.eat_assert(&NodeKind::With);
|
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);
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
p.expected("argument list");
|
p.expected("argument list");
|
||||||
Err(())
|
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,12 +678,12 @@ 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;
|
||||||
@ -737,30 +692,28 @@ fn import_expr(p: &mut Parser) -> ParseResult {
|
|||||||
}
|
}
|
||||||
p.end_group();
|
p.end_group();
|
||||||
|
|
||||||
marker.filter_children(
|
marker.filter_children(p, |n| match n.kind() {
|
||||||
p,
|
NodeKind::Ident(_) | NodeKind::Comma => Ok(()),
|
||||||
|n| matches!(n.kind(), NodeKind::Ident(_) | NodeKind::Comma),
|
_ => Err((ErrorPosition::Full, "expected identifier".into())),
|
||||||
|_| (ErrorPosition::Full, "expected identifier".into()),
|
});
|
||||||
);
|
});
|
||||||
p.end(NodeKind::ImportItems);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if p.eat_expect(&NodeKind::From) {
|
if p.eat_expect(&NodeKind::From).is_ok() {
|
||||||
expr(p);
|
expr(p)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.end(NodeKind::ImportExpr);
|
|
||||||
Ok(())
|
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);
|
|
||||||
p.end(NodeKind::IncludeExpr);
|
|
||||||
Ok(())
|
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(())
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,6 @@ 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()
|
||||||
@ -71,19 +70,16 @@ impl Marker {
|
|||||||
+ 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, len, children).into());
|
.insert(self.0, GreenNode::with_children(kind, 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"),
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 |
@ -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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user