Skip to content

Commit

Permalink
grammar: use inner expressions as appropriate
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Aug 15, 2024
1 parent e5df4b5 commit dac879c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 58 deletions.
2 changes: 1 addition & 1 deletion crates/rune/src/compile/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,7 @@ impl fmt::Display for ErrorKind {
}
#[cfg(feature = "fmt")]
ErrorKind::UnexpectedEndOfSyntax { inside } => {
write!(f, "Unexpected end of syntax while parsing {inside:?}")?;
write!(f, "Unexpected end of syntax while parsing {inside}")?;
}
#[cfg(feature = "fmt")]
ErrorKind::ExpectedSyntaxEnd { inside, actual } => {
Expand Down
65 changes: 33 additions & 32 deletions crates/rune/src/fmt/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ fn local<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<()> {
fmt.ws()?;
p.one(K![=])?.fmt(fmt)?;
fmt.ws()?;
p.pump()?.parse(|p| expr(fmt, p))?;
p.expect(Expr)?.parse(|p| expr(fmt, p))?;
Ok(())
}

Expand Down Expand Up @@ -553,25 +553,26 @@ fn expr_discard<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<()> {
}

fn expr<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<Kind> {
match p.kind() {
Expr => {
let mut attrs = Attrs::default();
let mut attrs = Attrs::default();

while let Some(attr) = p.try_pump(Attribute)? {
attrs.skip |= is_runefmt_skip(fmt, attr.clone());
attr.fmt(fmt)?;
fmt.ws()?;
}
while let Some(attr) = p.try_pump(Attribute)? {
attrs.skip |= is_runefmt_skip(fmt, attr.clone());
attr.fmt(fmt)?;
fmt.ws()?;
}

if attrs.skip {
p.write_remaining(fmt)?;
return Ok(Expr);
} else {
modifiers(fmt, p)?;
expr_labels(fmt, p)?;
return p.pump()?.parse(|p| expr(fmt, p));
}
}
if attrs.skip {
p.write_remaining(fmt)?;
Ok(Expr)
} else {
modifiers(fmt, p)?;
expr_labels(fmt, p)?;
p.pump()?.parse(|p| inner_expr(fmt, p))
}
}

fn inner_expr<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<Kind> {
match p.kind() {
ExprMacroCall => {
p.expect(Path)?.parse(|p| path(fmt, p))?;
p.expect(K![!])?.fmt(fmt)?;
Expand Down Expand Up @@ -663,17 +664,17 @@ fn expr<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<Kind> {
p.pump()?.fmt(fmt)?;
}
ExprRangeFrom => {
p.pump()?.parse(|p| expr(fmt, p))?;
p.pump()?.parse(|p| inner_expr(fmt, p))?;
p.pump()?.fmt(fmt)?;
}
ExprRangeTo | ExprRangeToInclusive => {
p.pump()?.fmt(fmt)?;
p.pump()?.parse(|p| expr(fmt, p))?;
p.pump()?.parse(|p| inner_expr(fmt, p))?;
}
ExprRange | ExprRangeInclusive => {
p.pump()?.parse(|p| expr(fmt, p))?;
p.pump()?.parse(|p| inner_expr(fmt, p))?;
p.pump()?.fmt(fmt)?;
p.pump()?.parse(|p| expr(fmt, p))?;
p.pump()?.parse(|p| inner_expr(fmt, p))?;
}
ExprClosure => {
expr_closure(fmt, p)?;
Expand All @@ -685,11 +686,11 @@ fn expr<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<Kind> {
if fmt.options.error_recovery {
p.fmt_remaining_trimmed(fmt)?;
} else {
return Err(p.unsupported("expression"));
return Err(p.unsupported("inner expression"));
}
}
_ => {
return Err(p.unsupported("expression"));
return Err(p.unsupported("inner expression"));
}
}

Expand Down Expand Up @@ -782,11 +783,11 @@ fn compact_expr_macro_call<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> R
}

fn expr_assign<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<()> {
p.pump()?.parse(|p| expr(fmt, p))?;
p.pump()?.parse(|p| inner_expr(fmt, p))?;
fmt.ws()?;
p.expect(K![=])?.fmt(fmt)?;
fmt.ws()?;
p.pump()?.parse(|p| expr(fmt, p))?;
p.expect(Expr)?.parse(|p| expr(fmt, p))?;
Ok(())
}

Expand Down Expand Up @@ -860,21 +861,21 @@ fn exprs_compact<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<()>
}

fn expr_binary<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<()> {
p.pump()?.parse(|p| expr(fmt, p))?;
p.pump()?.parse(|p| inner_expr(fmt, p))?;

while let Some(op) = p.try_pump(ExprOperator)? {
fmt.ws()?;
op.fmt(fmt)?;
fmt.ws()?;
p.pump()?.parse(|p| expr(fmt, p))?;
p.pump()?.parse(|p| inner_expr(fmt, p))?;
}

Ok(())
}

fn expr_unary<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<()> {
p.pump()?.fmt(fmt)?;
p.pump()?.parse(|p| expr(fmt, p))?;
p.pump()?.parse(|p| inner_expr(fmt, p))?;
Ok(())
}

Expand Down Expand Up @@ -1162,7 +1163,7 @@ fn expr_chain<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<()> {
// that need indentation in the chain, we can keep it all on one line.
let head = p.pump()?.parse(|p| {
let first = p.span();
expr(fmt, p)?;
inner_expr(fmt, p)?;
Ok(first)
})?;

Expand Down Expand Up @@ -1264,7 +1265,7 @@ fn condition_or_expr<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<
if let Some(c) = p.try_pump(Condition)? {
c.parse(|p| condition(fmt, p))?;
} else {
p.pump()?.parse(|p| expr(fmt, p))?;
p.expect(Expr)?.parse(|p| expr(fmt, p))?;
}

Ok(())
Expand All @@ -1277,7 +1278,7 @@ fn condition<'a>(fmt: &mut Formatter<'a>, p: &mut Stream<'a>) -> Result<()> {
fmt.ws()?;
p.expect(K![=])?.fmt(fmt)?;
fmt.ws()?;
p.pump()?.parse(|p| expr(fmt, p))?;
p.expect(Expr)?.parse(|p| expr(fmt, p))?;
Ok(())
}

Expand Down
11 changes: 9 additions & 2 deletions crates/rune/src/fmt/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,8 @@ fn patterns() {
"let ::a::b::c = ::a::b::c;"
);
assert_format!(
"let ::a ::b<::b, ::c ::d>::c = 42;",
"let ::a::b<::b, ::c::d>::c = 42;"
"let ::a ::b::<::b, ::c ::d>::c = 42;",
"let ::a::b::<::b, ::c::d>::c = 42;"
);
assert_format!(
"for _ in 121/10..=1*2-100{}",
Expand Down Expand Up @@ -585,6 +585,13 @@ fn expressions() {
};
"#
);

assert_format!(
r#"
if values - current_joltage < 4 {
}
"#
);
}

#[test]
Expand Down
40 changes: 17 additions & 23 deletions crates/rune/src/grammar/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ fn modifiers(p: &mut Parser<'_>) -> Result<Modifiers> {
}
K![in] => {
p.bump()?;
path(p, Binary::No)?;
path(p)?;
ModifierIn
}
_ => Error,
Expand Down Expand Up @@ -469,7 +469,7 @@ fn item_impl(p: &mut Parser<'_>) -> Result<()> {
p.bump()?;

if matches!(p.peek()?, path_component!()) {
path(p, Binary::No)?;
path(p)?;
}

block(p)?;
Expand Down Expand Up @@ -530,7 +530,7 @@ fn pat(p: &mut Parser<'_>) -> Result<()> {
}
path_component!() => {
let c = p.checkpoint()?;
path(p, Binary::No)?;
path(p)?;

match p.peek()? {
K!['{'] => {
Expand Down Expand Up @@ -657,13 +657,13 @@ fn outer_expr_with(
cx: &dyn ExprCx,
) -> Result<Kind> {
let c = p.checkpoint()?;
let mut kind = expr_primary(p, brace, range, binary, cx)?;
let mut kind = expr_primary(p, brace, range, cx)?;

if is_range(kind) {
return Ok(kind);
}

kind = expr_chain(p, &c, binary, kind)?;
kind = expr_chain(p, &c, kind)?;

if p.peek()? == K![=] {
p.bump()?;
Expand Down Expand Up @@ -700,13 +700,7 @@ fn labels(p: &mut Parser<'_>) -> Result<()> {
}

#[tracing::instrument(skip_all)]
fn expr_primary(
p: &mut Parser<'_>,
brace: Brace,
range: Range,
binary: Binary,
cx: &dyn ExprCx,
) -> Result<Kind> {
fn expr_primary(p: &mut Parser<'_>, brace: Brace, range: Range, cx: &dyn ExprCx) -> Result<Kind> {
let c = p.checkpoint()?;

let kind = match p.peek()? {
Expand All @@ -715,7 +709,7 @@ fn expr_primary(
ExprLit
}
path_component!() => {
path(p, binary)?;
path(p)?;

match p.peek()? {
K!['{'] if matches!(brace, Brace::Yes) => {
Expand Down Expand Up @@ -767,7 +761,7 @@ fn expr_primary(
}
K![!] | K![-] | K![&] | K![*] => {
p.bump()?;
expr_with(p, brace, range, Binary::No, cx)?;
outer_expr_with(p, brace, range, Binary::No, cx)?;
ExprUnary
}
K![if] => {
Expand Down Expand Up @@ -878,7 +872,7 @@ fn kind_is_callable(kind: Kind) -> bool {
}

#[tracing::instrument(skip_all)]
fn expr_chain(p: &mut Parser<'_>, c: &Checkpoint, binary: Binary, mut kind: Kind) -> Result<Kind> {
fn expr_chain(p: &mut Parser<'_>, c: &Checkpoint, mut kind: Kind) -> Result<Kind> {
let mut before = p.checkpoint()?;
let mut has_chain = false;

Expand Down Expand Up @@ -912,7 +906,7 @@ fn expr_chain(p: &mut Parser<'_>, c: &Checkpoint, binary: Binary, mut kind: Kind
}
// <expr>.field
path_component!() => {
path(p, binary)?;
path(p)?;
ExprField
}
// <expr>.<number>
Expand Down Expand Up @@ -1151,14 +1145,14 @@ fn condition(p: &mut Parser<'_>) -> Result<()> {
}

#[tracing::instrument(skip_all)]
fn path(p: &mut Parser<'_>, binary: Binary) -> Result<()> {
fn path(p: &mut Parser<'_>) -> Result<()> {
let c = p.checkpoint()?;

while matches!(p.peek()?, path_component!()) {
// Parse a generic path if we are not in a binary expression, or if we
// just parsed the prefix `::` of the turbofish syntax.
let has_generics = matches!(binary, Binary::No) || matches!(p.peek()?, K![::]);

// Parse a generic path if we are in a context supporting binary
// expressions, or if we just parsed the prefix `::` of the turbofish
// syntax.
let has_generics = matches!(p.peek()?, K![::]);
p.bump()?;

// We can't parse generics in binary expressions, since they would be
Expand All @@ -1169,7 +1163,7 @@ fn path(p: &mut Parser<'_>, binary: Binary) -> Result<()> {

while matches!(p.peek()?, path_component!()) {
// Inner paths are unambiguous.
path(p, Binary::No)?;
path(p)?;
p.bump_while(K![,])?;
}

Expand Down Expand Up @@ -1208,8 +1202,8 @@ fn expr_binary(
p.close_at(&op_c, ExprOperator)?;

let c = p.checkpoint()?;
outer_expr_with(p, brace, Range::No, Binary::No, cx)?;

expr_with(p, brace, Range::No, Binary::No, cx)?;
has_any = true;

lookahead = ast::BinOp::from_peeker(p)?;
Expand Down

0 comments on commit dac879c

Please sign in to comment.