Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,22 @@ The centerpiece of this whole endeavor is the syntax tree, in the

The syntax tree is produced using a three-staged process.

First, a raw text is split into tokens with a lexer. Lexer has a
peculiar signature: it is an `Fn(&str) -> Token`, where token is a
pair of `SyntaxKind` (you should have read the `tree` module and RFC
First, a raw text is split into tokens with a lexer (the `lexer` module).
Lexer has a peculiar signature: it is an `Fn(&str) -> Token`, where token
is a pair of `SyntaxKind` (you should have read the `tree` module and RFC
by this time! :)) and a len. That is, lexer chomps only the first
token of the input. This forces the lexer to be stateless, and makes
it possible to implement incremental relexing easily.

Then, the bulk of work, the parser turns a stream of tokens into
stream of events. Not that parser **does not** construct a tree right
away. This is done for several reasons:
stream of events (the `parser` module; of particular interest are
the `parser/event` and `parser/parser` modules, which contain parsing
API, and the `parser/grammar` module, which contains actual parsing code
for various Rust syntactic constructs). Not that parser **does not**
construct a tree right away. This is done for several reasons:

* to decouple the actual tree data structure from the parser: you can
build any datastructre you want from the stream of events
build any data structure you want from the stream of events

* to make parsing fast: you can produce a list of events without
allocations
Expand Down Expand Up @@ -77,12 +80,6 @@ And at last, the TreeBuilder converts a flat stream of events into a
tree structure. It also *should* be responsible for attaching comments
and rebalancing the tree, but it does not do this yet :)


## Error reporing

TODO: describe how stuff like `skip_to_first` works


## Validator

Parser and lexer accept a lot of *invalid* code intentionally. The
Expand Down
8 changes: 3 additions & 5 deletions src/parser/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub(crate) enum Event {
/// |
/// 'foo'
///
/// See also `CompleteMarker::precede`.
/// See also `CompletedMarker::precede`.
Start {
kind: SyntaxKind,
forward_parent: Option<u32>,
Expand All @@ -61,7 +61,7 @@ pub(crate) enum Event {
},

Error {
message: String,
msg: String,
},
}

Expand Down Expand Up @@ -140,9 +140,7 @@ pub(super) fn to_file(text: String, tokens: &[Token], events: Vec<Event>) -> Fil
}
builder.leaf(kind, len);
}
&Event::Error { ref message } => builder.error(ErrorMsg {
message: message.clone(),
}),
&Event::Error { ref msg } => builder.error(ErrorMsg { msg: msg.clone() }),
}
}
builder.finish()
Expand Down
4 changes: 2 additions & 2 deletions src/parser/grammar/items/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn item(p: &mut Parser) {

// test unsafe_auto_trait
// unsafe auto trait T {}
IDENT if p.at_kw("auto") && la == TRAIT_KW => {
IDENT if p.at_contextual_kw("auto") && la == TRAIT_KW => {
p.bump_remap(AUTO_KW);
traits::trait_item(p);
TRAIT_ITEM
Expand All @@ -109,7 +109,7 @@ fn item(p: &mut Parser) {

// test unsafe_default_impl
// unsafe default impl Foo {}
IDENT if p.at_kw("default") && la == IMPL_KW => {
IDENT if p.at_contextual_kw("default") && la == IMPL_KW => {
p.bump_remap(DEFAULT_KW);
traits::impl_item(p);
IMPL_ITEM
Expand Down
26 changes: 25 additions & 1 deletion src/parser/grammar/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
use super::parser::{Parser, TokenSet};
//! This is the actual "grammar" of the Rust language.
//!
//! Each function in this module and its children corresponds
//! to a production of the format grammar. Submodules roughly
//! correspond to different *areas* of the grammar. By convention,
//! each submodule starts with `use super::*` import and exports
//! "public" productions via `pub(super)`.
//!
//! See docs for `Parser` to learn about API, available to the grammar,
//! and see docs for `Event` to learn how this actually manages to
//! produce parse trees.
//!
//! Code in this module also contains inline tests, which start with
//! `// test name-of-the-test` comment and look like this:
//!
//! ```
//! // test fn_item_with_zero_parameters
//! // fn foo() {}
//! ```
//!
//! After adding a new inline-test, run `cargo collect-tests` to extract
//! it as a standalone text-fixture into `tests/data/parser/inline`, and
//! run `cargo test` once to create the "gold" value.
use parser::parser::Parser;
use parser::token_set::TokenSet;
use SyntaxKind;
use syntax_kinds::*;

Expand Down
37 changes: 4 additions & 33 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ use {File, SyntaxKind, Token};
use syntax_kinds::*;

#[macro_use]
mod token_set;
mod parser;
mod input;
mod event;
mod grammar;
use self::event::Event;

/// Parse a sequence of tokens into the representative node tree
pub fn parse(text: String, tokens: &[Token]) -> File {
let events = {
let input = input::ParserInput::new(&text, tokens);
let mut parser = parser::Parser::new(&input);
let parser_impl = parser::imp::ParserImpl::new(&input);
let mut parser = parser::Parser(parser_impl);
grammar::file(&mut parser);
parser.into_events()
parser.0.into_events()
};
event::to_file(text, tokens, events)
}
Expand All @@ -26,33 +27,3 @@ fn is_insignificant(kind: SyntaxKind) -> bool {
_ => false,
}
}

impl<'p> parser::Parser<'p> {
fn at(&self, kind: SyntaxKind) -> bool {
self.current() == kind
}

fn err_and_bump(&mut self, message: &str) {
let err = self.start();
self.error(message);
self.bump();
err.complete(self, ERROR);
}

fn expect(&mut self, kind: SyntaxKind) -> bool {
if self.at(kind) {
self.bump();
true
} else {
self.error(format!("expected {:?}", kind));
false
}
}

fn eat(&mut self, kind: SyntaxKind) -> bool {
self.at(kind) && {
self.bump();
true
}
}
}
193 changes: 0 additions & 193 deletions src/parser/parser.rs

This file was deleted.

Loading