ANTLR - 检查值的语义/含义

发布于 2024-12-02 21:12:02 字数 844 浏览 5 评论 0原文

我有一个简单的语法,允许用户定义一些带有属性的对象。 例如:

carpark : my carpark
lots: 100

car: BMW
color: red
wheels: 4

motocycle
age: 4
color: red

carpark : my second carpark

car:...
...
car:...
...
...

我使用 ANTLR 创建了一个语法来检查这些简单的作业。

现在我在检查作业的顺序或含义时遇到问题。 假设我可以从现有停车场继承,

carpark: my third carpark
extends: my second carpark

我应该如何检查“我的第二个停车场”是否已经存在?

此外,我希望一些属性(例如颜色)是可选的,其他属性是可选的,其他属性是强制性的,并且顺序不应该很重要

car: BMW
color: red
age: 4
//should be allowed as
car: BMW
age: 4
color: red

一个简单的规则是

cardefinition
    :   CAR COLON value NEWLINE attributedefinition*
    ;

attributedefinition
    :   attributekey COLON value NEWLINE!
    ;

,但是可能不会定义强制性属性。 我可以添加一个额外的规则,例如强制属性定义,但是很难允许以任何顺序进行定义

所以这种检查应该是解析器或树解析器的一部分

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

叶落知秋 2024-12-09 21:12:02

可以在解析器语法中检查有效的超级公园(extends ...),但树语法是(组合)语法的不太混乱的版本:所以我喜欢在那里做这样的事情。

您可以做的是创建一个 Set; Parks 作为您的 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

然后在遍历 AST 时向其中添加 String。然后,当您偶然发现 extends VALUE 时,您可以添加一些自定义代码,检查 VALUE.text 是否存在于您的 Set中。公园。如果不是,则抛出异常。

关于汽车(或停车场)的强制和可选属性,只需在(组合)语法中接受零个或多个参数,并让您的树语法规则返回一个 Vehicle 实例:

/* 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 ... )
  ;

其中 Vehicle 可能如下所示:

abstract class Vehicle {

  protected String make;
  protected String color;
  protected int age;
  protected int wheels;

  // ...
}

然后检查每个车辆是否已设置所有强制属性。

如果您自己尝试后在实现这一切方面遇到困难,我愿意发布一些演示。在这种情况下只需添加评论即可。

祝你好运!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文