scarf_parser/lexer/
mod.rs1pub(crate) mod callbacks;
7pub(crate) mod keywords;
8pub(crate) mod tokens;
9use crate::SpannedToken;
10use crate::report::{Report, ReportKind};
11pub use keywords::StandardVersion;
12use logos::Logos;
13use logos::Span as ByteSpan;
14use scarf_syntax::Span;
15use std::fs::{self, File};
16use std::io::{self, BufWriter, Write};
17use std::path::Path;
18pub use tokens::Token;
19
20pub type LexerResult<'a> = (Result<Token<'a>, String>, Span<'a>);
26
27impl<'a> TryFrom<&LexerResult<'a>> for Report {
28 type Error = ();
29 fn try_from(
30 value: &(Result<Token<'a>, String>, Span<'a>),
31 ) -> Result<Self, Self::Error> {
32 let (result, span) = value;
33 let Err(text) = result else {
34 return Err(());
35 };
36 if text.len() == 0 {
37 Ok(
38 Report::new(
39 ReportKind::Error,
40 span,
41 "L1",
42 "Unrecognized token",
43 )
44 .with_label(
45 &span,
46 ReportKind::Error,
47 "Unrecognized token",
48 ),
49 )
50 } else {
51 Ok(Report::new(ReportKind::Error, span, "L2", text).with_label(
52 &span,
53 ReportKind::Error,
54 text,
55 ))
56 }
57 }
58}
59
60fn map_lex_result<'a>(lex_result: LexerResult<'a>) -> SpannedToken<'a> {
61 match lex_result.0 {
62 Ok(tok) => SpannedToken(tok, lex_result.1),
63 Err(_) => SpannedToken(Token::Error, lex_result.1),
64 }
65}
66
67pub trait LexedSource<'a>: Iterator<Item = LexerResult<'a>> + Clone {
69 fn report_errors(&self) -> impl Iterator<Item = Report> {
71 self.clone().into_iter().filter_map(|result| {
72 let report_result: Result<Report, ()> = Report::try_from(&result);
73 report_result.ok()
74 })
75 }
76
77 fn dump(&self, file_path: &Path) -> io::Result<()> {
79 if let Some(parent_dir) = file_path.parent() {
80 fs::create_dir_all(parent_dir)?;
81 }
82 let file = File::create(file_path)?;
83 let mut writer = BufWriter::new(file);
84 for (result, span) in self.clone() {
85 let dump_str = format!(
86 "[{:>2}:{:>2}] {}\n",
87 span.bytes.start,
88 span.bytes.end,
89 match result {
90 Ok(token) => token,
91 Err(_) => Token::Error,
92 }
93 );
94 writer.write_all(dump_str.as_bytes())?;
95 }
96 writer.flush()?;
97 Ok(())
98 }
99
100 fn process(self) -> std::vec::IntoIter<LexerResult<'a>> {
105 self.collect::<Vec<_>>().into_iter()
106 }
107
108 fn tokens(self) -> impl Iterator<Item = SpannedToken<'a>> {
110 self.into_iter().map(map_lex_result)
111 }
112}
113impl<'a, T> LexedSource<'a> for T where
114 T: Iterator<Item = LexerResult<'a>> + Clone
115{
116}
117
118fn token_span_mapper<'a>(
119 file_name: &'a str,
120 included_from: Option<&'a Span<'a>>,
121) -> impl Fn((Result<Token<'a>, String>, ByteSpan)) -> LexerResult<'a> + Clone {
122 move |(token_result, byte_span)| {
123 (
124 token_result,
125 Span {
126 file: file_name,
127 bytes: byte_span,
128 expanded_from: None,
129 included_from,
130 },
131 )
132 }
133}
134
135pub(crate) fn lex_helper<'a>(
136 src: &'a str,
137 file_name: &'a str,
138 included_from: Option<&'a Span<'a>>,
139) -> impl LexedSource<'a> {
140 let span_mapper = token_span_mapper(file_name, included_from);
141 Token::lexer(src).spanned().map(span_mapper)
142}
143
144pub fn lex<'a>(src: &'a str, file_name: &'a str) -> impl LexedSource<'a> {
160 lex_helper(src, file_name, None)
161}