1 //! The Rust parser.
2 //!
3 //! NOTE: The crate is undergoing refactors, don't believe everything the docs
4 //! say :-)
5 //!
6 //! The parser doesn't know about concrete representation of tokens and syntax
7 //! trees. Abstract [`TokenSource`] and [`TreeSink`] traits are used instead. As
8 //! a consequence, this crate does not contain a lexer.
9 //!
10 //! The [`Parser`] struct from the [`parser`] module is a cursor into the
11 //! sequence of tokens. Parsing routines use [`Parser`] to inspect current
12 //! state and advance the parsing.
13 //!
14 //! The actual parsing happens in the [`grammar`] module.
15 //!
16 //! Tests for this crate live in the `syntax` crate.
17 //!
18 //! [`Parser`]: crate::parser::Parser
19 #![allow(rustdoc::private_intra_doc_links)]
20
21 mod lexed_str;
22 mod token_set;
23 mod syntax_kind;
24 mod event;
25 mod parser;
26 mod grammar;
27 mod tokens;
28
29 #[cfg(test)]
30 mod tests;
31
32 pub(crate) use token_set::TokenSet;
33
34 pub use crate::{lexed_str::LexedStr, syntax_kind::SyntaxKind, tokens::Tokens};
35
36 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
37 pub struct ParseError(pub Box<String>);
38
39 /// `TreeSink` abstracts details of a particular syntax tree implementation.
40 pub trait TreeSink {
41 /// Adds new token to the current branch.
token(&mut self, kind: SyntaxKind, n_tokens: u8)42 fn token(&mut self, kind: SyntaxKind, n_tokens: u8);
43
44 /// Start new branch and make it current.
start_node(&mut self, kind: SyntaxKind)45 fn start_node(&mut self, kind: SyntaxKind);
46
47 /// Finish current branch and restore previous
48 /// branch as current.
finish_node(&mut self)49 fn finish_node(&mut self);
50
error(&mut self, error: ParseError)51 fn error(&mut self, error: ParseError);
52 }
53
54 /// rust-analyzer parser allows you to choose one of the possible entry points.
55 ///
56 /// The primary consumer of this API are declarative macros, `$x:expr` matchers
57 /// are implemented by calling into the parser with non-standard entry point.
58 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
59 pub enum ParserEntryPoint {
60 SourceFile,
61 Path,
62 Expr,
63 Statement,
64 StatementOptionalSemi,
65 Type,
66 Pattern,
67 Item,
68 Block,
69 Visibility,
70 MetaItem,
71 Items,
72 Statements,
73 Attr,
74 }
75
76 /// Parse given tokens into the given sink as a rust file.
parse_source_file(tokens: &Tokens, tree_sink: &mut dyn TreeSink)77 pub fn parse_source_file(tokens: &Tokens, tree_sink: &mut dyn TreeSink) {
78 parse(tokens, tree_sink, ParserEntryPoint::SourceFile);
79 }
80
parse(tokens: &Tokens, tree_sink: &mut dyn TreeSink, entry_point: ParserEntryPoint)81 pub fn parse(tokens: &Tokens, tree_sink: &mut dyn TreeSink, entry_point: ParserEntryPoint) {
82 let entry_point: fn(&'_ mut parser::Parser) = match entry_point {
83 ParserEntryPoint::SourceFile => grammar::entry_points::source_file,
84 ParserEntryPoint::Path => grammar::entry_points::path,
85 ParserEntryPoint::Expr => grammar::entry_points::expr,
86 ParserEntryPoint::Type => grammar::entry_points::type_,
87 ParserEntryPoint::Pattern => grammar::entry_points::pattern,
88 ParserEntryPoint::Item => grammar::entry_points::item,
89 ParserEntryPoint::Block => grammar::entry_points::block_expr,
90 ParserEntryPoint::Visibility => grammar::entry_points::visibility,
91 ParserEntryPoint::MetaItem => grammar::entry_points::meta_item,
92 ParserEntryPoint::Statement => grammar::entry_points::stmt,
93 ParserEntryPoint::StatementOptionalSemi => grammar::entry_points::stmt_optional_semi,
94 ParserEntryPoint::Items => grammar::entry_points::macro_items,
95 ParserEntryPoint::Statements => grammar::entry_points::macro_stmts,
96 ParserEntryPoint::Attr => grammar::entry_points::attr,
97 };
98
99 let mut p = parser::Parser::new(tokens);
100 entry_point(&mut p);
101 let events = p.finish();
102 event::process(tree_sink, events);
103 }
104
105 /// A parsing function for a specific braced-block.
106 pub struct Reparser(fn(&mut parser::Parser));
107
108 impl Reparser {
109 /// If the node is a braced block, return the corresponding `Reparser`.
for_node( node: SyntaxKind, first_child: Option<SyntaxKind>, parent: Option<SyntaxKind>, ) -> Option<Reparser>110 pub fn for_node(
111 node: SyntaxKind,
112 first_child: Option<SyntaxKind>,
113 parent: Option<SyntaxKind>,
114 ) -> Option<Reparser> {
115 grammar::reparser(node, first_child, parent).map(Reparser)
116 }
117
118 /// Re-parse given tokens using this `Reparser`.
119 ///
120 /// Tokens must start with `{`, end with `}` and form a valid brace
121 /// sequence.
parse(self, tokens: &Tokens, tree_sink: &mut dyn TreeSink)122 pub fn parse(self, tokens: &Tokens, tree_sink: &mut dyn TreeSink) {
123 let Reparser(r) = self;
124 let mut p = parser::Parser::new(tokens);
125 r(&mut p);
126 let events = p.finish();
127 event::process(tree_sink, events);
128 }
129 }
130