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::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}
43
44impl<'a> Context<'a> {
45 #[must_use]
47 pub fn new(interner: &'a Interner, std: Std) -> Context<'a> {
48 Context { interner, std, gnu: true, pedantic: false, error_limit: DEFAULT_ERROR_LIMIT }
49 }
50}
51
52#[derive(Debug)]
54pub struct Parsed {
55 pub ast: Ast,
57 pub diagnostics: Vec<Diagnostic>,
59}
60
61impl Parsed {
62 #[must_use]
64 pub fn failed(&self) -> bool {
65 self.diagnostics.iter().any(|d| d.severity.is_fatal())
66 }
67}
68
69#[derive(Debug)]
71pub struct Parser<'a> {
72 pub(crate) cursor: Cursor<'a>,
73 pub(crate) tokens: &'a Tokens,
74 pub(crate) scopes: Scopes,
75 pub(crate) errors: Errors,
76 pub(crate) ast: Ast,
77 pub(crate) cx: Context<'a>,
78 depth: usize,
80 too_deep: bool,
83}
84
85impl<'a> Parser<'a> {
86 #[must_use]
88 pub fn new(tokens: &'a Tokens, cx: Context<'a>) -> Parser<'a> {
89 Parser {
90 cursor: Cursor::new(&tokens.tokens),
91 tokens,
92 scopes: Scopes::new(),
93 errors: Errors::new(cx.error_limit),
94 ast: Ast::new(),
95 cx,
96 depth: 0,
97 too_deep: false,
98 }
99 }
100
101 #[must_use]
103 pub fn finish(self) -> Parsed {
104 Parsed { ast: self.ast, diagnostics: self.errors.finish() }
105 }
106
107 pub(crate) fn error(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
109 self.errors.push(Diagnostic::error(message, span).with_code(code));
110 }
111
112 pub(crate) fn warn(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
114 self.errors.push(Diagnostic::warning(message, span).with_code(code));
115 }
116
117 pub(crate) fn pedantic(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
119 if self.cx.pedantic {
120 self.warn(code, message, span);
121 }
122 }
123
124 pub(crate) fn stopped(&self) -> bool {
126 self.errors.stopped()
127 }
128
129 pub(crate) fn describe(&self, token: Token) -> String {
131 match token.kind {
132 TokenKind::Eof => "end of file".to_string(),
133 TokenKind::Punct(punct) => format!("`{}`", punct.as_str()),
134 TokenKind::Keyword(word) => format!("`{}`", word.as_str()),
135 TokenKind::Ident => {
136 format!("`{}`", self.cx.interner.resolve(Symbol::from_raw(token.value)))
137 }
138 TokenKind::Int => "an integer constant".to_string(),
139 TokenKind::Float => "a floating constant".to_string(),
140 TokenKind::Char => "a character constant".to_string(),
141 TokenKind::Str => "a string literal".to_string(),
142 }
143 }
144
145 pub(crate) fn spelling(&self, name: Symbol) -> &str {
147 self.cx.interner.resolve(name)
148 }
149
150 pub(crate) fn expect_punct(&mut self, punct: Punct) -> bool {
156 if self.cursor.eat_punct(punct) {
157 return true;
158 }
159 let found = self.describe(self.cursor.current());
160 let message = format!("expected `{}`, found {found}", punct.as_str());
161 let at = if punct == Punct::Semi { self.cursor.prev_end() } else { self.cursor.span() };
162 self.error("E0400", message, at);
163 false
164 }
165
166 pub(crate) fn expect_keyword(&mut self, keyword: Keyword) -> bool {
168 if self.cursor.eat_keyword(keyword) {
169 return true;
170 }
171 let found = self.describe(self.cursor.current());
172 let message = format!("expected `{}`, found {found}", keyword.as_str());
173 self.error("E0400", message, self.cursor.span());
174 false
175 }
176
177 pub(crate) fn expect_ident(&mut self) -> Option<(Symbol, Span)> {
179 if let Some(name) = self.cursor.current().ident() {
180 let span = self.cursor.span();
181 self.cursor.bump();
182 return Some((name, span));
183 }
184 let found = self.describe(self.cursor.current());
185 self.error("E0401", format!("expected an identifier, found {found}"), self.cursor.span());
186 None
187 }
188
189 pub(crate) fn string_literal(&mut self) -> Option<StrId> {
195 let token = self.cursor.current();
196 if token.kind == TokenKind::Str {
197 self.cursor.bump();
198 let literal = self.tokens.strings[token.value as usize].clone();
199 return Some(self.ast.add_string(literal));
200 }
201 let found = self.describe(token);
202 self.error("E0409", format!("expected a string literal, found {found}"), token.span);
203 None
204 }
205
206 #[must_use]
212 pub(crate) fn enter(&mut self) -> bool {
213 if self.depth >= MAX_NESTING {
214 if !self.too_deep {
215 self.too_deep = true;
216 self.error(
217 "E0402",
218 format!("brackets nested more deeply than {MAX_NESTING} levels"),
219 self.cursor.span(),
220 );
221 }
222 return false;
223 }
224 self.depth += 1;
225 true
226 }
227
228 pub(crate) fn leave(&mut self) {
230 self.depth -= 1;
231 }
232
233 pub(crate) fn add_expr(&mut self, expr: Expr, span: Span) -> ExprId {
235 self.ast.expr(expr, span)
236 }
237
238 pub(crate) fn add_stmt(&mut self, stmt: Stmt, span: Span) -> StmtId {
240 self.ast.stmt(stmt, span)
241 }
242
243 pub(crate) fn add_decl(&mut self, decl: Decl, span: Span) -> DeclId {
245 self.ast.decl(decl, span)
246 }
247
248 pub(crate) fn poison_expr(&mut self, span: Span) -> ExprId {
250 self.ast.expr(Expr::Error, span)
251 }
252
253 pub(crate) fn poison_stmt(&mut self, span: Span) -> StmtId {
255 self.ast.stmt(Stmt::Error, span)
256 }
257
258 pub(crate) fn poison_decl(&mut self, span: Span) -> DeclId {
260 self.ast.decl(Decl::Error, span)
261 }
262
263 pub(crate) fn span_from(&self, start: Span) -> Span {
265 start.to(self.cursor.prev_end())
266 }
267}