ANTLR v4动态语法

时间:2018-02-20 14:44:29

标签: parsing antlr grammar antlr4

我有这个语法:

grammar ProcedureHeaderLanguage ;

@header
{
  package com.company.generated.antlr.atr;
}

fragment DIGIT
  : '0'..'9'
  ;

fragment A
  : [aA]
  ;

fragment B
  : [bB]
  ;

fragment C
  : [cC]
  ;

fragment D
  : [dD]
  ;

fragment E
  : [eE]
  ;

fragment F
  : [fF]
  ;

fragment G
  : [gG]
  ;

fragment H
  : [hH]
  ;

fragment I
  : [iI]
  ;

fragment J
  : [jJ]
  ;

fragment K
  : [kK]
  ;

fragment L
  : [lL]
  ;

fragment M
  : [mM]
  ;

fragment N
  : [nN]
  ;

fragment O
  : [oO]
  ;

fragment P
  : [pP]
  ;

fragment Q
  : [qQ]
  ;

fragment R
  : [rR]
  ;

fragment S
  : [sS]
  ;

fragment T
  : [tT]
  ;

fragment U
  : [uU]
  ;

fragment V
  : [vV]
  ;

fragment W
  : [wW]
  ;

fragment X
  : [xX]
  ;

fragment Y
  : [yY]
  ;

fragment Z
  : [zZ]
  ;

fragment DIGIT_PAIR
  : DIGIT DIGIT
  ;

fragment ALPHA
  : 'a'..'z'
  | 'A'..'Z'
  ;

SEMICOLON
  : ';'
  ;

HYPHEN
  : '-'
  ;

PROCEDURE_IDENTIFIER
  : P R O C E D U R E
  ;

COMMA
  : ','
  ;

LEFT_PARENTHESIS
  : '('
  ;

RIGHT_PARENTHESIS
  : ')'
  ;

dataField
  : IDENTIFIER
  ;

nameField
  : dataField
  ;

parameterNameField
  : dataField
  ;

dataTypeField
  : dataField
  ;

IN
  : I N
  ;

WS
  : (' ' | '\t' | '\r' | '\n')+ -> skip
  ;

IDENTIFIER
  : (ALPHA | '_') (ALPHA | DIGIT | '_')*
  ;

COMMENT
  : HYPHEN HYPHEN
  ;

parameterPair
  : parameterNameField IN dataTypeField
  ;

procedureName
  : PROCEDURE_IDENTIFIER nameField
  ;

procedureParameter
  : LEFT_PARENTHESIS parameterPair (COMMA parameterPair)* RIGHT_PARENTHESIS
  ;

procedure
  : procedureName procedureParameter SEMICOLON
  ;

procedures
  : procedure (procedure)*
  ;

能够解析以下示例:

sorten_COBB_SEK in number,
sorten_COBB_VORG in number,

然而,解析文件不仅包含此类数据。 它还将存储一些可选的而非强制性的信息。 我知道我可以简单地告诉他们?是可选的,但事情并非那么简单。

我还有这个例子:

sorten_FEUCHTE_MIN in number,
sorten_FEUCHTE_MAX in number,
sorten_FEUCHTE_SPERR in number,
sorten_LEIMUNG in varchar2, -- J or N
sorten_BEMERKUNG in varchar2

其中-- J or N与sorten_LEIMUNG条目相关联,我想获取该条目的信息。问题是分隔符COMMA在我要解析的注释之前。

所以这样的语法不起作用:

parameterPair
  : parameterNameField IN dataTypeField COMMA? COMMENT? dataField?
  ;

procedureParameter
  : LEFT_PARENTHESIS parameterPair (parameterPair)* RIGHT_PARENTHESIS
  ;

如何实现为同一条目(同一行)注册评论的目标?

编辑:如上所述,上述语法将正确解析第一个例子。然而,第二个将被打破。它会将or检测为新parameterName。 通过第二次语法更改,我能够解析-- J,而其余的将被检测为新的parameterName。

我如何告诉antlr解析我的意愿,或者这是一个限制,我最好告诉用户不要在他的评论中使用空格?

3 个答案:

答案 0 :(得分:0)

没有你的整个语法,我无法进行真正的测试,但我会尝试为你提出建议。由于您的评论标识符--必须是连续的,因此我将该规则编码为:

TEXT: ALPHA | DIGIT;
TEXTS : TEXT*;

COMMENT
  : '--' TEXTS
  ;

这样可以确保您的--评论+混合文字作为评论获得作为。

答案 1 :(得分:0)

您的COMMENT规则不完整。它只包含评论介绍人,但没有任何内容应与该行的其余部分相匹配。一种典型的方法是:

SINGLE_LINE_COMMENT: '--' ~([\r\n] | EOF)*;

答案 2 :(得分:0)

由于我刚刚开始使用ANTLR,我不知道这是否是最佳解决方案,但是使用语法规则:

SINGLE_LINE_COMMENT
  : '--' (.)*? '\r'? '\n'
  ;

parameterPair
  : parameterNameField IN dataTypeField COMMA? SINGLE_LINE_COMMENT?
  ;

然后我可以在自定义访问者中执行此操作:

/**
     * Filters out the needed informations of the antlr parser context and 
     * creates the POJO {@link SqlParameter} with it.
     *
     * @param parameterPair the parameter pair
     * @return the sql parameter
     */
    private SqlParameter createParameter( ParameterPairContext parameterPair )
    {
      final String parameterName = parameterPair.parameterNameField().getText();
      final String dataType = parameterPair.dataTypeField().getText();
      Optional<String> comment = Optional.empty();
      if ( parameterPair.SINGLE_LINE_COMMENT() != null )
      {
        comment = Optional.ofNullable( parameterPair.SINGLE_LINE_COMMENT().getText().trim() );
      }

      return new SqlParameter( parameterName, dataType, comment );
    }

在所有情况下哪个都不实用,但现在应该做到这一点。将其记录下来将导致我需要的东西:

StringBuilder log = new StringBuilder();
log.append( "Parameter: " );
log.append( parameter.getParameterName() );
log.append( " with type: " );
log.append( parameter.getParameterType() );
parameter.getComment().ifPresent( comment -> log.append( " with comment: " ).append( comment ) );
>>>>>>>>>>>>>>>>>>>>>>>>>>>
Parameter: sorten_FEUCHTE_SPERR with type: number
Parameter: sorten_LEIMUNG with type: varchar2 with comment: -- J or N
Parameter: sorten_BEMERKUNG with type: varchar2