Skip to content

Commit

Permalink
First attempt at error resilient code gen
Browse files Browse the repository at this point in the history
  • Loading branch information
AZWN committed Nov 23, 2023
1 parent 9139389 commit b54e685
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 32 deletions.
35 changes: 20 additions & 15 deletions scopegraphs-macros/src/regex.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::rc::Rc;

use proc_macro::TokenStream;
use quote::quote_spanned;
use scopegraphs_regular_expressions::Regex;
use syn::parse::{Parse, ParseStream};
use syn::spanned::Spanned;
use syn::{Attribute, Ident, Meta, Token, Type};

#[cfg(feature = "dot")]
Expand All @@ -19,25 +19,31 @@ pub(crate) struct RegexInput {
_close: Token![>],
_equals: Token![=],
regex: Regex,
_err: Vec<syn::Error>,
}

impl Parse for RegexInput {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(Self {
attrs: input.call(Attribute::parse_outer)?,
_type: input.parse()?,
name: input.parse()?,
_open: input.parse()?,
alphabet_type: input.parse()?,
_close: input.parse()?,
_equals: input.parse()?,
regex: input.parse()?,
})
let attrs = input.call(Attribute::parse_outer)?;
let _type = input.parse()?;
let name = input.parse()?;
let _open = input.parse()?;
let alphabet_type = input.parse()?;
let _close = input.parse()?;
let _equals = input.parse()?;
let regex_err = input.parse();
let (regex, _err) = match regex_err {
Ok(re) => (re, vec![]),
Err(err) => (Regex::Complement(Rc::new(Regex::EmptySet)), vec![err]),
};
println!("Parsed regex input: errors: {:?}", _err);
Ok(Self { attrs, _type, name, _open, alphabet_type, _close, _equals, regex, _err })
}
}

impl RegexInput {
pub fn compile(self) -> TokenStream {
let mut errors = self._err;
#[cfg(feature = "dot")]
let mut graph = None;

Expand All @@ -56,8 +62,7 @@ impl RegexInput {
graph = Some(s);
}
i => {
return quote_spanned!(i.span() => compile_error!("unexpected attribute");)
.into();
errors.push(syn::Error::new_spanned(i, "unexpected attribute"))
}
}
}
Expand All @@ -74,6 +79,6 @@ impl RegexInput {
.unwrap_or_else(|e| panic!("failed while graphing at {path}: {e}"));
}

compiled.emit(&self.name, &self.alphabet_type).into()
compiled.emit(&self.name, &self.alphabet_type, errors).into()
}
}
12 changes: 11 additions & 1 deletion scopegraphs-regular-expressions/src/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ impl Automaton {
/// Convert this compiled regex into rust code that accepts this regular expression.
/// `name` is the name of the type that is emitted, and `alphabet` is the type of symbols
/// that the machine should accept.
pub fn emit(&self, name: &Ident, alphabet: &Type) -> TokenStream {
pub fn emit(&self, name: &Ident, alphabet: &Type, errors: Vec<syn::Error>) -> TokenStream {
let Self {
states, initial, ..
} = self;
Expand Down Expand Up @@ -39,7 +39,9 @@ impl Automaton {

let finals: Vec<_> = states.iter().map(|i| i.is_final).collect();
let accepting: Vec<_> = states.iter().map(MatchState::is_accepting).collect();
let compile_errors: TokenStream = errors.iter().flat_map(syn::Error::to_compile_error).collect();

println!("Emitting code, errors: {:?}", errors);
quote!(
struct #name {
state: usize,
Expand Down Expand Up @@ -77,6 +79,14 @@ impl Automaton {
}
}
}

// try removing this wrapper: many more errors appear
impl #name {
fun error_container() {
#(#compile_errors;)
return ();
}
}
)
}
}
4 changes: 0 additions & 4 deletions scopegraphs-regular-expressions/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -834,10 +834,6 @@ impl<'a> Parser<'a> {

/// Entry point: parses the `input` to a [`Regex`].
pub fn parse_regex(input: ParseStream) -> syn::Result<Regex> {
if input.is_empty() {
return Ok(Regex::Complement(Rc::new(Regex::EmptySet)));
}

let mut parser = Parser::init(input)?;
let mut accept = false;
while !accept {
Expand Down
12 changes: 0 additions & 12 deletions scopegraphs/tests/test_regex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,3 @@ fn test_negate_or() {
assert!(Machine::new().accepts([C]));
}

#[test]
fn test_empty() {
use Alphabet::*;

compile_regex!(#[graph="empty.dot"] type Machine<Alphabet> = );

assert!(Machine::new().accepts([]));
assert!(Machine::new().accepts([A]));
assert!(Machine::new().accepts([B]));
assert!(Machine::new().accepts([C]));
assert!(Machine::new().accepts([A, B, C]));
}

0 comments on commit b54e685

Please sign in to comment.