ANTLR v4 动态文法
ANTLR v4 dynamic grammar
我有这个语法:
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
;
我怎样才能实现同时为同一条目(同一行)注册评论的目标?
EDIT: 如上所述,上面的语法将正确解析第一个示例。但是第二个会坏掉。它会将 or
检测为新的 parameterName
。
通过第二个语法更改,我能够解析 -- J
,而其余部分将被检测为新的 parameterName。
我如何告诉 antlr 按我的意愿解析,或者这是一个限制,我最好告诉用户不要在他的评论中使用空格?
没有你完整的语法,我无法进行真正的测试,但我会尽力为你提出建议。由于您的评论标识符 --
必须是连续的,因此我将该规则编码为:
TEXT: ALPHA | DIGIT;
TEXTS : TEXT*;
COMMENT
: '--' TEXTS
;
类似的东西可以确保您的 --
评论 + 混合文本被词法化为评论。
您的 COMMENT
规则不完整。它只包含评论介绍者,但没有任何内容应该与该行的其余部分相匹配。一个典型的做法是:
SINGLE_LINE_COMMENT: '--' ~([\r\n] | EOF)*;
因为我刚开始使用 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
我有这个语法:
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
;
我怎样才能实现同时为同一条目(同一行)注册评论的目标?
EDIT: 如上所述,上面的语法将正确解析第一个示例。但是第二个会坏掉。它会将 or
检测为新的 parameterName
。
通过第二个语法更改,我能够解析 -- J
,而其余部分将被检测为新的 parameterName。
我如何告诉 antlr 按我的意愿解析,或者这是一个限制,我最好告诉用户不要在他的评论中使用空格?
没有你完整的语法,我无法进行真正的测试,但我会尽力为你提出建议。由于您的评论标识符 --
必须是连续的,因此我将该规则编码为:
TEXT: ALPHA | DIGIT;
TEXTS : TEXT*;
COMMENT
: '--' TEXTS
;
类似的东西可以确保您的 --
评论 + 混合文本被词法化为评论。
您的 COMMENT
规则不完整。它只包含评论介绍者,但没有任何内容应该与该行的其余部分相匹配。一个典型的做法是:
SINGLE_LINE_COMMENT: '--' ~([\r\n] | EOF)*;
因为我刚开始使用 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