-
Notifications
You must be signed in to change notification settings - Fork 23
feat: Introducing fzn-rs, a better FlatZinc parser that is easier to re-use across projects
#238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
b2c3edc
feat(fzn-rs): Started working on a more ergonomic
maartenflippo 4832931
feat(fzn-rs): Implement first go at the derive macro
maartenflippo d93b3dc
fix(fzn-rs): Don't panic in an error case, but emit a compiler error
maartenflippo e502505
refactor(fzn-rs): Attach spans to AST in preparation for error messages
maartenflippo 8d188a3
refactor(fzn-rs): Simplify the code generation code
maartenflippo 1546a42
feat(fzn-rs): Improve error messages when parsing instance
maartenflippo cbd928d
feat(fzn-rs): Resolve arrays from the AST
maartenflippo 3e128a6
refactor(fzn-rs): Cleanup implementation and add documentation
maartenflippo acff028
docs(fzn-rs): Add root module documentation to fzn-rs
maartenflippo 1c2feab
feat(fzn-rs): Explicitly set the name of a constraint in derive macro
maartenflippo aa4bbc9
feat(fzn-rs): Implement a basic FZN parser, without annotation support
maartenflippo 9cb3af9
refactor(fzn-rs): Update documentation and generalize variable arguments
maartenflippo e1d0052
feat(fzn-rs): Start implemented typed annotation parsing
maartenflippo bab22ac
feat(fzn-rs): Implement parsing of nested annotations
maartenflippo 503ab69
feat(fzn-rs): Allow typed annotations on the solve item
maartenflippo 888d5ac
feat(fzn-rs): Implement array annotation arguments
maartenflippo 10efe95
refactor(fzn-rs): Implement parsing of comments
maartenflippo 3c52b9c
feat(fzn-rs): Parse annotations in variables, arrays, constraints, an…
maartenflippo 1178c9a
feat(fzn-rs): Ignore predicate declarations in flatzinc
maartenflippo ef3c05a
feat(fzn-rs): Allow constraint arguments to be separate structs
maartenflippo 1015e5c
docs(fzn-rs): Add example with constraint args as separate struct
maartenflippo b19b326
refactor(fzn-rs): Replace '_' with '-' in crate names
maartenflippo 127520d
refactor(fzn-rs): Separate annotations for variables, constraints, an…
maartenflippo 3275baa
feat(fzn-rs): Parse annotation arguments in struct
maartenflippo 433c34e
feat(fzn-rs): Implement RangeList::iter for i64 elements
maartenflippo 1e7eff6
feat(fzn-rs): Implement support for i32 as an integer type
maartenflippo 93be6b3
refactor(fzn-rs): Remove redundent function
maartenflippo 4ade384
refactor(fzn-rs): Rename VariableArg to VariableExpr, and use it as t…
maartenflippo e13302f
refactor(fzn-rs): Clean up the implementation into modules + document…
maartenflippo d2a1963
fix(fzn-rs): Fix numerous compiler issues after previous refactor
maartenflippo 6490f87
refactor(fzn-rs): Improve documentation of the API
maartenflippo 345ec0b
refactor(fzn-rs): Remove useless function
maartenflippo 345912d
fix(fzn-rs): Ignore consequtive lines with comments
maartenflippo 8a9d928
feat(fzn-rs): Implement display for token
maartenflippo 2b68ecf
feat(fzn-rs): Check argument length of constraint and provide span in…
maartenflippo fd8253b
docs(fzn-rs): Correct documentation on Ast and clarify the two annota…
maartenflippo e0e0841
refactor(fzn-rs): Use arrayexpr in annotation arguments
maartenflippo 7184bc3
chore(fzn-rs): Remove commented code
maartenflippo 43a9120
refactor: Update cargo.lock
maartenflippo beea64d
feat(fzn-rs): Implement parsing of the domain of array elements
maartenflippo e7202d4
refactor(fzn-rs): Move away from using Rc in errors
maartenflippo ef2b6c7
feat(fzn-rs): Allow access to error values
maartenflippo 2656a36
refactor(fzn-rs): Remove the explicit lexing stage from the fzn parser
maartenflippo 1c2ccaf
Revert "refactor(fzn-rs): Remove the explicit lexing stage from the f…
maartenflippo dfefbe2
docs(fzn-rs): Comments and naming of types
maartenflippo 7d97aaf
refactor(fzn-rs): Update docs
maartenflippo a57c6dc
fix(fzn-rs): Remove cargo features
maartenflippo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| [package] | ||
| name = "fzn-rs-derive" | ||
| version = "0.1.0" | ||
| repository.workspace = true | ||
| edition.workspace = true | ||
| license.workspace = true | ||
| authors.workspace = true | ||
|
|
||
| [lib] | ||
| proc-macro = true | ||
|
|
||
| [dependencies] | ||
| convert_case = "0.8.0" | ||
| proc-macro2 = "1.0.95" | ||
| quote = "1.0.40" | ||
| syn = { version = "2.0.104", features = ["extra-traits"] } | ||
|
|
||
| [dev-dependencies] | ||
| fzn-rs = { path = "../fzn-rs/" } | ||
|
|
||
| [lints] | ||
| workspace = true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| use quote::quote; | ||
|
|
||
| /// Construct a token stream that initialises an annotation with name `value_type` and the arguments | ||
| /// described in `fields`. | ||
| pub(crate) fn initialise_value( | ||
ImkoMarijnissen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| value_type: &syn::Ident, | ||
| fields: &syn::Fields, | ||
| ) -> proc_macro2::TokenStream { | ||
| // For every field, initialise the value for that field. | ||
| let field_values = fields.iter().enumerate().map(|(idx, field)| { | ||
| let ty = &field.ty; | ||
|
|
||
| // If the field has a name, then prepend the field value with the name: `name: value`. | ||
| let value_prefix = if let Some(ident) = &field.ident { | ||
| quote! { #ident: } | ||
| } else { | ||
| quote! {} | ||
| }; | ||
|
|
||
| // If there is an `#[annotation]` attribute on the field, then the value is the result of | ||
| // parsing a nested annotation. Otherwise, we look at the type of the field | ||
| // and parse the value corresponding to that type. | ||
| if field.attrs.iter().any(|attr| { | ||
| attr.path() | ||
| .get_ident() | ||
| .is_some_and(|ident| ident == "annotation") | ||
| }) { | ||
| quote! { | ||
| #value_prefix <#ty as ::fzn_rs::FromNestedAnnotation>::from_argument( | ||
| &arguments[#idx], | ||
| )? | ||
| } | ||
| } else { | ||
| quote! { | ||
| #value_prefix <#ty as ::fzn_rs::FromAnnotationArgument>::from_argument( | ||
| &arguments[#idx], | ||
| )? | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| // Complete the value initialiser by prepending the type name to the field values. | ||
| let value_initialiser = match fields { | ||
| syn::Fields::Named(_) => quote! { #value_type { #(#field_values),* } }, | ||
| syn::Fields::Unnamed(_) => quote! { #value_type ( #(#field_values),* ) }, | ||
| syn::Fields::Unit => quote! { #value_type }, | ||
| }; | ||
|
|
||
| let num_arguments = fields.len(); | ||
|
|
||
| // Output the final initialisation, with checking of number of arguments. | ||
| quote! { | ||
| if arguments.len() != #num_arguments { | ||
| return Err(::fzn_rs::InstanceError::IncorrectNumberOfArguments { | ||
| expected: #num_arguments, | ||
| actual: arguments.len(), | ||
| span: annotation.span, | ||
| }); | ||
| } | ||
|
|
||
| Ok(Some(#value_initialiser)) | ||
| } | ||
| } | ||
|
|
||
| /// Create the parsing code for one annotation corresponding to the given variant. | ||
| pub(crate) fn variant_to_annotation(variant: &syn::Variant) -> proc_macro2::TokenStream { | ||
| // Determine the flatzinc annotation name. | ||
| let name = match crate::common::get_explicit_name(variant) { | ||
| Ok(name) => name, | ||
| Err(_) => { | ||
| return quote! { | ||
| compile_error!("Invalid usage of #[name(...)]"); | ||
| }; | ||
| } | ||
| }; | ||
|
|
||
| let variant_name = &variant.ident; | ||
|
|
||
| // If variant argument is a struct, then delegate parsing of the annotation arguments to that | ||
| // struct. | ||
| if let Some(constraint_type) = crate::common::get_args_type(variant) { | ||
| return quote! { | ||
| ::fzn_rs::ast::Annotation::Call(::fzn_rs::ast::AnnotationCall { | ||
| name, | ||
| arguments, | ||
| }) if name.as_ref() == #name => { | ||
| let args = <#constraint_type as ::fzn_rs::FlatZincAnnotation>::from_ast_required(annotation)?; | ||
| let value = #variant_name(args); | ||
| Ok(Some(value)) | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| // If the variant has no arguments, parse an atom annotaton. Otherwise, initialise the values | ||
| // of the variant arguments. | ||
| if matches!(variant.fields, syn::Fields::Unit) { | ||
| quote! { | ||
| ::fzn_rs::ast::Annotation::Atom(ident) if ident.as_ref() == #name => { | ||
| Ok(Some(#variant_name)) | ||
| } | ||
| } | ||
| } else { | ||
| let value = initialise_value(&variant.ident, &variant.fields); | ||
|
|
||
| quote! { | ||
| ::fzn_rs::ast::Annotation::Call(::fzn_rs::ast::AnnotationCall { | ||
| name, | ||
| arguments, | ||
| }) if name.as_ref() == #name => { | ||
| #value | ||
| } | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.