ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, or translating structured text or binary files.
I have a use case where I have similar rules which I would like to handle with some common code. Currently I handle this by writing "generic" code that checks the types of the child rules of my current context. I would like to write an interface which would include some fields I know will exist in the generated ParserRuleContext. However, as far as I was able to find there is no way to set a common interface that both those rules would implement.
For example (made up example):
exp1: field ":BOOLEAN";
exp2: field ":STRING";
In some future parser rules I want to allow only exp1, only exp2 and sometimes either. However to reduce code I handle these two expressions (converting to my runtime representation) with generic code. I realize I can merge these two rules and check at runtime if I got the one that is allowed in any given context, but I find it simpler and safer to let the grammar prevent incorrect usages.
I would like to be able to add something like:
exp1: field ":BOOLEAN" {implement com.sompackage.FieldExpression }
exp2: field ":STRING" {implement com.somepackage.FieldExpression }
And then later I could use that interface (which would have a "field" field with the correct ParserRuleContext subtype).
I was unable to find functionality like this. There might be a way to do it by embedding "java" code in my grammar file. However, I use this grammar across Java and Javascript and would like to keep it language neutral (the "implement ..." should generate the correct "extends" depending on the target language. It shouldn't be embedded target language code).
I should also mention that this problem is less of an issue if using a visitor/listener pattern. Since using that pattern I could call a common method with the args extracted from the rule context, it it still has some duplicate code. Also I've found the visitor/listener pattern less suitable for my use case (but it may be worth re-considering at some point).
If there is a way to achieve this that I missed, or if for some reason I'm off track please let me know.
In my case, I generates parser for C#. All output classes are partial, so I can implement any interface for generated classes in non-gerated part of code for any rule I want.
I have a use case where I have similar rules which I would like to handle with some common code. Currently I handle this by writing "generic" code that checks the types of the child rules of my current context. I would like to write an interface which would include some fields I know will exist in the generated ParserRuleContext. However, as far as I was able to find there is no way to set a common interface that both those rules would implement.
For example (made up example):
In some future parser rules I want to allow only exp1, only exp2 and sometimes either. However to reduce code I handle these two expressions (converting to my runtime representation) with generic code. I realize I can merge these two rules and check at runtime if I got the one that is allowed in any given context, but I find it simpler and safer to let the grammar prevent incorrect usages.
I would like to be able to add something like:
And then later I could use that interface (which would have a "field" field with the correct ParserRuleContext subtype).
I was unable to find functionality like this. There might be a way to do it by embedding "java" code in my grammar file. However, I use this grammar across Java and Javascript and would like to keep it language neutral (the "implement ..." should generate the correct "extends" depending on the target language. It shouldn't be embedded target language code).
I should also mention that this problem is less of an issue if using a visitor/listener pattern. Since using that pattern I could call a common method with the args extracted from the rule context, it it still has some duplicate code. Also I've found the visitor/listener pattern less suitable for my use case (but it may be worth re-considering at some point).
If there is a way to achieve this that I missed, or if for some reason I'm off track please let me know.