mirror of
https://github.com/typst/typst
synced 2025-06-28 16:22:53 +08:00
13. Reorder functions to avoid jumping around when reading code. No actual changes.
This commit is contained in:
parent
91b384ad7b
commit
97229d24e4
@ -395,6 +395,22 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Precedence and wrapper kinds for the binary math operators.
|
||||||
|
fn math_op(kind: SyntaxKind) -> Option<(SyntaxKind, SyntaxKind, ast::Assoc, usize)> {
|
||||||
|
match kind {
|
||||||
|
SyntaxKind::Underscore => {
|
||||||
|
Some((SyntaxKind::MathAttach, SyntaxKind::Hat, ast::Assoc::Right, 2))
|
||||||
|
}
|
||||||
|
SyntaxKind::Hat => {
|
||||||
|
Some((SyntaxKind::MathAttach, SyntaxKind::Underscore, ast::Assoc::Right, 2))
|
||||||
|
}
|
||||||
|
SyntaxKind::Slash => {
|
||||||
|
Some((SyntaxKind::MathFrac, SyntaxKind::End, ast::Assoc::Left, 1))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Try to parse delimiters based on the current token's unicode math class.
|
/// Try to parse delimiters based on the current token's unicode math class.
|
||||||
fn maybe_delimited(p: &mut Parser) -> bool {
|
fn maybe_delimited(p: &mut Parser) -> bool {
|
||||||
let open = math_class(p.current_text()) == Some(MathClass::Opening);
|
let open = math_class(p.current_text()) == Some(MathClass::Opening);
|
||||||
@ -464,22 +480,6 @@ fn math_class(text: &str) -> Option<MathClass> {
|
|||||||
.and_then(unicode_math_class::class)
|
.and_then(unicode_math_class::class)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Precedence and wrapper kinds for the binary math operators.
|
|
||||||
fn math_op(kind: SyntaxKind) -> Option<(SyntaxKind, SyntaxKind, ast::Assoc, usize)> {
|
|
||||||
match kind {
|
|
||||||
SyntaxKind::Underscore => {
|
|
||||||
Some((SyntaxKind::MathAttach, SyntaxKind::Hat, ast::Assoc::Right, 2))
|
|
||||||
}
|
|
||||||
SyntaxKind::Hat => {
|
|
||||||
Some((SyntaxKind::MathAttach, SyntaxKind::Underscore, ast::Assoc::Right, 2))
|
|
||||||
}
|
|
||||||
SyntaxKind::Slash => {
|
|
||||||
Some((SyntaxKind::MathFrac, SyntaxKind::End, ast::Assoc::Left, 1))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse an argument list in math: `(a, b; c, d; size: #50%)`.
|
/// Parse an argument list in math: `(a, b; c, d; size: #50%)`.
|
||||||
fn math_args(p: &mut Parser) {
|
fn math_args(p: &mut Parser) {
|
||||||
let m = p.marker();
|
let m = p.marker();
|
||||||
@ -613,11 +613,6 @@ fn code_exprs(p: &mut Parser, mut stop: impl FnMut(&Parser) -> bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a single code expression.
|
|
||||||
fn code_expr(p: &mut Parser) {
|
|
||||||
code_expr_prec(p, false, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses an atomic code expression embedded in markup or math.
|
/// Parses an atomic code expression embedded in markup or math.
|
||||||
fn embedded_code_expr(p: &mut Parser) {
|
fn embedded_code_expr(p: &mut Parser) {
|
||||||
p.with_mode(LexMode::Code, |p| {
|
p.with_mode(LexMode::Code, |p| {
|
||||||
@ -647,6 +642,11 @@ fn embedded_code_expr(p: &mut Parser) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses a single code expression.
|
||||||
|
fn code_expr(p: &mut Parser) {
|
||||||
|
code_expr_prec(p, false, 0)
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses a code expression with at least the given precedence.
|
/// Parses a code expression with at least the given precedence.
|
||||||
fn code_expr_prec(p: &mut Parser, atomic: bool, min_prec: usize) {
|
fn code_expr_prec(p: &mut Parser, atomic: bool, min_prec: usize) {
|
||||||
let m = p.marker();
|
let m = p.marker();
|
||||||
@ -777,15 +777,6 @@ fn code_primary(p: &mut Parser, atomic: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a content or code block.
|
|
||||||
fn block(p: &mut Parser) {
|
|
||||||
match p.current() {
|
|
||||||
SyntaxKind::LeftBracket => content_block(p),
|
|
||||||
SyntaxKind::LeftBrace => code_block(p),
|
|
||||||
_ => p.expected("block"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reparses a full content or code block.
|
/// Reparses a full content or code block.
|
||||||
pub(super) fn reparse_block(text: &str, range: Range<usize>) -> Option<SyntaxNode> {
|
pub(super) fn reparse_block(text: &str, range: Range<usize>) -> Option<SyntaxNode> {
|
||||||
let mut p = Parser::new(text, range.start, LexMode::Code);
|
let mut p = Parser::new(text, range.start, LexMode::Code);
|
||||||
@ -795,6 +786,15 @@ pub(super) fn reparse_block(text: &str, range: Range<usize>) -> Option<SyntaxNod
|
|||||||
.then(|| p.finish().into_iter().next().unwrap())
|
.then(|| p.finish().into_iter().next().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses a content or code block.
|
||||||
|
fn block(p: &mut Parser) {
|
||||||
|
match p.current() {
|
||||||
|
SyntaxKind::LeftBracket => content_block(p),
|
||||||
|
SyntaxKind::LeftBrace => code_block(p),
|
||||||
|
_ => p.expected("block"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses a code block: `{ let x = 1; x + 2 }`.
|
/// Parses a code block: `{ let x = 1; x + 2 }`.
|
||||||
fn code_block(p: &mut Parser) {
|
fn code_block(p: &mut Parser) {
|
||||||
let m = p.marker();
|
let m = p.marker();
|
||||||
@ -1608,6 +1608,22 @@ impl AtNewline {
|
|||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
struct Marker(usize);
|
struct Marker(usize);
|
||||||
|
|
||||||
|
// Index into the parser with markers.
|
||||||
|
impl Index<Marker> for Parser<'_> {
|
||||||
|
type Output = SyntaxNode;
|
||||||
|
|
||||||
|
fn index(&self, m: Marker) -> &Self::Output {
|
||||||
|
&self.nodes[m.0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<Marker> for Parser<'_> {
|
||||||
|
fn index_mut(&mut self, m: Marker) -> &mut Self::Output {
|
||||||
|
&mut self.nodes[m.0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creating/Consuming the parser and getting info about the current token.
|
||||||
impl<'s> Parser<'s> {
|
impl<'s> Parser<'s> {
|
||||||
/// Create a new parser starting from the given text offset and lexer mode.
|
/// Create a new parser starting from the given text offset and lexer mode.
|
||||||
fn new(text: &'s str, offset: usize, mode: LexMode) -> Self {
|
fn new(text: &'s str, offset: usize, mode: LexMode) -> Self {
|
||||||
@ -1638,32 +1654,12 @@ impl<'s> Parser<'s> {
|
|||||||
SyntaxNode::inner(kind, self.finish())
|
SyntaxNode::inner(kind, self.finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The offset into `text` of the previous token's end.
|
|
||||||
fn prev_end(&self) -> usize {
|
|
||||||
self.token.prev_end
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Similar to a `peek()` function: returns the `kind` of the next token to
|
/// Similar to a `peek()` function: returns the `kind` of the next token to
|
||||||
/// be eaten.
|
/// be eaten.
|
||||||
fn current(&self) -> SyntaxKind {
|
fn current(&self) -> SyntaxKind {
|
||||||
self.token.kind
|
self.token.kind
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The offset into `text` of the current token's start.
|
|
||||||
fn current_start(&self) -> usize {
|
|
||||||
self.token.start
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The offset into `text` of the current token's end.
|
|
||||||
fn current_end(&self) -> usize {
|
|
||||||
self.lexer.cursor()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The current token's text.
|
|
||||||
fn current_text(&self) -> &'s str {
|
|
||||||
&self.text[self.token.start..self.current_end()]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the current token is a given [`SyntaxKind`].
|
/// Whether the current token is a given [`SyntaxKind`].
|
||||||
fn at(&self, kind: SyntaxKind) -> bool {
|
fn at(&self, kind: SyntaxKind) -> bool {
|
||||||
self.token.kind == kind
|
self.token.kind == kind
|
||||||
@ -1686,11 +1682,62 @@ impl<'s> Parser<'s> {
|
|||||||
self.token.kind == kind && !self.had_trivia()
|
self.token.kind == kind && !self.had_trivia()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Eat the current token by saving it to the `nodes` vector, then move
|
/// Whether `token` had any trivia before it in Code/Math.
|
||||||
/// the lexer forward to prepare a new token.
|
fn had_trivia(&self) -> bool {
|
||||||
fn eat(&mut self) {
|
self.token.n_trivia > 0
|
||||||
self.nodes.push(std::mem::take(&mut self.token.node));
|
}
|
||||||
self.token = Self::lex(&mut self.nodes, &mut self.lexer, self.nl_mode);
|
|
||||||
|
/// Whether the current token is a newline, only used in Markup.
|
||||||
|
fn newline(&self) -> bool {
|
||||||
|
self.token.had_newline
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The number of characters until the most recent newline in `text`.
|
||||||
|
fn column(&self, at: usize) -> usize {
|
||||||
|
self.text[..at].chars().rev().take_while(|&c| !is_newline(c)).count()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The current token's text.
|
||||||
|
fn current_text(&self) -> &'s str {
|
||||||
|
&self.text[self.token.start..self.current_end()]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The offset into `text` of the current token's start.
|
||||||
|
fn current_start(&self) -> usize {
|
||||||
|
self.token.start
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The offset into `text` of the current token's end.
|
||||||
|
fn current_end(&self) -> usize {
|
||||||
|
self.lexer.cursor()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The offset into `text` of the previous token's end.
|
||||||
|
fn prev_end(&self) -> usize {
|
||||||
|
self.token.prev_end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main parsing interface for generating tokens and eating/modifying nodes.
|
||||||
|
impl<'s> Parser<'s> {
|
||||||
|
/// A marker that will point to the current token in the parser once it's
|
||||||
|
/// been eaten.
|
||||||
|
fn marker(&self) -> Marker {
|
||||||
|
Marker(self.nodes.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A marker that will point to first trivia before this token in the
|
||||||
|
/// parser (or the token itself if no trivia precede it).
|
||||||
|
fn before_trivia(&self) -> Marker {
|
||||||
|
Marker(self.nodes.len() - self.token.n_trivia)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over the non-trivia tokens following the marker.
|
||||||
|
#[track_caller]
|
||||||
|
fn post_process(&mut self, m: Marker) -> impl Iterator<Item = &mut SyntaxNode> {
|
||||||
|
self.nodes[m.0..]
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|child| !child.kind().is_error() && !child.kind().is_trivia())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Eat the current node and return a reference for in-place mutation.
|
/// Eat the current node and return a reference for in-place mutation.
|
||||||
@ -1739,45 +1786,11 @@ impl<'s> Parser<'s> {
|
|||||||
self.eat();
|
self.eat();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the current token is a newline, only used in Markup.
|
/// Eat the current token by saving it to the `nodes` vector, then move
|
||||||
fn newline(&self) -> bool {
|
/// the lexer forward to prepare a new token.
|
||||||
self.token.had_newline
|
fn eat(&mut self) {
|
||||||
}
|
self.nodes.push(std::mem::take(&mut self.token.node));
|
||||||
|
self.token = Self::lex(&mut self.nodes, &mut self.lexer, self.nl_mode);
|
||||||
/// Whether `token` had any trivia before it in Code/Math.
|
|
||||||
fn had_trivia(&self) -> bool {
|
|
||||||
self.token.n_trivia > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The number of characters until the most recent newline in `text`.
|
|
||||||
fn column(&self, at: usize) -> usize {
|
|
||||||
self.text[..at].chars().rev().take_while(|&c| !is_newline(c)).count()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A marker that will point to the current token in the parser once it's
|
|
||||||
/// been eaten.
|
|
||||||
fn marker(&self) -> Marker {
|
|
||||||
Marker(self.nodes.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A marker that will point to first trivia before this token in the
|
|
||||||
/// parser (or the token itself if no trivia precede it).
|
|
||||||
fn before_trivia(&self) -> Marker {
|
|
||||||
Marker(self.nodes.len() - self.token.n_trivia)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the last non-trivia node is an error.
|
|
||||||
fn after_error(&mut self) -> bool {
|
|
||||||
let m = self.before_trivia();
|
|
||||||
m.0 > 0 && self.nodes[m.0 - 1].kind().is_error()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterate over the non-trivia tokens following the marker.
|
|
||||||
#[track_caller]
|
|
||||||
fn post_process(&mut self, m: Marker) -> impl Iterator<Item = &mut SyntaxNode> {
|
|
||||||
self.nodes[m.0..]
|
|
||||||
.iter_mut()
|
|
||||||
.filter(|child| !child.kind().is_error() && !child.kind().is_trivia())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrap the nodes from a marker up to (but excluding) the current token in
|
/// Wrap the nodes from a marker up to (but excluding) the current token in
|
||||||
@ -1898,6 +1911,7 @@ struct PartialState {
|
|||||||
token: Token,
|
token: Token,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The Memoization interface.
|
||||||
impl<'s> Parser<'s> {
|
impl<'s> Parser<'s> {
|
||||||
/// Store the already parsed nodes and the parser state into the memo map by
|
/// Store the already parsed nodes and the parser state into the memo map by
|
||||||
/// extending the arena and storing the extended range and a checkpoint.
|
/// extending the arena and storing the extended range and a checkpoint.
|
||||||
@ -1952,6 +1966,8 @@ impl<'s> Parser<'s> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Functions for eating expected or unexpected tokens and generating errors if
|
||||||
|
/// we don't get what we expect.
|
||||||
impl<'s> Parser<'s> {
|
impl<'s> Parser<'s> {
|
||||||
/// Consume the given `kind` or produce an error.
|
/// Consume the given `kind` or produce an error.
|
||||||
fn expect(&mut self, kind: SyntaxKind) -> bool {
|
fn expect(&mut self, kind: SyntaxKind) -> bool {
|
||||||
@ -1984,6 +2000,12 @@ impl<'s> Parser<'s> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the last non-trivia node is an error.
|
||||||
|
fn after_error(&mut self) -> bool {
|
||||||
|
let m = self.before_trivia();
|
||||||
|
m.0 > 0 && self.nodes[m.0 - 1].kind().is_error()
|
||||||
|
}
|
||||||
|
|
||||||
/// Produce an error that the given `thing` was expected at the position
|
/// Produce an error that the given `thing` was expected at the position
|
||||||
/// of the marker `m`.
|
/// of the marker `m`.
|
||||||
fn expected_at(&mut self, m: Marker, thing: &str) {
|
fn expected_at(&mut self, m: Marker, thing: &str) {
|
||||||
@ -2021,17 +2043,3 @@ impl<'s> Parser<'s> {
|
|||||||
self.nodes.drain(start..end);
|
self.nodes.drain(start..end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<Marker> for Parser<'_> {
|
|
||||||
type Output = SyntaxNode;
|
|
||||||
|
|
||||||
fn index(&self, m: Marker) -> &Self::Output {
|
|
||||||
&self.nodes[m.0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IndexMut<Marker> for Parser<'_> {
|
|
||||||
fn index_mut(&mut self, m: Marker) -> &mut Self::Output {
|
|
||||||
&mut self.nodes[m.0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user