litcheck_filecheck/parse/
mod.rs1mod lexer;
2mod parser;
3#[cfg(test)]
4mod tests;
5
6use crate::common::*;
7
8pub use self::lexer::{Lexed, Lexer, LexerError, Token};
9pub use self::parser::CheckFileParser;
10
11pub type ParseError<'a> = lalrpop_util::ParseError<usize, Token<'a>, ParserError>;
12
13#[derive(Diagnostic, Debug, thiserror::Error)]
14pub enum ParserError {
15 #[error(transparent)]
16 #[diagnostic(transparent)]
17 Lexer(#[from] LexerError),
18 #[error(transparent)]
19 #[diagnostic(transparent)]
20 Expr(#[from] crate::expr::ExprError),
21 #[error("invalid token")]
22 #[diagnostic()]
23 InvalidToken {
24 #[label("occurs here")]
25 span: SourceSpan,
26 },
27 #[error("unrecognized token")]
28 #[diagnostic(help("expected one of: {}", expected.as_slice().join(", ")))]
29 UnrecognizedToken {
30 #[label("lexed a {token} here")]
31 span: SourceSpan,
32 token: String,
33 expected: Vec<String>,
34 },
35 #[error("unexpected trailing tokens")]
36 #[diagnostic()]
37 ExtraToken {
38 #[label("{token} was found here, but was not expected")]
39 span: SourceSpan,
40 token: String,
41 },
42 #[error("unexpected end of file")]
43 #[diagnostic(help("expected one of: {}", expected.as_slice().join(", ")))]
44 UnrecognizedEof {
45 #[label("reached end of file here")]
46 span: SourceSpan,
47 expected: Vec<String>,
48 },
49 #[error("invalid check type")]
50 #[diagnostic()]
51 InvalidCheckType {
52 #[label("this is not a valid check type")]
53 span: SourceSpan,
54 },
55 #[error("invalid pattern")]
56 #[diagnostic(help("CHECK-EMPTY should be used to check for empty lines"))]
57 EmptyPattern {
58 #[label("expected a non-empty pattern")]
59 span: SourceSpan,
60 },
61 #[error("invalid check modifier")]
62 #[diagnostic()]
63 InvalidCheckModifier {
64 #[label("this modifier is not recognized, valid modifiers are: LITERAL")]
65 span: SourceSpan,
66 },
67 #[error("unclosed substitution block")]
68 #[diagnostic()]
69 UnclosedSubstitution {
70 #[label("no closing ']]' found for this block")]
71 span: SourceSpan,
72 },
73 #[error("unclosed regex block")]
74 #[diagnostic()]
75 UnclosedRegex {
76 #[label("no closing '}}' found for this block")]
77 span: SourceSpan,
78 },
79 #[error("no check strings found with prefix(es) {}", text::DisplayCommaSeparated(.0.as_slice()))]
80 #[diagnostic()]
81 UnusedCheckPrefixes(Vec<Arc<str>>),
82}
83
84pub type ParseResult<T> = Result<T, ParserError>;
85
86pub trait Parser<'parser> {
87 type Value<'a>
88 where
89 'a: 'parser;
90
91 fn parse<'a: 'parser, S>(&mut self, code: &'a S) -> ParseResult<Self::Value<'a>>
92 where
93 S: SourceFile + ?Sized + 'a;
94}