ANTLR - check semantics/meaning of the values
I have a simple grammar which allows the user to define some objects with attributes. For example:
carpark : my carpark
lots: 100
car: BMW
color: red
wheels: 4
motocycle
age: 4
color: red
carpark : my second carpark
car:...
...
car:...
...
...
I have created a grammar with ANTLR to check those simple assignments.
Now I have problems checking for example the order or the meaning of the assignments. Lets assume I can inherit from an existing carpark
carpark: my third carpark
extends: my second carpark
How should I check if 'my second carpark' already exists?
Further I want some of the attributes like color be optional, others mandatory and the order should not be important
car: BMW
color: red
age: 4
//should be allowed as
car: BMW
age: 4
color: red
A simple rule would be
cardefinition
: CAR COLON value NEWLINE attributedefinition*
;
attributedefinition
: attributekey COLON value NEWLINE!
;
But then mandatory attributes may not be defined. I could add an additional rule like mandatoryattributedefinition but then开发者_如何学Go it is hard to allow definitions in any order
So should this kind of checking be part of the parser or a tree parser
You could do the checking of valid super-parks (extends ...
) inside the parser grammar, but a tree grammar is less cluttered version of your (combined) grammar: so I like to do such stuff in there.
What you could do is create a Set<String> parks
as a member of your tree walker:
tree grammar CarParkWalker;
options {
tokenVocab=CarPark; // assuming your combined grammar is called CarPark.g
ASTLabelType=CommonTree;
}
@members {
private Set<String> parks = new HashSet<String>();
}
// rules here
and then add String
s to it while the AST is traversed. Then when you stumble upon an extends VALUE
, you add some custom code where you check if VALUE.text
is present in your Set<String> parks
. If not, throw an exception.
About mandatory an optional attributes of cars (or car-parks), simply accept zero or more parameters in your (combined) grammar and let your tree grammar rules return a Vehicle
instance:
/* tree grammar rules! */
vehicle returns [Vehicle v]
: car {$v = $car.v;}
| motorcycle {$v = $motorcycle.v;}
;
car returns [Vehicle v]
@init{$v = new Car();}
: ^(Car ... )
;
motorcycle returns [Vehicle v]
@init{$v = new Motorcycle();}
: ^(Motorcycle ... )
;
where a Vehicle
may look like:
abstract class Vehicle {
protected String make;
protected String color;
protected int age;
protected int wheels;
// ...
}
And then check if for each vehicle if all mandatory attributes have been set.
If, after trying yourself, you're having trouble implementing all this, I'm willing to post a little demo of it. Just add a comment in that case.
Good luck!
精彩评论