mirror of
https://github.com/typst/typst
synced 2025-06-28 08:12:53 +08:00
Style changes
Co-Authored-By: Martin <mhaug@live.de>
This commit is contained in:
parent
cf2e527a02
commit
515fe89c5e
126
src/parse/mod.rs
126
src/parse/mod.rs
@ -15,8 +15,6 @@ 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};
|
||||||
|
|
||||||
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> {
|
||||||
let mut p = Parser::new(source);
|
let mut p = Parser::new(source);
|
||||||
@ -53,29 +51,34 @@ where
|
|||||||
{
|
{
|
||||||
p.perform(NodeKind::Markup, |p| {
|
p.perform(NodeKind::Markup, |p| {
|
||||||
while !p.eof() && f(p) {
|
while !p.eof() && f(p) {
|
||||||
markup_node(p, &mut at_start).ok();
|
markup_node(p, &mut at_start);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a markup node.
|
/// Parse a markup node.
|
||||||
fn markup_node(p: &mut Parser, at_start: &mut bool) -> ParseResult {
|
fn markup_node(p: &mut Parser, at_start: &mut bool) {
|
||||||
let token = match p.peek() {
|
let token = match p.peek() {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => return Ok(()),
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
match token {
|
match token {
|
||||||
// Whitespace.
|
// Whitespace.
|
||||||
NodeKind::Space(newlines) => {
|
NodeKind::Space(newlines) => {
|
||||||
*at_start |= *newlines > 0;
|
*at_start |= *newlines > 0;
|
||||||
|
|
||||||
if *newlines < 2 {
|
if *newlines < 2 {
|
||||||
p.eat();
|
p.eat();
|
||||||
} else {
|
} else {
|
||||||
p.convert(NodeKind::Parbreak);
|
p.convert(NodeKind::Parbreak);
|
||||||
}
|
}
|
||||||
return Ok(());
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comments.
|
||||||
|
NodeKind::LineComment | NodeKind::BlockComment => {
|
||||||
|
p.eat();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text and markup.
|
// Text and markup.
|
||||||
@ -112,7 +115,7 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) -> ParseResult {
|
|||||||
let group = if stmt { Group::Stmt } else { Group::Expr };
|
let group = if stmt { Group::Stmt } else { Group::Expr };
|
||||||
|
|
||||||
p.start_group(group, TokenMode::Code);
|
p.start_group(group, TokenMode::Code);
|
||||||
let res = expr_with(p, true, 0);
|
let res = expr_prec(p, true, 0);
|
||||||
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");
|
||||||
}
|
}
|
||||||
@ -123,33 +126,18 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) -> ParseResult {
|
|||||||
NodeKind::LeftBrace => block(p),
|
NodeKind::LeftBrace => block(p),
|
||||||
NodeKind::LeftBracket => template(p),
|
NodeKind::LeftBracket => template(p),
|
||||||
|
|
||||||
// Comments.
|
NodeKind::Error(_, _) => p.eat(),
|
||||||
NodeKind::LineComment | NodeKind::BlockComment => {
|
_ => p.unexpected(),
|
||||||
p.eat();
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeKind::Error(_, _) => {
|
|
||||||
p.eat();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
p.unexpected();
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
*at_start = false;
|
*at_start = false;
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a heading.
|
/// Parse a heading.
|
||||||
fn heading(p: &mut Parser) {
|
fn heading(p: &mut Parser) {
|
||||||
p.perform(NodeKind::Heading, |p| {
|
p.perform(NodeKind::Heading, |p| {
|
||||||
p.eat_assert(&NodeKind::Eq);
|
p.eat_assert(&NodeKind::Eq);
|
||||||
|
|
||||||
while p.eat_if(&NodeKind::Eq) {}
|
while p.eat_if(&NodeKind::Eq) {}
|
||||||
|
|
||||||
let column = p.column(p.prev_end());
|
let column = p.column(p.prev_end());
|
||||||
markup_indented(p, column);
|
markup_indented(p, column);
|
||||||
});
|
});
|
||||||
@ -175,7 +163,7 @@ fn enum_node(p: &mut Parser) {
|
|||||||
|
|
||||||
/// Parse an expression.
|
/// Parse an expression.
|
||||||
fn expr(p: &mut Parser) -> ParseResult {
|
fn expr(p: &mut Parser) -> ParseResult {
|
||||||
expr_with(p, false, 0)
|
expr_prec(p, false, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an expression with operators having at least the minimum precedence.
|
/// Parse an expression with operators having at least the minimum precedence.
|
||||||
@ -185,20 +173,17 @@ fn expr(p: &mut Parser) -> ParseResult {
|
|||||||
/// in markup.
|
/// in markup.
|
||||||
///
|
///
|
||||||
/// Stops parsing at operations with lower precedence than `min_prec`,
|
/// Stops parsing at operations with lower precedence than `min_prec`,
|
||||||
fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
|
fn expr_prec(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
|
||||||
let marker = p.marker();
|
let marker = p.marker();
|
||||||
|
|
||||||
// Start the unary expression.
|
// Start the unary expression.
|
||||||
match p.eat_map(|x| UnOp::from_token(&x)) {
|
match p.eat_map(|x| UnOp::from_token(&x)) {
|
||||||
Some(op) => {
|
Some(op) => {
|
||||||
let prec = op.precedence();
|
let prec = op.precedence();
|
||||||
expr_with(p, atomic, prec)?;
|
expr_prec(p, atomic, prec)?;
|
||||||
|
|
||||||
marker.end(p, NodeKind::Unary);
|
marker.end(p, NodeKind::Unary);
|
||||||
}
|
}
|
||||||
None => {
|
None => primary(p, atomic)?,
|
||||||
primary(p, atomic)?;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@ -213,7 +198,7 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if atomic {
|
if atomic {
|
||||||
break Ok(());
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.peek() == Some(&NodeKind::With) {
|
if p.peek() == Some(&NodeKind::With) {
|
||||||
@ -222,14 +207,12 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
|
|||||||
|
|
||||||
let op = match p.peek().and_then(BinOp::from_token) {
|
let op = match p.peek().and_then(BinOp::from_token) {
|
||||||
Some(binop) => binop,
|
Some(binop) => binop,
|
||||||
None => {
|
None => break,
|
||||||
break Ok(());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut prec = op.precedence();
|
let mut prec = op.precedence();
|
||||||
if prec < min_prec {
|
if prec < min_prec {
|
||||||
break Ok(());
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.eat();
|
p.eat();
|
||||||
@ -239,8 +222,10 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
|
|||||||
Associativity::Right => {}
|
Associativity::Right => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
marker.perform(p, NodeKind::Binary, |p| expr_with(p, atomic, prec))?;
|
marker.perform(p, NodeKind::Binary, |p| expr_prec(p, atomic, prec))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a primary expression.
|
/// Parse a primary expression.
|
||||||
@ -260,7 +245,6 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
|
|||||||
if !atomic && p.peek() == Some(&NodeKind::Arrow) {
|
if !atomic && p.peek() == Some(&NodeKind::Arrow) {
|
||||||
marker.end(p, NodeKind::ClosureParams);
|
marker.end(p, NodeKind::ClosureParams);
|
||||||
p.eat();
|
p.eat();
|
||||||
|
|
||||||
marker.perform(p, NodeKind::Closure, expr)
|
marker.perform(p, NodeKind::Closure, expr)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -288,7 +272,7 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
|
|||||||
|
|
||||||
Some(NodeKind::Error(_, _)) => {
|
Some(NodeKind::Error(_, _)) => {
|
||||||
p.eat();
|
p.eat();
|
||||||
Ok(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing.
|
// Nothing.
|
||||||
@ -330,6 +314,7 @@ fn literal(p: &mut Parser) -> bool {
|
|||||||
/// - Parameter list of closure expression
|
/// - Parameter list of closure expression
|
||||||
fn parenthesized(p: &mut Parser) -> ParseResult {
|
fn parenthesized(p: &mut Parser) -> ParseResult {
|
||||||
let marker = p.marker();
|
let marker = p.marker();
|
||||||
|
|
||||||
p.start_group(Group::Paren, TokenMode::Code);
|
p.start_group(Group::Paren, TokenMode::Code);
|
||||||
let colon = p.eat_if(&NodeKind::Colon);
|
let colon = p.eat_if(&NodeKind::Colon);
|
||||||
let kind = collection(p).0;
|
let kind = collection(p).0;
|
||||||
@ -337,28 +322,26 @@ fn parenthesized(p: &mut Parser) -> ParseResult {
|
|||||||
|
|
||||||
// Leading colon makes this a (empty) dictionary.
|
// Leading colon makes this a (empty) dictionary.
|
||||||
if colon {
|
if colon {
|
||||||
return dict(p, &marker);
|
dict(p, &marker);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arrow means this is a closure's parameter list.
|
// Arrow means this is a closure's parameter list.
|
||||||
if p.peek() == Some(&NodeKind::Arrow) {
|
if p.peek() == Some(&NodeKind::Arrow) {
|
||||||
params(p, &marker, true);
|
params(p, &marker, true);
|
||||||
marker.end(p, NodeKind::ClosureParams);
|
marker.end(p, NodeKind::ClosureParams);
|
||||||
|
|
||||||
p.eat_assert(&NodeKind::Arrow);
|
p.eat_assert(&NodeKind::Arrow);
|
||||||
|
|
||||||
return marker.perform(p, NodeKind::Closure, expr);
|
return marker.perform(p, NodeKind::Closure, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find out which kind of collection this is.
|
// Find out which kind of collection this is.
|
||||||
match kind {
|
match kind {
|
||||||
CollectionKind::Group => {
|
CollectionKind::Group => marker.end(p, NodeKind::Group),
|
||||||
marker.end(p, NodeKind::Group);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
CollectionKind::Positional => array(p, &marker),
|
CollectionKind::Positional => array(p, &marker),
|
||||||
CollectionKind::Named => dict(p, &marker),
|
CollectionKind::Named => dict(p, &marker),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type of a collection.
|
/// The type of a collection.
|
||||||
@ -380,17 +363,18 @@ enum CollectionKind {
|
|||||||
fn collection(p: &mut Parser) -> (CollectionKind, usize) {
|
fn collection(p: &mut Parser) -> (CollectionKind, usize) {
|
||||||
let mut items = 0;
|
let mut items = 0;
|
||||||
let mut kind = CollectionKind::Positional;
|
let mut kind = CollectionKind::Positional;
|
||||||
let mut has_comma = false;
|
let mut can_group = true;
|
||||||
let mut missing_coma: Option<Marker> = None;
|
let mut missing_coma: Option<Marker> = None;
|
||||||
|
|
||||||
while !p.eof() {
|
while !p.eof() {
|
||||||
if let Ok(item_kind) = item(p) {
|
if let Ok(item_kind) = item(p) {
|
||||||
if items == 0 && item_kind == NodeKind::Named {
|
if items == 0 && item_kind == NodeKind::Named {
|
||||||
kind = CollectionKind::Named;
|
kind = CollectionKind::Named;
|
||||||
|
can_group = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if item_kind == NodeKind::Spread {
|
if item_kind == NodeKind::Spread {
|
||||||
has_comma = true;
|
can_group = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
items += 1;
|
items += 1;
|
||||||
@ -404,14 +388,14 @@ fn collection(p: &mut Parser) -> (CollectionKind, usize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if p.eat_if(&NodeKind::Comma) {
|
if p.eat_if(&NodeKind::Comma) {
|
||||||
has_comma = true;
|
can_group = false;
|
||||||
} else {
|
} else {
|
||||||
missing_coma = Some(p.marker());
|
missing_coma = Some(p.marker());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !has_comma && items == 1 && kind == CollectionKind::Positional {
|
if can_group && items == 1 {
|
||||||
kind = CollectionKind::Group;
|
kind = CollectionKind::Group;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,23 +406,19 @@ fn collection(p: &mut Parser) -> (CollectionKind, usize) {
|
|||||||
fn item(p: &mut Parser) -> ParseResult<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) {
|
||||||
return marker
|
marker.perform(p, NodeKind::Spread, expr)?;
|
||||||
.perform(p, NodeKind::Spread, |p| expr(p).map(|_| NodeKind::Spread));
|
return Ok(NodeKind::Spread);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident_marker = p.marker();
|
|
||||||
expr(p)?;
|
expr(p)?;
|
||||||
|
|
||||||
if p.peek() == Some(&NodeKind::Colon) {
|
if p.peek() == Some(&NodeKind::Colon) {
|
||||||
marker.perform(p, NodeKind::Named, |p| {
|
marker.perform(p, NodeKind::Named, |p| {
|
||||||
if matches!(
|
if matches!(marker.child_at(p).unwrap().kind(), &NodeKind::Ident(_)) {
|
||||||
ident_marker.child_at(p).unwrap().kind(),
|
|
||||||
&NodeKind::Ident(_)
|
|
||||||
) {
|
|
||||||
p.eat();
|
p.eat();
|
||||||
expr(p).map(|_| NodeKind::Named)
|
expr(p)
|
||||||
} else {
|
} else {
|
||||||
ident_marker.end(
|
marker.end(
|
||||||
p,
|
p,
|
||||||
NodeKind::Error(ErrorPosition::Full, "expected identifier".into()),
|
NodeKind::Error(ErrorPosition::Full, "expected identifier".into()),
|
||||||
);
|
);
|
||||||
@ -447,7 +427,8 @@ fn item(p: &mut Parser) -> ParseResult<NodeKind> {
|
|||||||
expr(p).ok();
|
expr(p).ok();
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
})
|
})?;
|
||||||
|
Ok(NodeKind::Named)
|
||||||
} else {
|
} else {
|
||||||
Ok(p.last_child().unwrap().kind().clone())
|
Ok(p.last_child().unwrap().kind().clone())
|
||||||
}
|
}
|
||||||
@ -455,7 +436,7 @@ fn item(p: &mut Parser) -> ParseResult<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) {
|
||||||
marker.filter_children(p, |x| match x.kind() {
|
marker.filter_children(p, |x| match x.kind() {
|
||||||
NodeKind::Named => Err((
|
NodeKind::Named => Err((
|
||||||
ErrorPosition::Full,
|
ErrorPosition::Full,
|
||||||
@ -466,14 +447,12 @@ fn array(p: &mut Parser, marker: &Marker) -> ParseResult {
|
|||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
});
|
});
|
||||||
|
|
||||||
marker.end(p, NodeKind::Array);
|
marker.end(p, NodeKind::Array);
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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) {
|
||||||
marker.filter_children(p, |x| match x.kind() {
|
marker.filter_children(p, |x| match x.kind() {
|
||||||
NodeKind::Named | NodeKind::Comma | NodeKind::Colon => Ok(()),
|
NodeKind::Named | NodeKind::Comma | NodeKind::Colon => Ok(()),
|
||||||
NodeKind::Spread => {
|
NodeKind::Spread => {
|
||||||
@ -485,9 +464,7 @@ fn dict(p: &mut Parser, marker: &Marker) -> ParseResult {
|
|||||||
"expected named pair, found expression".into(),
|
"expected named pair, found expression".into(),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
|
|
||||||
marker.end(p, NodeKind::Dict);
|
marker.end(p, NodeKind::Dict);
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a collection into a list of parameters, producing errors for
|
/// Convert a collection into a list of parameters, producing errors for
|
||||||
@ -591,7 +568,8 @@ fn let_expr(p: &mut Parser) -> ParseResult {
|
|||||||
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 = p.peek_direct() == Some(&NodeKind::LeftParen);
|
||||||
|
if has_params {
|
||||||
p.perform(NodeKind::ClosureParams, |p| {
|
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();
|
||||||
@ -599,10 +577,7 @@ fn let_expr(p: &mut Parser) -> ParseResult {
|
|||||||
params(p, &marker, true);
|
params(p, &marker, true);
|
||||||
p.end_group();
|
p.end_group();
|
||||||
});
|
});
|
||||||
true
|
}
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
if p.eat_if(&NodeKind::Eq) {
|
if p.eat_if(&NodeKind::Eq) {
|
||||||
expr(p)?;
|
expr(p)?;
|
||||||
@ -655,7 +630,6 @@ fn while_expr(p: &mut Parser) -> ParseResult {
|
|||||||
fn for_expr(p: &mut Parser) -> ParseResult {
|
fn for_expr(p: &mut Parser) -> ParseResult {
|
||||||
p.perform(NodeKind::ForExpr, |p| {
|
p.perform(NodeKind::ForExpr, |p| {
|
||||||
p.eat_assert(&NodeKind::For);
|
p.eat_assert(&NodeKind::For);
|
||||||
|
|
||||||
for_pattern(p)?;
|
for_pattern(p)?;
|
||||||
p.eat_expect(&NodeKind::In)?;
|
p.eat_expect(&NodeKind::In)?;
|
||||||
expr(p)?;
|
expr(p)?;
|
||||||
@ -668,8 +642,7 @@ fn for_expr(p: &mut Parser) -> ParseResult {
|
|||||||
fn for_pattern(p: &mut Parser) -> ParseResult {
|
fn for_pattern(p: &mut Parser) -> ParseResult {
|
||||||
p.perform(NodeKind::ForPattern, |p| {
|
p.perform(NodeKind::ForPattern, |p| {
|
||||||
ident(p)?;
|
ident(p)?;
|
||||||
if p.peek() == Some(&NodeKind::Comma) {
|
if p.eat_if(&NodeKind::Comma) {
|
||||||
p.eat();
|
|
||||||
ident(p)?;
|
ident(p)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -699,9 +672,8 @@ fn import_expr(p: &mut Parser) -> ParseResult {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if p.eat_expect(&NodeKind::From).is_ok() {
|
p.eat_expect(&NodeKind::From)?;
|
||||||
expr(p)?;
|
expr(p)?;
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::{ParseResult, TokenMode, Tokens};
|
use super::{TokenMode, Tokens};
|
||||||
use crate::syntax::{ErrorPosition, Green, GreenData, GreenNode, NodeKind};
|
use crate::syntax::{ErrorPosition, Green, GreenData, GreenNode, NodeKind};
|
||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
|
|
||||||
|
/// Allows parser methods to use the try operator. Not exposed as the parser
|
||||||
|
/// recovers from all errors.
|
||||||
|
pub(crate) type ParseResult<T = ()> = Result<T, ()>;
|
||||||
|
|
||||||
/// A convenient token-based parser.
|
/// A convenient token-based parser.
|
||||||
pub struct Parser<'s> {
|
pub struct Parser<'s> {
|
||||||
/// The parsed file.
|
/// The parsed file.
|
||||||
@ -56,59 +60,6 @@ pub enum Group {
|
|||||||
Imports,
|
Imports,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A marker that indicates where a child may start.
|
|
||||||
pub struct Marker(usize);
|
|
||||||
|
|
||||||
impl Marker {
|
|
||||||
/// Wraps all children in front of the marker.
|
|
||||||
pub fn end(&self, p: &mut Parser, kind: NodeKind) {
|
|
||||||
let stop_nl = p.stop_at_newline();
|
|
||||||
let end = (self.0 .. p.children.len())
|
|
||||||
.rev()
|
|
||||||
.find(|&i| !Parser::skip_type_ext(p.children[i].kind(), stop_nl))
|
|
||||||
.unwrap_or(self.0)
|
|
||||||
+ 1;
|
|
||||||
|
|
||||||
let children: Vec<_> = p.children.drain(self.0 .. end).collect();
|
|
||||||
p.children
|
|
||||||
.insert(self.0, GreenNode::with_children(kind, children).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrap all children that do not fulfill the predicate in error nodes.
|
|
||||||
pub fn filter_children<F>(&self, p: &mut Parser, f: F)
|
|
||||||
where
|
|
||||||
F: Fn(&Green) -> Result<(), (ErrorPosition, EcoString)>,
|
|
||||||
{
|
|
||||||
p.filter_children(self, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Insert an error message that `what` was expected at the marker position.
|
|
||||||
pub fn expected_at(&self, p: &mut Parser, what: &str) {
|
|
||||||
p.children.insert(
|
|
||||||
self.0,
|
|
||||||
GreenData::new(
|
|
||||||
NodeKind::Error(ErrorPosition::Full, format!("expected {}", what).into()),
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.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> {
|
||||||
/// Create a new parser for the source string.
|
/// Create a new parser for the source string.
|
||||||
pub fn new(src: &'s str) -> Self {
|
pub fn new(src: &'s str) -> Self {
|
||||||
@ -127,40 +78,16 @@ impl<'s> Parser<'s> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start a nested node.
|
/// Perform a subparse that wraps its result in a node with the given kind.
|
||||||
///
|
pub fn perform<T, F>(&mut self, kind: NodeKind, f: F) -> T
|
||||||
/// Each start call has to be matched with a call to `end`,
|
|
||||||
/// `end_with_custom_children`, `lift`, `abort`, or `end_or_abort`.
|
|
||||||
fn start(&mut self) {
|
|
||||||
self.stack.push(std::mem::take(&mut self.children));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Filter the last children using the given predicate.
|
|
||||||
fn filter_children<F>(&mut self, count: &Marker, f: F)
|
|
||||||
where
|
where
|
||||||
F: Fn(&Green) -> Result<(), (ErrorPosition, EcoString)>,
|
F: FnOnce(&mut Self) -> T,
|
||||||
{
|
{
|
||||||
for child in &mut self.children[count.0 ..] {
|
let prev = std::mem::take(&mut self.children);
|
||||||
if !((self.tokens.mode() != TokenMode::Code
|
let output = f(self);
|
||||||
|| Self::skip_type_ext(child.kind(), false))
|
let mut children = std::mem::replace(&mut self.children, prev);
|
||||||
|| child.kind().is_error())
|
|
||||||
{
|
|
||||||
if let Err((pos, msg)) = f(child) {
|
|
||||||
let inner = std::mem::take(child);
|
|
||||||
*child =
|
|
||||||
GreenNode::with_child(NodeKind::Error(pos, msg), inner).into();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// End the current node as a node of given `kind`.
|
// Trailing trivia should not be wrapped into the new node.
|
||||||
fn end(&mut self, kind: NodeKind) {
|
|
||||||
let outer = self.stack.pop().unwrap();
|
|
||||||
let mut children = std::mem::replace(&mut self.children, outer);
|
|
||||||
|
|
||||||
// have trailing whitespace continue to sit in self.children in code
|
|
||||||
// mode.
|
|
||||||
let mut remains = vec![];
|
let mut remains = vec![];
|
||||||
if self.tokens.mode() == TokenMode::Code {
|
if self.tokens.mode() == TokenMode::Code {
|
||||||
let len = children.len();
|
let len = children.len();
|
||||||
@ -176,16 +103,8 @@ impl<'s> Parser<'s> {
|
|||||||
|
|
||||||
self.children.push(GreenNode::with_children(kind, children).into());
|
self.children.push(GreenNode::with_children(kind, children).into());
|
||||||
self.children.extend(remains);
|
self.children.extend(remains);
|
||||||
}
|
|
||||||
|
|
||||||
pub fn perform<T, F>(&mut self, kind: NodeKind, f: F) -> T
|
output
|
||||||
where
|
|
||||||
F: FnOnce(&mut Self) -> T,
|
|
||||||
{
|
|
||||||
self.start();
|
|
||||||
let success = f(self);
|
|
||||||
self.end(kind);
|
|
||||||
success
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Eat and wrap the next token.
|
/// Eat and wrap the next token.
|
||||||
@ -332,7 +251,6 @@ impl<'s> Parser<'s> {
|
|||||||
/// This panics if the next token does not start the given group.
|
/// This panics if the next token does not start the given group.
|
||||||
pub fn start_group(&mut self, kind: Group, mode: TokenMode) {
|
pub fn start_group(&mut self, kind: Group, mode: TokenMode) {
|
||||||
self.groups.push(GroupEntry { kind, prev_mode: self.tokens.mode() });
|
self.groups.push(GroupEntry { kind, prev_mode: self.tokens.mode() });
|
||||||
|
|
||||||
self.tokens.set_mode(mode);
|
self.tokens.set_mode(mode);
|
||||||
self.repeek();
|
self.repeek();
|
||||||
|
|
||||||
@ -534,3 +452,67 @@ impl<'s> Parser<'s> {
|
|||||||
Marker(self.children.len())
|
Marker(self.children.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A marker that indicates where a child may start.
|
||||||
|
pub struct Marker(usize);
|
||||||
|
|
||||||
|
impl Marker {
|
||||||
|
/// Wraps all children in front of the marker.
|
||||||
|
pub fn end(&self, p: &mut Parser, kind: NodeKind) {
|
||||||
|
let stop_nl = p.stop_at_newline();
|
||||||
|
let end = (self.0 .. p.children.len())
|
||||||
|
.rev()
|
||||||
|
.find(|&i| !Parser::skip_type_ext(p.children[i].kind(), stop_nl))
|
||||||
|
.unwrap_or(self.0)
|
||||||
|
+ 1;
|
||||||
|
|
||||||
|
let children: Vec<_> = p.children.drain(self.0 .. end).collect();
|
||||||
|
p.children
|
||||||
|
.insert(self.0, GreenNode::with_children(kind, children).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrap all children that do not fulfill the predicate in error nodes.
|
||||||
|
pub fn filter_children<F>(&self, p: &mut Parser, f: F)
|
||||||
|
where
|
||||||
|
F: Fn(&Green) -> Result<(), (ErrorPosition, EcoString)>,
|
||||||
|
{
|
||||||
|
for child in &mut p.children[self.0 ..] {
|
||||||
|
if !((p.tokens.mode() != TokenMode::Code
|
||||||
|
|| Parser::skip_type_ext(child.kind(), false))
|
||||||
|
|| child.kind().is_error())
|
||||||
|
{
|
||||||
|
if let Err((pos, msg)) = f(child) {
|
||||||
|
let inner = std::mem::take(child);
|
||||||
|
*child =
|
||||||
|
GreenNode::with_child(NodeKind::Error(pos, msg), inner).into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert an error message that `what` was expected at the marker position.
|
||||||
|
pub fn expected_at(&self, p: &mut Parser, what: &str) {
|
||||||
|
p.children.insert(
|
||||||
|
self.0,
|
||||||
|
GreenData::new(
|
||||||
|
NodeKind::Error(ErrorPosition::Full, format!("expected {}", what).into()),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -114,5 +114,4 @@ This is never reached.
|
|||||||
// An item after a star.
|
// An item after a star.
|
||||||
// Should output `, a from "target.typ"`.
|
// Should output `, a from "target.typ"`.
|
||||||
// Error: 10 expected keyword `from`
|
// Error: 10 expected keyword `from`
|
||||||
// Error: 10 expected semicolon or line break
|
|
||||||
#import *, a from "target.typ"
|
#import *, a from "target.typ"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user