1#![allow(rustdoc::private_intra_doc_links)]
22#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
23
24#[cfg(not(feature = "in-rust-tree"))]
25extern crate ra_ap_rustc_lexer as rustc_lexer;
26#[cfg(feature = "in-rust-tree")]
27extern crate rustc_driver as _;
28#[cfg(feature = "in-rust-tree")]
29extern crate rustc_lexer;
30
31mod event;
32mod frontmatter;
33mod grammar;
34mod input;
35mod lexed_str;
36mod output;
37mod parser;
38mod shortcuts;
39mod syntax_kind;
40mod token_set;
41
42pub use T_ as T;
43
44#[cfg(test)]
45mod tests;
46
47pub(crate) use token_set::TokenSet;
48
49pub use edition::Edition;
50
51pub use crate::{
52 input::Input,
53 lexed_str::LexedStr,
54 output::{Output, Step},
55 shortcuts::StrStep,
56 syntax_kind::SyntaxKind,
57};
58
59pub fn is_rust_whitespace(c: char) -> bool {
63 frontmatter::is_whitespace(c)
64}
65
66#[derive(Debug)]
88pub enum TopEntryPoint {
89 SourceFile,
90 MacroStmts,
91 MacroItems,
92 Pattern,
93 Type,
94 Expr,
95 MetaItem,
98}
99
100impl TopEntryPoint {
101 pub fn parse(&self, input: &Input) -> Output {
102 let _p = tracing::info_span!("TopEntryPoint::parse", ?self).entered();
103 let entry_point: fn(&'_ mut parser::Parser<'_>) = match self {
104 TopEntryPoint::SourceFile => grammar::entry::top::source_file,
105 TopEntryPoint::MacroStmts => grammar::entry::top::macro_stmts,
106 TopEntryPoint::MacroItems => grammar::entry::top::macro_items,
107 TopEntryPoint::Pattern => grammar::entry::top::pattern,
108 TopEntryPoint::Type => grammar::entry::top::type_,
109 TopEntryPoint::Expr => grammar::entry::top::expr,
110 TopEntryPoint::MetaItem => grammar::entry::top::meta_item,
111 };
112 let mut p = parser::Parser::new(input);
113 entry_point(&mut p);
114 let (events, errors) = p.finish();
115 let res = event::process(events, errors);
116
117 if cfg!(debug_assertions) {
118 let mut depth = 0;
119 let mut first = true;
120 for step in res.iter() {
121 assert!(depth > 0 || first);
122 first = false;
123 match step {
124 Step::Enter { .. } => depth += 1,
125 Step::Exit => depth -= 1,
126 Step::FloatSplit { ends_in_dot: has_pseudo_dot } => {
127 depth -= 1 + !has_pseudo_dot as usize
128 }
129 Step::Token { .. } | Step::Error { .. } => (),
130 }
131 }
132 assert!(!first, "no tree at all");
133 assert_eq!(depth, 0, "unbalanced tree");
134 }
135
136 res
137 }
138}
139
140#[derive(Debug)]
150pub enum PrefixEntryPoint {
151 Vis,
152 Block,
153 Stmt,
154 Pat,
155 PatTop,
156 Ty,
157 Expr,
158 Path,
159 Item,
160 MetaItem,
161}
162
163impl PrefixEntryPoint {
164 pub fn parse(&self, input: &Input) -> Output {
165 let entry_point: fn(&'_ mut parser::Parser<'_>) = match self {
166 PrefixEntryPoint::Vis => grammar::entry::prefix::vis,
167 PrefixEntryPoint::Block => grammar::entry::prefix::block,
168 PrefixEntryPoint::Stmt => grammar::entry::prefix::stmt,
169 PrefixEntryPoint::Pat => grammar::entry::prefix::pat,
170 PrefixEntryPoint::PatTop => grammar::entry::prefix::pat_top,
171 PrefixEntryPoint::Ty => grammar::entry::prefix::ty,
172 PrefixEntryPoint::Expr => grammar::entry::prefix::expr,
173 PrefixEntryPoint::Path => grammar::entry::prefix::path,
174 PrefixEntryPoint::Item => grammar::entry::prefix::item,
175 PrefixEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
176 };
177 let mut p = parser::Parser::new(input);
178 entry_point(&mut p);
179 let (events, errors) = p.finish();
180 event::process(events, errors)
181 }
182}
183
184pub struct Reparser(fn(&mut parser::Parser<'_>));
186
187impl Reparser {
188 pub fn for_node(
190 node: SyntaxKind,
191 first_child: Option<SyntaxKind>,
192 parent: Option<SyntaxKind>,
193 ) -> Option<Reparser> {
194 grammar::reparser(node, first_child, parent).map(Reparser)
195 }
196
197 pub fn parse(self, tokens: &Input) -> Output {
202 let Reparser(r) = self;
203 let mut p = parser::Parser::new(tokens);
204 r(&mut p);
205 let (events, errors) = p.finish();
206 event::process(events, errors)
207 }
208}