use rucc_diag::Span;
use rucc_lex::{Encoding, Token, TokenKind};
use crate::pack::eat_punct;
use crate::parser::Parser;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Comment {
Lib(String),
Linker(String),
}
impl Parser<'_> {
pub(crate) fn comment_line(&mut self, mut rest: &[Token], span: Span) {
if !eat_punct(&mut rest, "(") {
self.warn("E0745", "missing `(` after `#pragma comment` - ignored", span);
return;
}
let Some(kind) = rest.first().and_then(|token| token.ident()) else {
self.warn("E0745", "malformed `#pragma comment` - ignored", span);
return;
};
let kind = self.cx.interner.resolve(kind).to_owned();
rest = &rest[1..];
let text = if eat_punct(&mut rest, ",") {
let Some(text) = self.comment_text(&mut rest) else {
self.warn("E0745", "`#pragma comment` wants a string after the comma", span);
return;
};
Some(text)
} else {
None
};
if !eat_punct(&mut rest, ")") || !rest.is_empty() {
self.warn("E0745", "malformed `#pragma comment` - ignored", span);
return;
}
match (kind.as_str(), text) {
("lib", Some(text)) => self.comments.push(Comment::Lib(text)),
("linker", Some(text)) => self.comments.push(Comment::Linker(text)),
("lib" | "linker", None) => {
let what = format!("`#pragma comment({kind})` wants a string - ignored");
self.warn("E0745", what, span);
}
("compiler" | "exestr" | "user", _) => {}
_ => {
let what = format!("unknown kind `{kind}` in `#pragma comment` - ignored");
self.warn("E0745", what, span);
}
}
}
fn comment_text(&self, rest: &mut &[Token]) -> Option<String> {
let token = rest.first()?;
if token.kind != TokenKind::Str {
return None;
}
let literal = self.tokens.strings.get(token.value as usize)?;
if !matches!(literal.encoding, Encoding::Plain | Encoding::Utf8) {
return None;
}
*rest = &rest[1..];
let bytes: Vec<u8> = literal.elements.iter().map(|&element| element as u8).collect();
Some(String::from_utf8_lossy(&bytes).into_owned())
}
}