diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-07-30 18:04:08 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-07-30 18:49:19 +0200 |
| commit | 1ee1d078e2480ddd08d40915bc7a74a8352acff0 (patch) | |
| tree | 1e7ff367278a19fead3e404cf06d65bfb80a6cd9 /src/parse/parser.rs | |
| parent | 42a27b48df427edf8dbb624c51551a90ecf2e7ea (diff) | |
Fatal errors
- Makes errors fatal, so that a phase is only reached when all previous phases were error-free
- Parsing still recovers and can produce multiple errors
- Evaluation fails fast and can thus produce only a single error (except for parse errors due to an import)
- The single error that could occur during execution is removed for now
- Removes Value::Error variant
Diffstat (limited to 'src/parse/parser.rs')
| -rw-r--r-- | src/parse/parser.rs | 64 |
1 files changed, 37 insertions, 27 deletions
diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 5fba961a..0238c8be 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,14 +1,17 @@ use std::fmt::{self, Debug, Formatter}; use std::ops::Range; -use super::{search_column, TokenMode, Tokens}; -use crate::diag::{Diag, DiagSet}; +use super::{count_columns, TokenMode, Tokens}; +use crate::diag::Error; +use crate::loading::FileId; use crate::syntax::{Pos, Span, Token}; /// A convenient token-based parser. pub struct Parser<'s> { - /// Parsing diagnostics. - pub diags: DiagSet, + /// The id of the parsed file. + file: FileId, + /// Parsing errors. + errors: Vec<Error>, /// An iterator over the source tokens. tokens: Tokens<'s>, /// The stack of open groups. @@ -57,11 +60,12 @@ pub enum Group { impl<'s> Parser<'s> { /// Create a new parser for the source string. - pub fn new(src: &'s str) -> Self { + pub fn new(file: FileId, src: &'s str) -> Self { let mut tokens = Tokens::new(src, TokenMode::Markup); let next = tokens.next(); Self { - diags: DiagSet::new(), + file, + errors: vec![], tokens, groups: vec![], next, @@ -71,39 +75,45 @@ impl<'s> Parser<'s> { } } - /// Add a diagnostic. - pub fn diag(&mut self, diag: Diag) { - self.diags.insert(diag); + /// Finish parsing and return all errors. + pub fn finish(self) -> Vec<Error> { + self.errors } - /// Eat the next token and add a diagnostic that it is not the expected - /// `thing`. + /// Add an error with location and message. + pub fn error(&mut self, span: impl Into<Span>, message: impl Into<String>) { + self.errors.push(Error { + file: self.file, + span: span.into(), + message: message.into(), + }); + } + + /// Eat the next token and add an error that it is not the expected `thing`. pub fn expected(&mut self, what: &str) { let before = self.next_start(); if let Some(found) = self.eat() { let after = self.prev_end(); - self.diag(error!( + self.error( before .. after, - "expected {}, found {}", - what, - found.name(), - )); + format!("expected {}, found {}", what, found.name()), + ); } else { - self.expected_at(what, self.next_start()); + self.expected_at(self.next_start(), what); } } - /// Add a diagnostic that `what` was expected at the given position. - pub fn expected_at(&mut self, what: &str, pos: impl Into<Pos>) { - self.diag(error!(pos.into(), "expected {}", what)); + /// Add an error that `what` was expected at the given position. + pub fn expected_at(&mut self, pos: impl Into<Pos>, what: &str) { + self.error(pos.into(), format!("expected {}", what)); } - /// Eat the next token and add a diagnostic that it is unexpected. + /// Eat the next token and add an error that it is unexpected. pub fn unexpected(&mut self) { let before = self.next_start(); if let Some(found) = self.eat() { let after = self.prev_end(); - self.diag(error!(before .. after, "unexpected {}", found.name())); + self.error(before .. after, format!("unexpected {}", found.name())); } } @@ -159,7 +169,7 @@ impl<'s> Parser<'s> { self.bump(); rescan = false; } else if required { - self.diag(error!(self.next_start(), "expected {}", end.name())); + self.error(self.next_start(), format!("expected {}", end.name())); } } @@ -276,12 +286,12 @@ impl<'s> Parser<'s> { Span::new(start, self.prev_end()) } - /// Consume the next token if it is the given one and produce a diagnostic - /// if not. + /// Consume the next token if it is the given one and produce an error if + /// not. pub fn expect(&mut self, t: Token) -> bool { let eaten = self.eat_if(t); if !eaten { - self.expected_at(t.name(), self.prev_end()); + self.expected_at(self.prev_end(), t.name()); } eaten } @@ -314,7 +324,7 @@ impl<'s> Parser<'s> { /// Determine the column for the given index in the source. pub fn column(&self, index: usize) -> usize { - search_column(self.tokens.scanner().get(.. index)) + count_columns(self.tokens.scanner().get(.. index)) } /// The span from `start` to [`self.prev_end()`](Self::prev_end). |
