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