Closed trolley813 closed 3 years ago
Actually, this is not possible because the Oak compiler needs to access the return type of semantic action to generate the code. What you can do now is to write a kind of "declaration" such that:
// in actions/part2.rs
pub fn action2() -> TypeAction {
// ...
}
// in grammar
grammar! test {
use super::actions::part2::*;
fn forward_action2() -> TypeAction { action2() }
...
I know it's not totally satisfactory, I think the only way to get around is to add type ascription on rules such that you can specify the return type of a rule (actually I tried hard to avoid it since I wanted the grammar to be the clearer as possible.) I do not close it for the moment and will give it more thoughts later.
Could the return type bot just also be declared outside of the grammar macro? And then imported into the module defined by the grammar macro?
When generating the code we need to know the return type of the semantic actions, but the only knowledge we have is what's inside the current macro, so we need a way to communicate this type. The way chosen in Oak is to declare the function inside the macro. Another possible way (not implemented in Oak) could be to allow type annotations on the rule:
r -> usize = digit+ > string_to_usize
and then we don't need the function string_to_usize
to be declared inside the macro. The problem with this approach is that we can have type or arity mismatch that will only be detected when rustc
compiles the generated code. With the current approach, such errors can be detected by Oak and the error messages are on the macro (and not the generated code).
When you write the context actions (such as
e > f
) in the grammar, they actually must be defined (not only declared) inside thegrammar!
macro. But it becomes uncomfortable when the grammar is large (for example, one for a whole programming language may require several tens of actions). So, it's currently impossible to write like this:So, for large grammar, allowing use functions from other modules would be useful.