mirror of
https://github.com/typst/typst
synced 2025-05-18 11:05:28 +08:00
More efficient incremental parsing
If validation fails, we now do exponential fallback to a larger segment instead of giving up entirely.
This commit is contained in:
parent
bc1795732b
commit
d9ba84085e
@ -96,14 +96,22 @@ fn try_reparse(
|
|||||||
// possible if the markup is top-level or contained in a block, not if it is
|
// possible if the markup is top-level or contained in a block, not if it is
|
||||||
// contained in things like headings or lists because too much can go wrong
|
// contained in things like headings or lists because too much can go wrong
|
||||||
// with indent and line breaks.
|
// with indent and line breaks.
|
||||||
if node.kind() == SyntaxKind::Markup
|
if overlap.is_empty()
|
||||||
&& (parent_kind.is_none() || parent_kind == Some(SyntaxKind::ContentBlock))
|
|| node.kind() != SyntaxKind::Markup
|
||||||
&& !overlap.is_empty()
|
|| !matches!(parent_kind, None | Some(SyntaxKind::ContentBlock))
|
||||||
{
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let children = node.children_mut();
|
||||||
|
|
||||||
|
// Reparse a segment. Retries until it works, taking exponentially more
|
||||||
|
// children into account.
|
||||||
|
let mut expansion = 1;
|
||||||
|
loop {
|
||||||
// Add slack in both directions.
|
// Add slack in both directions.
|
||||||
let children = node.children_mut();
|
let mut start = overlap.start.saturating_sub(expansion.max(2));
|
||||||
let mut start = overlap.start.saturating_sub(2);
|
let mut end = (overlap.end + expansion).min(children.len());
|
||||||
let mut end = (overlap.end + 1).min(children.len());
|
|
||||||
|
|
||||||
// Expand to the left.
|
// Expand to the left.
|
||||||
while start > 0 && expand(&children[start]) {
|
while start > 0 && expand(&children[start]) {
|
||||||
@ -141,26 +149,48 @@ fn try_reparse(
|
|||||||
next_nesting(child, &mut prev_nesting_after);
|
next_nesting(child, &mut prev_nesting_after);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine the range in the new text that we want to reparse.
|
||||||
let shifted = offset + prefix_len;
|
let shifted = offset + prefix_len;
|
||||||
let new_len = prev_len + replacement_len - replaced.len();
|
let new_len = prev_len + replacement_len - replaced.len();
|
||||||
let new_range = shifted..shifted + new_len;
|
let new_range = shifted..shifted + new_len;
|
||||||
|
let at_end = end == children.len();
|
||||||
|
|
||||||
|
// Stop parsing early if this kind is encountered.
|
||||||
let stop_kind = match parent_kind {
|
let stop_kind = match parent_kind {
|
||||||
Some(_) => SyntaxKind::RightBracket,
|
Some(_) => SyntaxKind::RightBracket,
|
||||||
None => SyntaxKind::Eof,
|
None => SyntaxKind::Eof,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(newborns) =
|
// Reparse!
|
||||||
reparse_markup(text, new_range.clone(), &mut at_start, &mut nesting, |kind| {
|
let reparsed = reparse_markup(
|
||||||
kind == stop_kind
|
text,
|
||||||
})
|
new_range.clone(),
|
||||||
{
|
&mut at_start,
|
||||||
if at_start == prev_at_start_after && nesting == prev_nesting_after {
|
&mut nesting,
|
||||||
|
|kind| kind == stop_kind,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(newborns) = reparsed {
|
||||||
|
// If more children follow, at_start must match its previous value.
|
||||||
|
// Similarly, if we children follow or we not top-level the nesting
|
||||||
|
// must match its previous value.
|
||||||
|
if (at_end || at_start == prev_at_start_after)
|
||||||
|
&& ((at_end && parent_kind.is_none()) || nesting == prev_nesting_after)
|
||||||
|
{
|
||||||
return node
|
return node
|
||||||
.replace_children(start..end, newborns)
|
.replace_children(start..end, newborns)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
.then_some(new_range);
|
.then_some(new_range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If it didn't even work with all children, we give up.
|
||||||
|
if start == 0 && at_end {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exponential expansion to both sides.
|
||||||
|
expansion *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user