Lower `RepeatRange` to railroads more elaborately

For `RepeatRange(e, a, b)`, we were rendering `e` on the main line
then rendering under it a message about how many times it may or must
repeat based on `a` and `b`.

The trouble is that if we say that something "repeats once" on the
recurrent edge -- after we've already consumed a thing -- that reads
reasonably as though we're saying that two things can be consumed when
that's not what we mean.

Similarly, it's a bit odd to say, on the recurrent edge, that
something must "repeat twice" when that edge (and presumably then that
rule) may not be taken at all.

Let's solve all this by doing the following:

- For `e{1..1}`, simply render the node.
- For `e{0..1}`, treat this as simply `e?`.
- For `e{0..}`, treat this as simply `e*`.
- For `e{1..}`, treat this as simply `e+`.
- For `e{a..0}`, render an empty node.
- For `e{0..b} b > 1`, treat this as `(e{1..b})?`.
- For `e{1..b} b > 1`, render the node on the main line, then on the
  recurrent line render "at most {b - 1} more times".
- For `e{a..b} a > 1`, make a sequence of length `a` where the final
  node repeats `{1..b - (a - 1)}` times (or `{1..}` times if `b` is
  unbounded).

(We'll also add a check in parsing to ensure that for the range to be
well formed `a <= b`.)

As it turns out, the most straightforward way to implement this isn't
by recursing.  Doing that means we end up needing to take special care
to handle the suffix and the footnote, we have to build up an extra
`Expression` we don't need, and we have to `unwrap` the call.
Instead, it works better to treat this lowering in the manner of a
transitioning state machine in the spirit of `loop match` as proposed
in RFC 3720.
3 files changed
tree: 28fae9eac9b57bdb46e239a23a9f74c189a2db42
  1. .cargo/
  2. .github/
  3. docs/
  4. mdbook-spec/
  5. src/
  6. style-check/
  7. theme/
  8. xtask/
  9. .gitattributes
  10. .gitignore
  11. book.toml
  12. CONTRIBUTING.md
  13. LICENSE-APACHE
  14. LICENSE-MIT
  15. README.md
  16. reference.md
  17. rust-toolchain.toml
  18. rustfmt.toml
  19. STYLE.md
  20. triagebot.toml
README.md

The Rust Language Reference

This document is the primary reference for the Rust programming language.

This document is not normative. It may include details that are specific to rustc itself, and should not be taken as a specification for the Rust language. We intend to produce such a document someday, but this is what we have for now.

Dependencies

Installing dependencies

First, ensure that you have a recent copy of the nightly Rust compiler installed, as this is needed in order to run the tests:

rustup toolchain install nightly

Now, ensure you have mdbook installed, as this is needed in order to build the Reference:

cargo install --locked mdbook

Building

To build the Reference, first clone the project:

git clone https://github.com/rust-lang/reference.git

(Alternatively, if you don't want to use git, download a ZIP file of the project, extract it using your preferred tool, and rename the top-level directory to reference.)

Now change your current directory to the working directory:

cd reference

To test all of the code examples in the Reference, run:

mdbook test

For authors, consider using the server functionality which supports automatic reload.

To build the Reference locally (in build/) and open it in a web browser, run:

SPEC_RELATIVE=0 mdbook build --open

This will open a browser with a websocket live-link to automatically reload whenever the source is updated.

You can also use mdbook's live webserver option, which will automatically rebuild the book and reload your web browser whenever a source file is modified:

SPEC_RELATIVE=0 mdbook serve --open

SPEC_RELATIVE

The SPEC_RELATIVE=0 environment variable makes links to the standard library go to https://doc.rust-lang.org/ instead of being relative, which is useful when viewing locally since you normally don't have a copy of the standard library.

The published site at https://doc.rust-lang.org/reference/ (or local docs using rustup doc) does not set this, which means it will use relative links which supports offline viewing and links to the correct version (for example, links in https://doc.rust-lang.org/1.81.0/reference/ will stay within the 1.81.0 directory).

SPEC_DENY_WARNINGS

The SPEC_DENY_WARNINGS=1 environment variable will turn all warnings generated by mdbook-spec to errors. This is used in CI to ensure that there aren't any problems with the book content.

SPEC_RUST_ROOT

The SPEC_RUST_ROOT can be used to point to the directory of a checkout of https://github.com/rust-lang/rust. This is used by the test-linking feature so that it can find tests linked to reference rules. If this is not set, then the tests won't be linked.