mirror of
https://github.com/nushell/nushell.git
synced 2025-05-01 08:34:26 +02:00
The original purpose of this PR was to modernize the external parser to
use the new Shape system.
This commit does include some of that change, but a more important
aspect of this change is an improvement to the expansion trace.
Previous commit 6a7c00ea
adding trace infrastructure to the syntax coloring
feature. This commit adds tracing to the expander.
The bulk of that work, in addition to the tree builder logic, was an
overhaul of the formatter traits to make them more general purpose, and
more structured.
Some highlights:
- `ToDebug` was split into two traits (`ToDebug` and `DebugFormat`)
because implementations needed to become objects, but a convenience
method on `ToDebug` didn't qualify
- `DebugFormat`'s `fmt_debug` method now takes a `DebugFormatter` rather
than a standard formatter, and `DebugFormatter` has a new (but still
limited) facility for structured formatting.
- Implementations of `ExpandSyntax` need to produce output that
implements `DebugFormat`.
Unlike the highlighter changes, these changes are fairly focused in the
trace output, so these changes aren't behind a flag.
215 lines
6.5 KiB
Rust
215 lines
6.5 KiB
Rust
use crate::parser::hir::syntax_shape::{
|
|
expand_atom, parse_single_node, ExpandContext, ExpandExpression, ExpansionRule,
|
|
FallibleColorSyntax, FlatShape, ParseError,
|
|
};
|
|
use crate::parser::{
|
|
hir,
|
|
hir::{RawNumber, TokensIterator},
|
|
RawToken,
|
|
};
|
|
use crate::prelude::*;
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
pub struct NumberShape;
|
|
|
|
impl ExpandExpression for NumberShape {
|
|
fn name(&self) -> &'static str {
|
|
"number"
|
|
}
|
|
|
|
fn expand_expr<'a, 'b>(
|
|
&self,
|
|
token_nodes: &mut TokensIterator<'_>,
|
|
context: &ExpandContext,
|
|
) -> Result<hir::Expression, ParseError> {
|
|
parse_single_node(token_nodes, "Number", |token, token_span, err| {
|
|
Ok(match token {
|
|
RawToken::GlobPattern | RawToken::Operator(..) => return Err(err.error()),
|
|
RawToken::Variable(tag) if tag.slice(context.source) == "it" => {
|
|
hir::Expression::it_variable(tag, token_span)
|
|
}
|
|
RawToken::ExternalCommand(tag) => {
|
|
hir::Expression::external_command(tag, token_span)
|
|
}
|
|
RawToken::ExternalWord => {
|
|
return Err(ParseError::mismatch(
|
|
"number",
|
|
"syntax error".tagged(Tag {
|
|
span: token_span,
|
|
anchor: None,
|
|
}),
|
|
))
|
|
}
|
|
RawToken::Variable(tag) => hir::Expression::variable(tag, token_span),
|
|
RawToken::Number(number) => {
|
|
hir::Expression::number(number.to_number(context.source), token_span)
|
|
}
|
|
RawToken::Bare => hir::Expression::bare(token_span),
|
|
RawToken::String(tag) => hir::Expression::string(tag, token_span),
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg(not(coloring_in_tokens))]
|
|
impl FallibleColorSyntax for NumberShape {
|
|
type Info = ();
|
|
type Input = ();
|
|
|
|
fn color_syntax<'a, 'b>(
|
|
&self,
|
|
_input: &(),
|
|
token_nodes: &'b mut TokensIterator<'a>,
|
|
context: &ExpandContext,
|
|
shapes: &mut Vec<Spanned<FlatShape>>,
|
|
) -> Result<(), ShellError> {
|
|
let atom = token_nodes.spanned(|token_nodes| {
|
|
expand_atom(token_nodes, "number", context, ExpansionRule::permissive())
|
|
});
|
|
|
|
let atom = match atom {
|
|
Spanned { item: Err(_), span } => {
|
|
shapes.push(FlatShape::Error.spanned(span));
|
|
return Ok(());
|
|
}
|
|
Spanned { item: Ok(atom), .. } => atom,
|
|
};
|
|
|
|
atom.color_tokens(shapes);
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(coloring_in_tokens)]
|
|
impl FallibleColorSyntax for NumberShape {
|
|
type Info = ();
|
|
type Input = ();
|
|
|
|
fn name(&self) -> &'static str {
|
|
"NumberShape"
|
|
}
|
|
|
|
fn color_syntax<'a, 'b>(
|
|
&self,
|
|
_input: &(),
|
|
token_nodes: &'b mut TokensIterator<'a>,
|
|
context: &ExpandContext,
|
|
) -> Result<(), ShellError> {
|
|
let atom = token_nodes.spanned(|token_nodes| {
|
|
expand_atom(token_nodes, "number", context, ExpansionRule::permissive())
|
|
});
|
|
|
|
let atom = match atom {
|
|
Spanned { item: Err(_), span } => {
|
|
token_nodes.color_shape(FlatShape::Error.spanned(span));
|
|
return Ok(());
|
|
}
|
|
Spanned { item: Ok(atom), .. } => atom,
|
|
};
|
|
|
|
token_nodes.mutate_shapes(|shapes| atom.color_tokens(shapes));
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
pub struct IntShape;
|
|
|
|
impl ExpandExpression for IntShape {
|
|
fn name(&self) -> &'static str {
|
|
"integer"
|
|
}
|
|
|
|
fn expand_expr<'a, 'b>(
|
|
&self,
|
|
token_nodes: &mut TokensIterator<'_>,
|
|
context: &ExpandContext,
|
|
) -> Result<hir::Expression, ParseError> {
|
|
parse_single_node(token_nodes, "Integer", |token, token_span, err| {
|
|
Ok(match token {
|
|
RawToken::GlobPattern | RawToken::Operator(..) | RawToken::ExternalWord => {
|
|
return Err(err.error())
|
|
}
|
|
RawToken::Variable(span) if span.slice(context.source) == "it" => {
|
|
hir::Expression::it_variable(span, token_span)
|
|
}
|
|
RawToken::ExternalCommand(span) => {
|
|
hir::Expression::external_command(span, token_span)
|
|
}
|
|
RawToken::Variable(span) => hir::Expression::variable(span, token_span),
|
|
RawToken::Number(number @ RawNumber::Int(_)) => {
|
|
hir::Expression::number(number.to_number(context.source), token_span)
|
|
}
|
|
RawToken::Number(_) => return Err(err.error()),
|
|
RawToken::Bare => hir::Expression::bare(token_span),
|
|
RawToken::String(span) => hir::Expression::string(span, token_span),
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg(not(coloring_in_tokens))]
|
|
impl FallibleColorSyntax for IntShape {
|
|
type Info = ();
|
|
type Input = ();
|
|
|
|
fn color_syntax<'a, 'b>(
|
|
&self,
|
|
_input: &(),
|
|
token_nodes: &'b mut TokensIterator<'a>,
|
|
context: &ExpandContext,
|
|
shapes: &mut Vec<Spanned<FlatShape>>,
|
|
) -> Result<(), ShellError> {
|
|
let atom = token_nodes.spanned(|token_nodes| {
|
|
expand_atom(token_nodes, "integer", context, ExpansionRule::permissive())
|
|
});
|
|
|
|
let atom = match atom {
|
|
Spanned { item: Err(_), span } => {
|
|
shapes.push(FlatShape::Error.spanned(span));
|
|
return Ok(());
|
|
}
|
|
Spanned { item: Ok(atom), .. } => atom,
|
|
};
|
|
|
|
atom.color_tokens(shapes);
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(coloring_in_tokens)]
|
|
impl FallibleColorSyntax for IntShape {
|
|
type Info = ();
|
|
type Input = ();
|
|
|
|
fn name(&self) -> &'static str {
|
|
"IntShape"
|
|
}
|
|
|
|
fn color_syntax<'a, 'b>(
|
|
&self,
|
|
_input: &(),
|
|
token_nodes: &'b mut TokensIterator<'a>,
|
|
context: &ExpandContext,
|
|
) -> Result<(), ShellError> {
|
|
let atom = token_nodes.spanned(|token_nodes| {
|
|
expand_atom(token_nodes, "integer", context, ExpansionRule::permissive())
|
|
});
|
|
|
|
let atom = match atom {
|
|
Spanned { item: Err(_), span } => {
|
|
token_nodes.color_shape(FlatShape::Error.spanned(span));
|
|
return Ok(());
|
|
}
|
|
Spanned { item: Ok(atom), .. } => atom,
|
|
};
|
|
|
|
token_nodes.mutate_shapes(|shapes| atom.color_tokens(shapes));
|
|
|
|
Ok(())
|
|
}
|
|
}
|