繁体   English   中英

在antlr语法g4文件中使用Java代码

[英]Using Java code in antlr grammar g4 file

我想定义一个语法来解析与测量单位有关的单词,例如千克:'kg','KG','千克','公斤','l','升','升'等。

我已经在使用Java enum类来执行类似的操作,以验证应该表示度量单位的输入字符串。

我想知道是否可以在ANTLR语法文件中的enum类中重用已定义的度量单位。 基本上我想在.g4语法文件中设置词法分析器 ,如:

UNITS: UnitMeasures.values()

.values()方法返回UnitMeasures枚举Java类中的枚举值,这与ANTLR语法词法分析器“应该是等价的”:

UNITS: ('kg' | 'KG' | 'kilograms' | 'l' | 'litres' | 'liters' );

我试图这样做的原因是:

  • 我想避免枚举Java类和ANTLR语法文件之间的代码重复 ;
  • 我不能只使用ANTLR并删除枚举Java类,因为它已经在很多不同的地方使用过;
  • 现在我试图在一个更复杂的场景中使用度量单位,我需要解析数量,度量单位和其他相关内容,所以我决定使用ANTLR。

有可能以某种方式避免这种代码重复吗?

如果您的程序中尚未存在枚举,我建议根据语法本身生成运行时工件。

由于您已经定义了枚举,因此在使用AbstractParseTreeVisitor完成解析后,让我们实现单元识别。

1)添加units解析器规则并概括你的UNITS词法分析器规则:

...

unit : ID
     ;

...

ID: [a-zA-Z_0-9]+ ; // whatever you want/need 

...

现在你的语法不会复制任何代码,但你的单位规则太笼统了。 我们将在java方面解决这个问题。

2)生成访问者并覆盖visitUnit(UnitContext)

@Override
public Object visitUnit(UnitContext ctx) {

    String unitId = ctx.ID();

    try{ 
         // Next line will throw exception if unitId is not
         // the name of one of your enums.
         UnitMeasures unit = UnitMeasures.valueOf(unitId);

         // do something maybe?

    } catch (IllegalArgumentException(e) {
        throw new RuntimeException("Invalid unit: " + unitId);
    }

    return super.visitUnit(ctx);
}

这将消除任何代码重复。 现在,无论UnitMeasuresUnitMeasures添加新的枚举,您都不必改变语法。 您甚至不需要重新生成解析器。

另一个选项:这将为您的语法添加一个java依赖项,但您可以在unit规则之后添加一些小动作,如果ID不是基于enum的有效单元,则可以做出相应的响应。

unit : ID 
     { 
         try {
             UnitMeasures.valueOf($unit.text);
         }
         catch(IllegalArgumentException e) {
             //report invalid unit
         }
     }
     ;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM