ANTLR - la semantica di controllo / significato dei valori
-
26-10-2019 - |
Domanda
Ho una semplice grammatica che permette all'utente di definire alcuni oggetti con gli attributi. Ad esempio:
carpark : my carpark
lots: 100
car: BMW
color: red
wheels: 4
motocycle
age: 4
color: red
carpark : my second carpark
car:...
...
car:...
...
...
ho creato una grammatica con ANTLR per controllare tali assegnazioni semplici.
Ora ho problemi di controllo, ad esempio l'ordine o il significato delle assegnazioni. Assumiamo che posso ereditare da un parcheggio
esistentecarpark: my third carpark
extends: my second carpark
Come devo controllare se 'il mio secondo parcheggio' esiste già?
Inoltre voglio alcuni degli attributi come il colore è facoltativo, altre obbligatorie e l'ordine non dovrebbe essere importante
car: BMW
color: red
age: 4
//should be allowed as
car: BMW
age: 4
color: red
Una regola semplice sarebbe
cardefinition
: CAR COLON value NEWLINE attributedefinition*
;
attributedefinition
: attributekey COLON value NEWLINE!
;
Ma poi attributi obbligatori non può essere definito. Potrei aggiungere una regola aggiuntiva come mandatoryattributedefinition ma poi è difficile da permettere definizioni in qualsiasi ordine
Quindi, dovrebbe questo tipo di controllo far parte del parser o di un parser albero
Soluzione
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!