1use rucc_ast::{Ast, Decl, DeclId, Expr, ExprId, Stmt, StmtId, StrId};
11use rucc_base::{Interner, Symbol};
12use rucc_diag::{DEFAULT_ERROR_LIMIT, Diagnostic, Errors, Span};
13use rucc_lex::{Keyword, Punct, Token, TokenKind, Tokens};
14use rucc_session::Std;
15
16use crate::cursor::Cursor;
17use crate::scope::{IdentKind, Scopes};
18
19pub const MAX_NESTING: usize = 256;
27
28#[derive(Debug, Clone, Copy)]
30pub struct Context<'a> {
31 pub interner: &'a Interner,
33 pub std: Std,
36 pub gnu: bool,
38 pub pedantic: bool,
40 pub error_limit: usize,
42 pub type_names: &'a [Symbol],
46}
47
48impl<'a> Context<'a> {
49 #[must_use]
51 pub fn new(interner: &'a Interner, std: Std) -> Context<'a> {
52 Context {
53 interner,
54 std,
55 gnu: true,
56 pedantic: false,
57 error_limit: DEFAULT_ERROR_LIMIT,
58 type_names: &[],
59 }
60 }
61}
62
63#[derive(Debug)]
65pub struct Parsed {
66 pub ast: Ast,
68 pub diagnostics: Vec<Diagnostic>,
70 pub comments: Vec<crate::Comment>,
73}
74
75impl Parsed {
76 #[must_use]
78 pub fn failed(&self) -> bool {
79 self.diagnostics.iter().any(|d| d.severity.is_fatal())
80 }
81}
82
83#[derive(Debug)]
85pub struct Parser<'a> {
86 pub(crate) cursor: Cursor<'a>,
87 pub(crate) tokens: &'a Tokens,
88 pub(crate) scopes: Scopes,
89 pub(crate) errors: Errors,
90 pub(crate) ast: Ast,
91 pub(crate) cx: Context<'a>,
92 depth: usize,
94 too_deep: bool,
97 pub(crate) packs: crate::pack::Packs,
99 pub(crate) comments: Vec<crate::Comment>,
101}
102
103impl<'a> Parser<'a> {
104 #[must_use]
106 pub fn new(tokens: &'a Tokens, cx: Context<'a>) -> Parser<'a> {
107 let mut scopes = Scopes::new();
108 for &name in cx.type_names {
109 scopes.declare(name, IdentKind::Typedef);
110 }
111 Parser {
112 cursor: Cursor::new(&tokens.tokens),
113 tokens,
114 scopes,
115 errors: Errors::new(cx.error_limit),
116 ast: Ast::new(),
117 cx,
118 depth: 0,
119 too_deep: false,
120 packs: crate::pack::Packs::default(),
121 comments: Vec::new(),
122 }
123 }
124
125 #[must_use]
127 pub fn finish(self) -> Parsed {
128 Parsed { ast: self.ast, diagnostics: self.errors.finish(), comments: self.comments }
129 }
130
131 pub(crate) fn error(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
133 self.errors.push(Diagnostic::error(message, span).with_code(code));
134 }
135
136 pub(crate) fn warn(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
138 self.errors.push(Diagnostic::warning(message, span).with_code(code));
139 }
140
141 pub(crate) fn pedantic(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
143 if self.cx.pedantic {
144 self.warn(code, message, span);
145 }
146 }
147
148 pub(crate) fn stopped(&self) -> bool {
150 self.errors.stopped()
151 }
152
153 pub(crate) fn describe(&self, token: Token) -> String {
155 match token.kind {
156 TokenKind::Eof => "end of file".to_string(),
157 TokenKind::Punct(punct) => format!("`{}`", punct.as_str()),
158 TokenKind::Keyword(word) => format!("`{}`", word.as_str()),
159 TokenKind::Ident => {
160 format!("`{}`", self.cx.interner.resolve(Symbol::from_raw(token.value)))
161 }
162 TokenKind::Int => "an integer constant".to_string(),
163 TokenKind::Float => "a floating constant".to_string(),
164 TokenKind::Char => "a character constant".to_string(),
165 TokenKind::Str => "a string literal".to_string(),
166 }
167 }
168
169 pub(crate) fn expect_punct(&mut self, punct: Punct) -> bool {
175 if self.cursor.eat_punct(punct) {
176 return true;
177 }
178 let found = self.describe(self.cursor.current());
179 let message = format!("expected `{}`, found {found}", punct.as_str());
180 let at = if punct == Punct::Semi { self.cursor.prev_end() } else { self.cursor.span() };
181 self.error("E0400", message, at);
182 false
183 }
184
185 pub(crate) fn expect_keyword(&mut self, keyword: Keyword) -> bool {
187 if self.cursor.eat_keyword(keyword) {
188 return true;
189 }
190 let found = self.describe(self.cursor.current());
191 let message = format!("expected `{}`, found {found}", keyword.as_str());
192 self.error("E0400", message, self.cursor.span());
193 false
194 }
195
196 pub(crate) fn expect_ident(&mut self) -> Option<(Symbol, Span)> {
198 if let Some(name) = self.cursor.current().ident() {
199 let span = self.cursor.span();
200 self.cursor.bump();
201 return Some((name, span));
202 }
203 let found = self.describe(self.cursor.current());
204 self.error("E0401", format!("expected an identifier, found {found}"), self.cursor.span());
205 None
206 }
207
208 pub(crate) fn string_literal(&mut self) -> Option<StrId> {
214 let token = self.cursor.current();
215 if token.kind == TokenKind::Str {
216 self.cursor.bump();
217 let literal = self.tokens.strings[token.value as usize].clone();
218 return Some(self.ast.add_string(literal));
219 }
220 let found = self.describe(token);
221 self.error("E0409", format!("expected a string literal, found {found}"), token.span);
222 None
223 }
224
225 #[must_use]
231 pub(crate) fn enter(&mut self) -> bool {
232 if self.depth >= MAX_NESTING {
233 if !self.too_deep {
234 self.too_deep = true;
235 self.error(
236 "E0402",
237 format!("brackets nested more deeply than {MAX_NESTING} levels"),
238 self.cursor.span(),
239 );
240 }
241 return false;
242 }
243 self.depth += 1;
244 true
245 }
246
247 pub(crate) fn leave(&mut self) {
249 self.depth -= 1;
250 }
251
252 pub(crate) fn add_expr(&mut self, expr: Expr, span: Span) -> ExprId {
254 self.ast.expr(expr, span)
255 }
256
257 pub(crate) fn add_stmt(&mut self, stmt: Stmt, span: Span) -> StmtId {
259 self.ast.stmt(stmt, span)
260 }
261
262 pub(crate) fn add_decl(&mut self, decl: Decl, span: Span) -> DeclId {
264 self.ast.decl(decl, span)
265 }
266
267 pub(crate) fn poison_expr(&mut self, span: Span) -> ExprId {
269 self.ast.expr(Expr::Error, span)
270 }
271
272 pub(crate) fn poison_stmt(&mut self, span: Span) -> StmtId {
274 self.ast.stmt(Stmt::Error, span)
275 }
276
277 pub(crate) fn poison_decl(&mut self, span: Span) -> DeclId {
279 self.ast.decl(Decl::Error, span)
280 }
281
282 pub(crate) fn span_from(&self, start: Span) -> Span {
284 start.to(self.cursor.prev_end())
285 }
286}