我正在尝试学习一点ANTLR4并为某些4GL语言定义语法。
这就是我所拥有的:
compileUnit
:
typedeclaration EOF
;
typedeclaration
:
ID LPAREN DATATYPE INT RPAREN
;
DATATYPE
:
DATATYPE_ALPHANUMERIC
| DATATYPE_NUMERIC
;
DATATYPE_ALPHANUMERIC
:
'A'
;
DATATYPE_NUMERIC
:
'N'
;
fragment
DIGIT
:
[0-9]
;
fragment
LETTER
:
[a-zA-Z]
;
INT
:
DIGIT+
;
ID
:
LETTER
(
LETTER
| DIGIT
)*
;
LPAREN
:
'('
;
RPAREN
:
')'
;
WS
:
[ \t\f]+ -> skip
;
我希望能够解析的内容:
TEST(A10)
我得到了什么:
typedeclaration:1:6:不匹配的输入'A10'期待DATATYPE
但我能够写下:
TEST(A 10)
为什么我需要在这里放一个空格? LPAREN DATATYPE本身正在工作,因此不需要在它们之间留出空间。 INT RPAREN也在工作。 为什么DATATYPE和INT之间需要一个空间?我对那个有点困惑。 我猜它是匹配的ID,因为它是“最长的”匹配,但是必须有一些方法可以让这里更加懒散,对吗?
答案 0 :(得分:1)
你应该在ID的第一个位置忽略'A'和'N'聊天。由于@CoronA注意到ANTLR尽可能地匹配令牌(ID'A10'的长度超过DATATYPE_ALPHANUMERIC'A'的长度)。另请阅读:Priority rules。尝试使用以下语法:
grammar expr;
compileUnit
: typedeclaration EOF
;
typedeclaration
: ID LPAREN datatype INT RPAREN
;
datatype
: DATATYPE_ALPHANUMERIC
| DATATYPE_NUMERIC
;
DATATYPE_ALPHANUMERIC
: 'A'
;
DATATYPE_NUMERIC
: 'N'
;
INT
: DIGIT+
;
ID
: [b-mo-zB-MO-Z] (LETTER | DIGIT)*
;
LPAREN
: '('
;
RPAREN
: ')'
;
WS
: [ \t\f]+ -> skip
;
fragment
DIGIT
: [0-9]
;
fragment
LETTER
: [a-zA-Z]
;
此外,您可以使用以下语法而不受ID限制。数据类型将比字母更早识别。它也不清楚:
grammar expr;
compileUnit
: typedeclaration EOF
;
typedeclaration
: id LPAREN datatype DIGIT+ RPAREN
;
id
: (datatype | LETTER) (datatype | LETTER | DIGIT)*
;
datatype
: DATATYPE_ALPHANUMERIC
| DATATYPE_NUMERIC
;
DATATYPE_ALPHANUMERIC: 'A';
DATATYPE_NUMERIC: 'N';
// List with another Data types.
LETTER: [a-zA-Z];
LPAREN
: '('
;
RPAREN
: ')'
;
WS
: [ \t\f]+ -> skip
;
DIGIT
: [0-9]
;