Skip to content

Instantly share code, notes, and snippets.

@SteveAlexander
Created March 15, 2025 14:45
Show Gist options
  • Save SteveAlexander/45b44b8425371d5e4e6e3904ad76aaec to your computer and use it in GitHub Desktop.
Save SteveAlexander/45b44b8425371d5e4e6e3904ad76aaec to your computer and use it in GitHub Desktop.
asciidork attribute ref observer sketch
--- a/parser/src/tasks/attr_refs.rs
+++ b/parser/src/tasks/attr_refs.rs
@@ -35,22 +35,30 @@ impl<'arena> Parser<'arena> {
if token.kind(TokenKind::AttrRef) && self.ctx.subs.attr_refs() {
match self.document.meta.get(token.attr_name()) {
Some(AttrValue::String(attr_val)) => {
+ if let Some(observer) = &self.attr_ref_observer {
+ observer.attr_ref_replaced(token.attr_name(), token.loc);
+ }
if !attr_val.is_empty() {
self.lexer.set_tmp_buf(attr_val, BufLoc::Repeat(token.loc));
}
line.push(token);
}
- _ => match self.document.meta.str("attribute-missing") {
- Some("drop") => {}
- Some("drop-line") => *drop_line = true,
- val => {
- token.kind = TokenKind::Word;
- if val == Some("warn") {
- self.err_token_full("Skipping reference to missing attribute", &token)?;
+ _ => {
+ if let Some(observer) = &self.attr_ref_observer {
+ observer.attr_ref_missing(token.attr_name(), token.loc);
+ }
+ match self.document.meta.str("attribute-missing") {
+ Some("drop") => {}
+ Some("drop-line") => *drop_line = true,
+ val => {
+ token.kind = TokenKind::Word;
+ if val == Some("warn") {
+ self.err_token_full("Skipping reference to missing attribute", &token)?;
+ }
+ line.push(token);
}
- line.push(token);
}
- },
+ }
}
} else {
line.push(token);
--- a/parser/src/parser.rs
+++ b/parser/src/parser.rs
@@ -12,6 +12,7 @@ pub struct Parser<'arena> {
pub(super) errors: RefCell<Vec<Diagnostic>>,
pub(super) strict: bool, // todo: naming...
pub(super) include_resolver: Option<Box<dyn IncludeResolver>>,
+ pub(super) attr_ref_observer: Option<Box<dyn AttrRefObserver>>,
}
pub struct ParseResult<'arena> {
@@ -19,6 +20,12 @@ pub struct ParseResult<'arena> {
pub warnings: Vec<Diagnostic>,
}
+pub trait AttrRefObserver {
+ fn attr_ref_replaced(&self, attr_name: &str, loc: SourceLocation);
+ fn attr_ref_missing(&self, attr_name: &str, loc: SourceLocation);
+}
+
+
impl<'arena> Parser<'arena> {
pub fn new(src: BumpVec<'arena, u8>, file: SourceFile, bump: &'arena Bump) -> Self {
Parser::from_lexer(Lexer::new(src, file, bump))
@@ -39,6 +46,7 @@ impl<'arena> Parser<'arena> {
strict: true,
include_resolver: None,
lexer,
+ attr_ref_observer: None,
};
parser.set_source_file_attrs();
parser
@@ -67,6 +75,10 @@ impl<'arena> Parser<'arena> {
self.include_resolver = Some(resolver);
}
+ pub fn set_attr_ref_observer(&mut self, observer: Box<dyn AttrRefObserver>) {
+ self.attr_ref_observer = Some(observer);
+ }
+
pub fn cell_parser(&mut self, src: BumpVec<'arena, u8>, offset: u32) -> Parser<'arena> {
let mut cell_parser = Parser::new(src, self.lexer.source_file().clone(), self.bump);
cell_parser.strict = self.strict;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment