aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/lib.rs')
-rw-r--r--crates/ra_parser/src/lib.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs
new file mode 100644
index 000000000..ddc08e462
--- /dev/null
+++ b/crates/ra_parser/src/lib.rs
@@ -0,0 +1,88 @@
1//! The Rust parser.
2//!
3//! The parser doesn't know about concrete representation of tokens and syntax
4//! trees. Abstract `TokenSource` and `TreeSink` traits are used instead. As a
5//! consequence, this crates does not contain a lexer.
6//!
7//! The `Parser` struct from the `parser` module is a cursor into the sequence
8//! of tokens. Parsing routines use `Parser` to inspect current state and
9//! advance the parsing.
10//!
11//! The actual parsing happens in the `grammar` module.
12//!
13//! Tests for this crate live in `ra_syntax` crate.
14
15#[macro_use]
16mod token_set;
17mod syntax_kind;
18mod event;
19mod parser;
20mod grammar;
21
22pub(crate) use token_set::TokenSet;
23
24pub use syntax_kind::SyntaxKind;
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash)]
27pub struct ParseError(pub String);
28
29/// `TokenSource` abstracts the source of the tokens parser operates one.
30///
31/// Hopefully this will allow us to treat text and token trees in the same way!
32pub trait TokenSource {
33 /// What is the current token?
34 fn token_kind(&self, pos: usize) -> SyntaxKind;
35 /// Is the current token joined to the next one (`> >` vs `>>`).
36 fn is_token_joint_to_next(&self, pos: usize) -> bool;
37 /// Is the current token a specified keyword?
38 fn is_keyword(&self, pos: usize, kw: &str) -> bool;
39}
40
41/// `TreeSink` abstracts details of a particular syntax tree implementation.
42pub trait TreeSink {
43 /// Adds new leaf to the current branch.
44 fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8);
45
46 /// Start new branch and make it current.
47 fn start_branch(&mut self, kind: SyntaxKind);
48
49 /// Finish current branch and restore previous
50 /// branch as current.
51 fn finish_branch(&mut self);
52
53 fn error(&mut self, error: ParseError);
54}
55
56/// Parse given tokens into the given sink as a rust file.
57pub fn parse(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) {
58 let mut p = parser::Parser::new(token_source);
59 grammar::root(&mut p);
60 let events = p.finish();
61 event::process(tree_sink, events);
62}
63
64/// A parsing function for a specific braced-block.
65pub struct Reparser(fn(&mut parser::Parser));
66
67impl Reparser {
68 /// If the node is a braced block, return the corresponding `Reparser`.
69 pub fn for_node(
70 node: SyntaxKind,
71 first_child: Option<SyntaxKind>,
72 parent: Option<SyntaxKind>,
73 ) -> Option<Reparser> {
74 grammar::reparser(node, first_child, parent).map(Reparser)
75 }
76
77 /// Re-parse given tokens using this `Reparser`.
78 ///
79 /// Tokens must start with `{`, end with `}` and form a valid brace
80 /// sequence.
81 pub fn parse(self, token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) {
82 let Reparser(r) = self;
83 let mut p = parser::Parser::new(token_source);
84 r(&mut p);
85 let events = p.finish();
86 event::process(tree_sink, events);
87 }
88}