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}
71
72impl Parsed {
73 #[must_use]
75 pub fn failed(&self) -> bool {
76 self.diagnostics.iter().any(|d| d.severity.is_fatal())
77 }
78}
79
80#[derive(Debug)]
82pub struct Parser<'a> {
83 pub(crate) cursor: Cursor<'a>,
84 pub(crate) tokens: &'a Tokens,
85 pub(crate) scopes: Scopes,
86 pub(crate) errors: Errors,
87 pub(crate) ast: Ast,
88 pub(crate) cx: Context<'a>,
89 depth: usize,
91 too_deep: bool,
94 pub(crate) packs: crate::pack::Packs,
96}
97
98impl<'a> Parser<'a> {
99 #[must_use]
101 pub fn new(tokens: &'a Tokens, cx: Context<'a>) -> Parser<'a> {
102 let mut scopes = Scopes::new();
103 for &name in cx.type_names {
104 scopes.declare(name, IdentKind::Typedef);
105 }
106 Parser {
107 cursor: Cursor::new(&tokens.tokens),
108 tokens,
109 scopes,
110 errors: Errors::new(cx.error_limit),
111 ast: Ast::new(),
112 cx,
113 depth: 0,
114 too_deep: false,
115 packs: crate::pack::Packs::default(),
116 }
117 }
118
119 #[must_use]
121 pub fn finish(self) -> Parsed {
122 Parsed { ast: self.ast, diagnostics: self.errors.finish() }
123 }
124
125 pub(crate) fn error(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
127 self.errors.push(Diagnostic::error(message, span).with_code(code));
128 }
129
130 pub(crate) fn warn(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
132 self.errors.push(Diagnostic::warning(message, span).with_code(code));
133 }
134
135 pub(crate) fn pedantic(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
137 if self.cx.pedantic {
138 self.warn(code, message, span);
139 }
140 }
141
142 pub(crate) fn stopped(&self) -> bool {
144 self.errors.stopped()
145 }
146
147 pub(crate) fn describe(&self, token: Token) -> String {
149 match token.kind {
150 TokenKind::Eof => "end of file".to_string(),
151 TokenKind::Punct(punct) => format!("`{}`", punct.as_str()),
152 TokenKind::Keyword(word) => format!("`{}`", word.as_str()),
153 TokenKind::Ident => {
154 format!("`{}`", self.cx.interner.resolve(Symbol::from_raw(token.value)))
155 }
156 TokenKind::Int => "an integer constant".to_string(),
157 TokenKind::Float => "a floating constant".to_string(),
158 TokenKind::Char => "a character constant".to_string(),
159 TokenKind::Str => "a string literal".to_string(),
160 }
161 }
162
163 pub(crate) fn expect_punct(&mut self, punct: Punct) -> bool {
169 if self.cursor.eat_punct(punct) {
170 return true;
171 }
172 let found = self.describe(self.cursor.current());
173 let message = format!("expected `{}`, found {found}", punct.as_str());
174 let at = if punct == Punct::Semi { self.cursor.prev_end() } else { self.cursor.span() };
175 self.error("E0400", message, at);
176 false
177 }
178
179 pub(crate) fn expect_keyword(&mut self, keyword: Keyword) -> bool {
181 if self.cursor.eat_keyword(keyword) {
182 return true;
183 }
184 let found = self.describe(self.cursor.current());
185 let message = format!("expected `{}`, found {found}", keyword.as_str());
186 self.error("E0400", message, self.cursor.span());
187 false
188 }
189
190 pub(crate) fn expect_ident(&mut self) -> Option<(Symbol, Span)> {
192 if let Some(name) = self.cursor.current().ident() {
193 let span = self.cursor.span();
194 self.cursor.bump();
195 return Some((name, span));
196 }
197 let found = self.describe(self.cursor.current());
198 self.error("E0401", format!("expected an identifier, found {found}"), self.cursor.span());
199 None
200 }
201
202 pub(crate) fn string_literal(&mut self) -> Option<StrId> {
208 let token = self.cursor.current();
209 if token.kind == TokenKind::Str {
210 self.cursor.bump();
211 let literal = self.tokens.strings[token.value as usize].clone();
212 return Some(self.ast.add_string(literal));
213 }
214 let found = self.describe(token);
215 self.error("E0409", format!("expected a string literal, found {found}"), token.span);
216 None
217 }
218
219 #[must_use]
225 pub(crate) fn enter(&mut self) -> bool {
226 if self.depth >= MAX_NESTING {
227 if !self.too_deep {
228 self.too_deep = true;
229 self.error(
230 "E0402",
231 format!("brackets nested more deeply than {MAX_NESTING} levels"),
232 self.cursor.span(),
233 );
234 }
235 return false;
236 }
237 self.depth += 1;
238 true
239 }
240
241 pub(crate) fn leave(&mut self) {
243 self.depth -= 1;
244 }
245
246 pub(crate) fn add_expr(&mut self, expr: Expr, span: Span) -> ExprId {
248 self.ast.expr(expr, span)
249 }
250
251 pub(crate) fn add_stmt(&mut self, stmt: Stmt, span: Span) -> StmtId {
253 self.ast.stmt(stmt, span)
254 }
255
256 pub(crate) fn add_decl(&mut self, decl: Decl, span: Span) -> DeclId {
258 self.ast.decl(decl, span)
259 }
260
261 pub(crate) fn poison_expr(&mut self, span: Span) -> ExprId {
263 self.ast.expr(Expr::Error, span)
264 }
265
266 pub(crate) fn poison_stmt(&mut self, span: Span) -> StmtId {
268 self.ast.stmt(Stmt::Error, span)
269 }
270
271 pub(crate) fn poison_decl(&mut self, span: Span) -> DeclId {
273 self.ast.decl(Decl::Error, span)
274 }
275
276 pub(crate) fn span_from(&self, start: Span) -> Span {
278 start.to(self.cursor.prev_end())
279 }
280}