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 pub(crate) packs: crate::pack::Packs,
85}
86
87impl<'a> Parser<'a> {
88 #[must_use]
90 pub fn new(tokens: &'a Tokens, cx: Context<'a>) -> Parser<'a> {
91 Parser {
92 cursor: Cursor::new(&tokens.tokens),
93 tokens,
94 scopes: Scopes::new(),
95 errors: Errors::new(cx.error_limit),
96 ast: Ast::new(),
97 cx,
98 depth: 0,
99 too_deep: false,
100 packs: crate::pack::Packs::default(),
101 }
102 }
103
104 #[must_use]
106 pub fn finish(self) -> Parsed {
107 Parsed { ast: self.ast, diagnostics: self.errors.finish() }
108 }
109
110 pub(crate) fn error(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
112 self.errors.push(Diagnostic::error(message, span).with_code(code));
113 }
114
115 pub(crate) fn warn(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
117 self.errors.push(Diagnostic::warning(message, span).with_code(code));
118 }
119
120 pub(crate) fn pedantic(&mut self, code: &'static str, message: impl Into<String>, span: Span) {
122 if self.cx.pedantic {
123 self.warn(code, message, span);
124 }
125 }
126
127 pub(crate) fn stopped(&self) -> bool {
129 self.errors.stopped()
130 }
131
132 pub(crate) fn describe(&self, token: Token) -> String {
134 match token.kind {
135 TokenKind::Eof => "end of file".to_string(),
136 TokenKind::Punct(punct) => format!("`{}`", punct.as_str()),
137 TokenKind::Keyword(word) => format!("`{}`", word.as_str()),
138 TokenKind::Ident => {
139 format!("`{}`", self.cx.interner.resolve(Symbol::from_raw(token.value)))
140 }
141 TokenKind::Int => "an integer constant".to_string(),
142 TokenKind::Float => "a floating constant".to_string(),
143 TokenKind::Char => "a character constant".to_string(),
144 TokenKind::Str => "a string literal".to_string(),
145 }
146 }
147
148 pub(crate) fn expect_punct(&mut self, punct: Punct) -> bool {
154 if self.cursor.eat_punct(punct) {
155 return true;
156 }
157 let found = self.describe(self.cursor.current());
158 let message = format!("expected `{}`, found {found}", punct.as_str());
159 let at = if punct == Punct::Semi { self.cursor.prev_end() } else { self.cursor.span() };
160 self.error("E0400", message, at);
161 false
162 }
163
164 pub(crate) fn expect_keyword(&mut self, keyword: Keyword) -> bool {
166 if self.cursor.eat_keyword(keyword) {
167 return true;
168 }
169 let found = self.describe(self.cursor.current());
170 let message = format!("expected `{}`, found {found}", keyword.as_str());
171 self.error("E0400", message, self.cursor.span());
172 false
173 }
174
175 pub(crate) fn expect_ident(&mut self) -> Option<(Symbol, Span)> {
177 if let Some(name) = self.cursor.current().ident() {
178 let span = self.cursor.span();
179 self.cursor.bump();
180 return Some((name, span));
181 }
182 let found = self.describe(self.cursor.current());
183 self.error("E0401", format!("expected an identifier, found {found}"), self.cursor.span());
184 None
185 }
186
187 pub(crate) fn string_literal(&mut self) -> Option<StrId> {
193 let token = self.cursor.current();
194 if token.kind == TokenKind::Str {
195 self.cursor.bump();
196 let literal = self.tokens.strings[token.value as usize].clone();
197 return Some(self.ast.add_string(literal));
198 }
199 let found = self.describe(token);
200 self.error("E0409", format!("expected a string literal, found {found}"), token.span);
201 None
202 }
203
204 #[must_use]
210 pub(crate) fn enter(&mut self) -> bool {
211 if self.depth >= MAX_NESTING {
212 if !self.too_deep {
213 self.too_deep = true;
214 self.error(
215 "E0402",
216 format!("brackets nested more deeply than {MAX_NESTING} levels"),
217 self.cursor.span(),
218 );
219 }
220 return false;
221 }
222 self.depth += 1;
223 true
224 }
225
226 pub(crate) fn leave(&mut self) {
228 self.depth -= 1;
229 }
230
231 pub(crate) fn add_expr(&mut self, expr: Expr, span: Span) -> ExprId {
233 self.ast.expr(expr, span)
234 }
235
236 pub(crate) fn add_stmt(&mut self, stmt: Stmt, span: Span) -> StmtId {
238 self.ast.stmt(stmt, span)
239 }
240
241 pub(crate) fn add_decl(&mut self, decl: Decl, span: Span) -> DeclId {
243 self.ast.decl(decl, span)
244 }
245
246 pub(crate) fn poison_expr(&mut self, span: Span) -> ExprId {
248 self.ast.expr(Expr::Error, span)
249 }
250
251 pub(crate) fn poison_stmt(&mut self, span: Span) -> StmtId {
253 self.ast.stmt(Stmt::Error, span)
254 }
255
256 pub(crate) fn poison_decl(&mut self, span: Span) -> DeclId {
258 self.ast.decl(Decl::Error, span)
259 }
260
261 pub(crate) fn span_from(&self, start: Span) -> Span {
263 start.to(self.cursor.prev_end())
264 }
265}