سؤال

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 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 Strings 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!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top