summaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/incremental.rs12
-rw-r--r--src/parse/mod.rs184
-rw-r--r--src/parse/parser.rs14
-rw-r--r--src/parse/tokens.rs16
4 files changed, 112 insertions, 114 deletions
diff --git a/src/parse/incremental.rs b/src/parse/incremental.rs
index 4736845f..759b3a68 100644
--- a/src/parse/incremental.rs
+++ b/src/parse/incremental.rs
@@ -136,8 +136,8 @@ impl Reparser<'_> {
let superseded_span = pos.offset .. pos.offset + prev_len;
let func: Option<ReparseMode> = match child.kind() {
- NodeKind::Template => Some(ReparseMode::Template),
- NodeKind::Block => Some(ReparseMode::Block),
+ NodeKind::CodeBlock => Some(ReparseMode::Code),
+ NodeKind::TemplateBlock => Some(ReparseMode::Template),
_ => None,
};
@@ -211,7 +211,7 @@ impl Reparser<'_> {
}
let (newborns, terminated, amount) = match mode {
- ReparseMode::Block => reparse_block(
+ ReparseMode::Code => reparse_block(
&prefix,
&self.src[newborn_span.start ..],
newborn_span.len(),
@@ -292,9 +292,9 @@ impl SearchState {
/// Which reparse function to choose for a span of elements.
#[derive(Clone, Copy, Debug, PartialEq)]
enum ReparseMode {
- /// Reparse a code block with its braces.
- Block,
- /// Reparse a template, including its square brackets.
+ /// Reparse a code block, including its braces.
+ Code,
+ /// Reparse a template block, including its square brackets.
Template,
/// Reparse elements of the markup. The variant carries whether the node is
/// `at_start` and the minimum indent of the containing markup node.
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index 11ce872f..833a5b33 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -28,8 +28,57 @@ pub fn parse(src: &str) -> Arc<GreenNode> {
}
}
-/// Parse some markup without the topmost node. Returns `Some` if all of the
-/// input was consumed.
+/// Reparse a code block.
+///
+/// Returns `Some` if all of the input was consumed.
+pub fn reparse_block(
+ prefix: &str,
+ src: &str,
+ end_pos: usize,
+) -> Option<(Vec<Green>, bool, usize)> {
+ let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
+ if !p.at(&NodeKind::LeftBrace) {
+ return None;
+ }
+
+ block(&mut p);
+
+ let (mut green, terminated) = p.consume()?;
+ let first = green.remove(0);
+ if first.len() != end_pos {
+ return None;
+ }
+
+ Some((vec![first], terminated, 1))
+}
+
+/// Reparse a template literal.
+///
+/// Returns `Some` if all of the input was consumed.
+pub fn reparse_template(
+ prefix: &str,
+ src: &str,
+ end_pos: usize,
+) -> Option<(Vec<Green>, bool, usize)> {
+ let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
+ if !p.at(&NodeKind::LeftBracket) {
+ return None;
+ }
+
+ template(&mut p);
+
+ let (mut green, terminated) = p.consume()?;
+ let first = green.remove(0);
+ if first.len() != end_pos {
+ return None;
+ }
+
+ Some((vec![first], terminated, 1))
+}
+
+/// Reparse some markup elements without the topmost node.
+///
+/// Returns `Some` if all of the input was consumed.
pub fn reparse_markup_elements(
prefix: &str,
src: &str,
@@ -100,50 +149,6 @@ pub fn reparse_markup_elements(
Some((res, terminated, replaced))
}
-/// Parse a template literal. Returns `Some` if all of the input was consumed.
-pub fn reparse_template(
- prefix: &str,
- src: &str,
- end_pos: usize,
-) -> Option<(Vec<Green>, bool, usize)> {
- let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
- if !p.at(&NodeKind::LeftBracket) {
- return None;
- }
-
- template(&mut p);
-
- let (mut green, terminated) = p.consume()?;
- let first = green.remove(0);
- if first.len() != end_pos {
- return None;
- }
-
- Some((vec![first], terminated, 1))
-}
-
-/// Parse a code block. Returns `Some` if all of the input was consumed.
-pub fn reparse_block(
- prefix: &str,
- src: &str,
- end_pos: usize,
-) -> Option<(Vec<Green>, bool, usize)> {
- let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
- if !p.at(&NodeKind::LeftBrace) {
- return None;
- }
-
- block(&mut p);
-
- let (mut green, terminated) = p.consume()?;
- let first = green.remove(0);
- if first.len() != end_pos {
- return None;
- }
-
- Some((vec![first], terminated, 1))
-}
-
/// Parse markup.
///
/// If `at_start` is true, things like headings that may only appear at the
@@ -201,9 +206,9 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) {
// Text and markup.
NodeKind::Text(_)
+ | NodeKind::NonBreakingSpace
| NodeKind::EnDash
| NodeKind::EmDash
- | NodeKind::NonBreakingSpace
| NodeKind::Linebreak
| NodeKind::Raw(_)
| NodeKind::Math(_)
@@ -350,7 +355,7 @@ fn expr_prec(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
p.eat();
let prec = op.precedence();
expr_prec(p, atomic, prec)?;
- marker.end(p, NodeKind::Unary);
+ marker.end(p, NodeKind::UnaryExpr);
}
_ => primary(p, atomic)?,
};
@@ -388,7 +393,7 @@ fn expr_prec(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
Associativity::Right => {}
}
- marker.perform(p, NodeKind::Binary, |p| expr_prec(p, atomic, prec))?;
+ marker.perform(p, NodeKind::BinaryExpr, |p| expr_prec(p, atomic, prec))?;
}
Ok(())
@@ -410,7 +415,7 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
if !atomic && p.at(&NodeKind::Arrow) {
marker.end(p, NodeKind::ClosureParams);
p.eat_assert(&NodeKind::Arrow);
- marker.perform(p, NodeKind::Closure, expr)
+ marker.perform(p, NodeKind::ClosureExpr, expr)
} else {
Ok(())
}
@@ -418,14 +423,8 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
// Structures.
Some(NodeKind::LeftParen) => parenthesized(p, atomic),
- Some(NodeKind::LeftBracket) => {
- template(p);
- Ok(())
- }
- Some(NodeKind::LeftBrace) => {
- block(p);
- Ok(())
- }
+ Some(NodeKind::LeftBrace) => Ok(block(p)),
+ Some(NodeKind::LeftBracket) => Ok(template(p)),
// Keywords.
Some(NodeKind::Let) => let_expr(p),
@@ -478,6 +477,20 @@ fn literal(p: &mut Parser) -> bool {
}
}
+/// Parse an identifier.
+fn ident(p: &mut Parser) -> ParseResult {
+ match p.peek() {
+ Some(NodeKind::Ident(_)) => {
+ p.eat();
+ Ok(())
+ }
+ _ => {
+ p.expected_found("identifier");
+ Err(ParseError)
+ }
+ }
+}
+
/// Parse something that starts with a parenthesis, which can be either of:
/// - Array literal
/// - Dictionary literal
@@ -501,12 +514,12 @@ fn parenthesized(p: &mut Parser, atomic: bool) -> ParseResult {
if !atomic && p.at(&NodeKind::Arrow) {
params(p, marker);
p.eat_assert(&NodeKind::Arrow);
- return marker.perform(p, NodeKind::Closure, expr);
+ return marker.perform(p, NodeKind::ClosureExpr, expr);
}
// Transform into the identified collection.
match kind {
- CollectionKind::Group => marker.end(p, NodeKind::Group),
+ CollectionKind::Group => marker.end(p, NodeKind::GroupExpr),
CollectionKind::Positional => array(p, marker),
CollectionKind::Named => dict(p, marker),
}
@@ -614,7 +627,7 @@ fn array(p: &mut Parser, marker: Marker) {
NodeKind::Spread => Err("spreading is not allowed here"),
_ => Ok(()),
});
- marker.end(p, NodeKind::Array);
+ marker.end(p, NodeKind::ArrayExpr);
}
/// Convert a collection into a dictionary, producing errors for anything other
@@ -626,7 +639,7 @@ fn dict(p: &mut Parser, marker: Marker) {
NodeKind::Spread => Err("spreading is not allowed here"),
_ => Err("expected named pair, found expression"),
});
- marker.end(p, NodeKind::Dict);
+ marker.end(p, NodeKind::DictExpr);
}
/// Convert a collection into a list of parameters, producing errors for
@@ -648,18 +661,9 @@ fn params(p: &mut Parser, marker: Marker) {
marker.end(p, NodeKind::ClosureParams);
}
-// Parse a template block: `[...]`.
-fn template(p: &mut Parser) {
- p.perform(NodeKind::Template, |p| {
- p.start_group(Group::Bracket);
- markup(p, true);
- p.end_group();
- });
-}
-
/// Parse a code block: `{...}`.
fn block(p: &mut Parser) {
- p.perform(NodeKind::Block, |p| {
+ p.perform(NodeKind::CodeBlock, |p| {
p.start_group(Group::Brace);
while !p.eof() {
p.start_group(Group::Expr);
@@ -675,9 +679,18 @@ fn block(p: &mut Parser) {
});
}
+// Parse a template block: `[...]`.
+fn template(p: &mut Parser) {
+ p.perform(NodeKind::TemplateBlock, |p| {
+ p.start_group(Group::Bracket);
+ markup(p, true);
+ p.end_group();
+ });
+}
+
/// Parse a function call.
fn call(p: &mut Parser, callee: Marker) -> ParseResult {
- callee.perform(p, NodeKind::Call, |p| args(p, true, true))
+ callee.perform(p, NodeKind::CallExpr, |p| args(p, true, true))
}
/// Parse the arguments to a function call.
@@ -744,7 +757,7 @@ fn let_expr(p: &mut Parser) -> ParseResult {
// Rewrite into a closure expression if it's a function definition.
if has_params {
- marker.end(p, NodeKind::Closure);
+ marker.end(p, NodeKind::ClosureExpr);
}
}
@@ -770,7 +783,7 @@ fn show_expr(p: &mut Parser) -> ParseResult {
p.expected_found("parameter list");
return Err(ParseError);
}
- p.perform(NodeKind::Closure, |p| {
+ p.perform(NodeKind::ClosureExpr, |p| {
let marker = p.marker();
p.start_group(Group::Paren);
collection(p);
@@ -906,31 +919,16 @@ fn return_expr(p: &mut Parser) -> ParseResult {
})
}
-/// Parse an identifier.
-fn ident(p: &mut Parser) -> ParseResult {
- match p.peek() {
- Some(NodeKind::Ident(_)) => {
- p.eat();
- Ok(())
- }
- _ => {
- p.expected_found("identifier");
- Err(ParseError)
- }
- }
-}
-
/// Parse a control flow body.
fn body(p: &mut Parser) -> ParseResult {
match p.peek() {
- Some(NodeKind::LeftBracket) => template(p),
- Some(NodeKind::LeftBrace) => block(p),
+ Some(NodeKind::LeftBracket) => Ok(template(p)),
+ Some(NodeKind::LeftBrace) => Ok(block(p)),
_ => {
p.expected("body");
- return Err(ParseError);
+ Err(ParseError)
}
}
- Ok(())
}
#[cfg(test)]
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 123871a5..33cf489c 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -229,13 +229,13 @@ impl<'s> Parser<'s> {
self.groups.push(GroupEntry { kind, prev_mode: self.tokens.mode() });
self.tokens.set_mode(match kind {
Group::Bracket | Group::Strong | Group::Emph => TokenMode::Markup,
- Group::Paren | Group::Brace | Group::Expr | Group::Imports => TokenMode::Code,
+ Group::Brace | Group::Paren | Group::Expr | Group::Imports => TokenMode::Code,
});
match kind {
- Group::Paren => self.eat_assert(&NodeKind::LeftParen),
- Group::Bracket => self.eat_assert(&NodeKind::LeftBracket),
Group::Brace => self.eat_assert(&NodeKind::LeftBrace),
+ Group::Bracket => self.eat_assert(&NodeKind::LeftBracket),
+ Group::Paren => self.eat_assert(&NodeKind::LeftParen),
Group::Strong => self.eat_assert(&NodeKind::Star),
Group::Emph => self.eat_assert(&NodeKind::Underscore),
Group::Expr => self.repeek(),
@@ -321,9 +321,9 @@ impl<'s> Parser<'s> {
/// group.
fn repeek(&mut self) {
self.eof = match &self.current {
- Some(NodeKind::RightParen) => self.inside(Group::Paren),
- Some(NodeKind::RightBracket) => self.inside(Group::Bracket),
Some(NodeKind::RightBrace) => self.inside(Group::Brace),
+ Some(NodeKind::RightBracket) => self.inside(Group::Bracket),
+ Some(NodeKind::RightParen) => self.inside(Group::Paren),
Some(NodeKind::Star) => self.inside(Group::Strong),
Some(NodeKind::Underscore) => self.inside(Group::Emph),
Some(NodeKind::Semicolon) => self.inside(Group::Expr),
@@ -482,10 +482,10 @@ struct GroupEntry {
/// A group, confined by optional start and end delimiters.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Group {
- /// A bracketed group: `[...]`.
- Bracket,
/// A curly-braced group: `{...}`.
Brace,
+ /// A bracketed group: `[...]`.
+ Bracket,
/// A parenthesized group: `(...)`.
Paren,
/// A group surrounded with stars: `*...*`.
diff --git a/src/parse/tokens.rs b/src/parse/tokens.rs
index 91bbf9e8..752714fd 100644
--- a/src/parse/tokens.rs
+++ b/src/parse/tokens.rs
@@ -26,7 +26,7 @@ pub struct Tokens<'s> {
pub enum TokenMode {
/// Text and markup.
Markup,
- /// Blocks and expressions.
+ /// Keywords, literals and operators.
Code,
}
@@ -104,11 +104,11 @@ impl<'s> Iterator for Tokens<'s> {
let start = self.s.index();
let c = self.s.eat()?;
Some(match c {
- // Blocks and templates.
- '[' => NodeKind::LeftBracket,
- ']' => NodeKind::RightBracket,
+ // Blocks.
'{' => NodeKind::LeftBrace,
'}' => NodeKind::RightBrace,
+ '[' => NodeKind::LeftBracket,
+ ']' => NodeKind::RightBracket,
// Whitespace.
' ' if self.s.check_or(true, |c| !c.is_whitespace()) => NodeKind::Space(0),
@@ -741,18 +741,18 @@ mod tests {
#[test]
fn test_tokenize_brackets() {
// Test in markup.
- t!(Markup: "[" => LeftBracket);
- t!(Markup: "]" => RightBracket);
t!(Markup: "{" => LeftBrace);
t!(Markup: "}" => RightBrace);
+ t!(Markup: "[" => LeftBracket);
+ t!(Markup: "]" => RightBracket);
t!(Markup[" /"]: "(" => Text("("));
t!(Markup[" /"]: ")" => Text(")"));
// Test in code.
- t!(Code: "[" => LeftBracket);
- t!(Code: "]" => RightBracket);
t!(Code: "{" => LeftBrace);
t!(Code: "}" => RightBrace);
+ t!(Code: "[" => LeftBracket);
+ t!(Code: "]" => RightBracket);
t!(Code: "(" => LeftParen);
t!(Code: ")" => RightParen);
}